Merge pull request #1230 from 0xProject/feature/instant/dropdown-ui
[instant] Dropdown Component Skeleton
This commit is contained in:
@@ -54,6 +54,7 @@
|
||||
"@0x/typescript-typings": "^3.0.3",
|
||||
"@0x/utils": "^2.0.3",
|
||||
"@0x/web3-wrapper": "^3.1.0",
|
||||
"copy-to-clipboard": "^3.0.8",
|
||||
"ethereum-types": "^1.1.1",
|
||||
"lodash": "^4.17.10",
|
||||
"polished": "^2.2.0",
|
||||
|
||||
@@ -77,6 +77,7 @@ const generatePositionAnimationCss = (positionSettings: PositionAnimationSetting
|
||||
export interface PositionAnimationProps {
|
||||
positionSettings: OptionallyScreenSpecific<PositionAnimationSettings>;
|
||||
zIndex?: OptionallyScreenSpecific<number>;
|
||||
height?: string;
|
||||
}
|
||||
|
||||
const defaultAnimation = (positionSettings: OptionallyScreenSpecific<PositionAnimationSettings>) => {
|
||||
@@ -104,5 +105,6 @@ export const PositionAnimation =
|
||||
${props => animationForSize(props.positionSettings, 'sm', media.small)}
|
||||
${props => animationForSize(props.positionSettings, 'md', media.medium)}
|
||||
${props => animationForSize(props.positionSettings, 'lg', media.large)}
|
||||
${props => (props.height ? `height: ${props.height};` : '')}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -10,6 +10,7 @@ export interface SlideAnimationProps {
|
||||
slideInSettings: OptionallyScreenSpecific<PositionAnimationSettings>;
|
||||
slideOutSettings: OptionallyScreenSpecific<PositionAnimationSettings>;
|
||||
zIndex?: OptionallyScreenSpecific<number>;
|
||||
height?: string;
|
||||
}
|
||||
|
||||
export const SlideAnimation: React.StatelessComponent<SlideAnimationProps> = props => {
|
||||
@@ -18,7 +19,7 @@ export const SlideAnimation: React.StatelessComponent<SlideAnimationProps> = pro
|
||||
}
|
||||
const positionSettings = props.animationState === 'slidIn' ? props.slideInSettings : props.slideOutSettings;
|
||||
return (
|
||||
<PositionAnimation positionSettings={positionSettings} zIndex={props.zIndex}>
|
||||
<PositionAnimation height={props.height} positionSettings={positionSettings} zIndex={props.zIndex}>
|
||||
{props.children}
|
||||
</PositionAnimation>
|
||||
);
|
||||
|
||||
@@ -27,7 +27,6 @@ export const CSSReset = createGlobalStyle`
|
||||
text-align: left;
|
||||
text-decoration: none;
|
||||
vertical-align: baseline;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -113,7 +113,7 @@ export class ERC20AssetAmountInput extends React.Component<ERC20AssetAmountInput
|
||||
}
|
||||
return (
|
||||
<Container marginLeft="5px">
|
||||
<Icon icon="chevron" width={12} onClick={this._handleSelectAssetClick} />
|
||||
<Icon icon="chevron" width={12} stroke={ColorOption.white} onClick={this._handleSelectAssetClick} />
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -28,14 +28,14 @@ export class ERC20TokenSelector extends React.Component<ERC20TokenSelectorProps>
|
||||
public render(): React.ReactNode {
|
||||
const { tokens, onTokenSelect } = this.props;
|
||||
return (
|
||||
<Container>
|
||||
<Container height="100%">
|
||||
<SearchInput
|
||||
placeholder="Search tokens..."
|
||||
width="100%"
|
||||
value={this.state.searchQuery}
|
||||
onChange={this._handleSearchInputChange}
|
||||
/>
|
||||
<Container overflow="scroll" height={{ default: '275px', sm: '75vh' }} marginTop="10px">
|
||||
<Container overflow="scroll" height="calc(100% - 80px)" marginTop="10px">
|
||||
{_.map(tokens, token => {
|
||||
if (!this._isTokenQueryMatch(token)) {
|
||||
return null;
|
||||
@@ -85,7 +85,7 @@ class TokenSelectorRow extends React.Component<TokenSelectorRowProps> {
|
||||
<Container marginLeft="5px">
|
||||
<Flex justify="flex-start">
|
||||
<Container marginRight="10px">
|
||||
<Circle diameter={30} fillColor={token.metaData.primaryColor}>
|
||||
<Circle diameter={30} rawColor={token.metaData.primaryColor}>
|
||||
<Flex height="100%">
|
||||
<Text fontColor={ColorOption.white} fontSize="8px">
|
||||
{displaySymbol}
|
||||
|
||||
45
packages/instant/src/components/payment_method.tsx
Normal file
45
packages/instant/src/components/payment_method.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { ColorOption } from '../style/theme';
|
||||
import { Network } from '../types';
|
||||
|
||||
import { PaymentMethodDropdown } from './payment_method_dropdown';
|
||||
import { Circle } from './ui/circle';
|
||||
import { Container } from './ui/container';
|
||||
import { Flex } from './ui/flex';
|
||||
import { Text } from './ui/text';
|
||||
|
||||
export interface PaymentMethodProps {}
|
||||
|
||||
export const PaymentMethod: React.StatelessComponent<PaymentMethodProps> = () => (
|
||||
<Container padding="20px" width="100%">
|
||||
<Container marginBottom="10px">
|
||||
<Flex justify="space-between">
|
||||
<Text
|
||||
letterSpacing="1px"
|
||||
fontColor={ColorOption.primaryColor}
|
||||
fontWeight={600}
|
||||
textTransform="uppercase"
|
||||
fontSize="14px"
|
||||
>
|
||||
Payment Method
|
||||
</Text>
|
||||
<Flex>
|
||||
<Circle color={ColorOption.green} diameter={8} />
|
||||
<Container marginLeft="3px">
|
||||
<Text fontColor={ColorOption.darkGrey} fontSize="12px">
|
||||
MetaMask
|
||||
</Text>
|
||||
</Container>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Container>
|
||||
<PaymentMethodDropdown
|
||||
accountAddress="0xa1b2c3d4e5f6g7h8j9k10"
|
||||
accountEthBalanceInWei={new BigNumber(10500000000000000000)}
|
||||
network={Network.Mainnet}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
44
packages/instant/src/components/payment_method_dropdown.tsx
Normal file
44
packages/instant/src/components/payment_method_dropdown.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import * as React from 'react';
|
||||
|
||||
import { Network } from '../types';
|
||||
import { etherscanUtil } from '../util/etherscan';
|
||||
import { format } from '../util/format';
|
||||
|
||||
import { Dropdown, DropdownItemConfig } from './ui/dropdown';
|
||||
|
||||
export interface PaymentMethodDropdownProps {
|
||||
accountAddress: string;
|
||||
accountEthBalanceInWei?: BigNumber;
|
||||
network: Network;
|
||||
}
|
||||
|
||||
export class PaymentMethodDropdown extends React.Component<PaymentMethodDropdownProps> {
|
||||
public render(): React.ReactNode {
|
||||
const { accountAddress, accountEthBalanceInWei } = this.props;
|
||||
const value = format.ethAddress(accountAddress);
|
||||
const label = format.ethBaseAmount(accountEthBalanceInWei, 4, '') as string;
|
||||
return <Dropdown value={value} label={label} items={this._getDropdownItemConfigs()} />;
|
||||
}
|
||||
private readonly _getDropdownItemConfigs = (): DropdownItemConfig[] => {
|
||||
const viewOnEtherscan = {
|
||||
text: 'View on Etherscan',
|
||||
onClick: this._handleEtherscanClick,
|
||||
};
|
||||
const copyAddressToClipboard = {
|
||||
text: 'Copy address to clipboard',
|
||||
onClick: this._handleCopyToClipboardClick,
|
||||
};
|
||||
return [viewOnEtherscan, copyAddressToClipboard];
|
||||
};
|
||||
private readonly _handleEtherscanClick = (): void => {
|
||||
const { accountAddress, network } = this.props;
|
||||
const etherscanUrl = etherscanUtil.getEtherScanEthAddressIfExists(accountAddress, network);
|
||||
window.open(etherscanUrl, '_blank');
|
||||
};
|
||||
private readonly _handleCopyToClipboardClick = (): void => {
|
||||
const { accountAddress } = this.props;
|
||||
copy(accountAddress);
|
||||
};
|
||||
}
|
||||
@@ -86,7 +86,7 @@ export const SlidingError: React.StatelessComponent<SlidingErrorProps> = props =
|
||||
<SlideAnimation
|
||||
slideInSettings={slideUpSettings}
|
||||
slideOutSettings={slideOutSettings}
|
||||
zIndex={{ sm: zIndex.errorPopUp, default: zIndex.errorPopBehind }}
|
||||
zIndex={{ sm: zIndex.errorPopup, default: zIndex.errorPopBehind }}
|
||||
animationState={props.animationState}
|
||||
>
|
||||
<Error icon={props.icon} message={props.message} />
|
||||
|
||||
@@ -30,7 +30,9 @@ export const Panel: React.StatelessComponent<PanelProps> = ({ title, children, o
|
||||
<Icon width={12} color={ColorOption.lightGrey} icon="closeX" onClick={onClose} />
|
||||
</Container>
|
||||
</Flex>
|
||||
<Container marginTop="10px">{children}</Container>
|
||||
<Container marginTop="10px" height="100%">
|
||||
{children}
|
||||
</Container>
|
||||
</Container>
|
||||
);
|
||||
|
||||
@@ -67,6 +69,7 @@ export const SlidingPanel: React.StatelessComponent<SlidingPanelProps> = props =
|
||||
slideInSettings={slideUpSettings}
|
||||
slideOutSettings={slideDownSettings}
|
||||
animationState={animationState}
|
||||
height="100%"
|
||||
>
|
||||
<Panel {...rest} />
|
||||
</SlideAnimation>
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
import { styled } from '../../style/theme';
|
||||
import { ColorOption, styled, Theme, withTheme } from '../../style/theme';
|
||||
|
||||
export interface CircleProps {
|
||||
diameter: number;
|
||||
fillColor?: string;
|
||||
rawColor?: string;
|
||||
color?: ColorOption;
|
||||
theme: Theme;
|
||||
}
|
||||
|
||||
export const Circle =
|
||||
export const Circle = withTheme(
|
||||
styled.div <
|
||||
CircleProps >
|
||||
`
|
||||
CircleProps >
|
||||
`
|
||||
&& {
|
||||
width: ${props => props.diameter}px;
|
||||
height: ${props => props.diameter}px;
|
||||
background-color: ${props => props.fillColor};
|
||||
background-color: ${props => (props.rawColor ? props.rawColor : props.theme[props.color || ColorOption.white])};
|
||||
border-radius: 50%;
|
||||
}
|
||||
`;
|
||||
`,
|
||||
);
|
||||
|
||||
Circle.displayName = 'Circle';
|
||||
|
||||
Circle.defaultProps = {
|
||||
fillColor: 'white',
|
||||
color: ColorOption.white,
|
||||
};
|
||||
|
||||
@@ -34,6 +34,7 @@ export interface ContainerProps {
|
||||
cursor?: string;
|
||||
overflow?: string;
|
||||
darkenOnHover?: boolean;
|
||||
boxShadowOnHover?: boolean;
|
||||
flexGrow?: string | number;
|
||||
}
|
||||
|
||||
@@ -42,7 +43,6 @@ export const Container =
|
||||
ContainerProps >
|
||||
`
|
||||
&& {
|
||||
all: initial;
|
||||
box-sizing: border-box;
|
||||
${props => cssRuleIfExists(props, 'flex-grow')}
|
||||
${props => cssRuleIfExists(props, 'position')}
|
||||
@@ -79,6 +79,7 @@ export const Container =
|
||||
props.backgroundColor ? darken(0.05, props.theme[props.backgroundColor]) : 'none'
|
||||
}`
|
||||
: ''};
|
||||
${props => (props.boxShadowOnHover ? 'box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1)' : '')};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
134
packages/instant/src/components/ui/dropdown.tsx
Normal file
134
packages/instant/src/components/ui/dropdown.tsx
Normal file
@@ -0,0 +1,134 @@
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { ColorOption, completelyTransparent } from '../../style/theme';
|
||||
import { zIndex } from '../../style/z_index';
|
||||
|
||||
import { Container } from './container';
|
||||
import { Flex } from './flex';
|
||||
import { Icon } from './icon';
|
||||
import { Overlay } from './overlay';
|
||||
import { Text } from './text';
|
||||
|
||||
export interface DropdownItemConfig {
|
||||
text: string;
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
export interface DropdownProps {
|
||||
value: string;
|
||||
label?: string;
|
||||
items: DropdownItemConfig[];
|
||||
}
|
||||
|
||||
export interface DropdownState {
|
||||
isOpen: boolean;
|
||||
}
|
||||
|
||||
export class Dropdown extends React.Component<DropdownProps, DropdownState> {
|
||||
public static defaultProps = {
|
||||
items: [],
|
||||
};
|
||||
public state: DropdownState = {
|
||||
isOpen: false,
|
||||
};
|
||||
public render(): React.ReactNode {
|
||||
const { value, label, items } = this.props;
|
||||
const { isOpen } = this.state;
|
||||
const hasItems = !_.isEmpty(items);
|
||||
const borderRadius = isOpen ? '4px 4px 0px 0px' : '4px';
|
||||
return (
|
||||
<React.Fragment>
|
||||
{isOpen && (
|
||||
<Overlay
|
||||
zIndex={zIndex.dropdownItems - 1}
|
||||
backgroundColor={completelyTransparent}
|
||||
onClick={this._closeDropdown}
|
||||
/>
|
||||
)}
|
||||
<Container position="relative">
|
||||
<Container
|
||||
cursor={hasItems ? 'pointer' : undefined}
|
||||
onClick={this._handleDropdownClick}
|
||||
hasBoxShadow={isOpen}
|
||||
boxShadowOnHover={true}
|
||||
borderRadius={borderRadius}
|
||||
border="1px solid"
|
||||
borderColor={ColorOption.feintGrey}
|
||||
padding="0.8em"
|
||||
>
|
||||
<Flex justify="space-between">
|
||||
<Text fontSize="16px" fontColor={ColorOption.darkGrey}>
|
||||
{value}
|
||||
</Text>
|
||||
<Container>
|
||||
{label && (
|
||||
<Text fontSize="16px" fontColor={ColorOption.lightGrey}>
|
||||
{label}
|
||||
</Text>
|
||||
)}
|
||||
{hasItems && (
|
||||
<Container marginLeft="5px" display="inline-block" position="relative" bottom="2px">
|
||||
<Icon padding="3px" icon="chevron" width={12} stroke={ColorOption.grey} />
|
||||
</Container>
|
||||
)}
|
||||
</Container>
|
||||
</Flex>
|
||||
</Container>
|
||||
{isOpen && (
|
||||
<Container
|
||||
width="100%"
|
||||
position="absolute"
|
||||
onClick={this._closeDropdown}
|
||||
backgroundColor={ColorOption.white}
|
||||
hasBoxShadow={true}
|
||||
zIndex={zIndex.dropdownItems}
|
||||
>
|
||||
{_.map(items, (item, index) => (
|
||||
<DropdownItem key={item.text} {...item} isLast={index === items.length - 1} />
|
||||
))}
|
||||
</Container>
|
||||
)}
|
||||
</Container>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
private readonly _handleDropdownClick = (): void => {
|
||||
if (_.isEmpty(this.props.items)) {
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
isOpen: !this.state.isOpen,
|
||||
});
|
||||
};
|
||||
private readonly _closeDropdown = (): void => {
|
||||
this.setState({
|
||||
isOpen: false,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export interface DropdownItemProps extends DropdownItemConfig {
|
||||
text: string;
|
||||
onClick?: () => void;
|
||||
isLast: boolean;
|
||||
}
|
||||
|
||||
export const DropdownItem: React.StatelessComponent<DropdownItemProps> = ({ text, onClick, isLast }) => (
|
||||
<Container
|
||||
onClick={onClick}
|
||||
cursor="pointer"
|
||||
darkenOnHover={true}
|
||||
backgroundColor={ColorOption.white}
|
||||
padding="0.8em"
|
||||
borderTop="0"
|
||||
border="1px solid"
|
||||
borderRadius={isLast ? '0px 0px 4px 4px' : undefined}
|
||||
width="100%"
|
||||
borderColor={ColorOption.feintGrey}
|
||||
>
|
||||
<Text fontSize="14px" fontColor={ColorOption.darkGrey}>
|
||||
{text}
|
||||
</Text>
|
||||
</Container>
|
||||
);
|
||||
@@ -19,7 +19,6 @@ export const Flex =
|
||||
FlexProps >
|
||||
`
|
||||
&& {
|
||||
all: initial;
|
||||
display: ${props => (props.inline ? 'inline-flex' : 'flex')};
|
||||
flex-direction: ${props => props.direction};
|
||||
flex-wrap: ${props => props.flexWrap};
|
||||
|
||||
@@ -9,7 +9,6 @@ interface IconInfo {
|
||||
path: string;
|
||||
fillRule?: svgRule;
|
||||
clipRule?: svgRule;
|
||||
stroke?: string;
|
||||
strokeOpacity?: number;
|
||||
strokeWidth?: number;
|
||||
strokeLinecap?: 'butt' | 'round' | 'square' | 'inherit';
|
||||
@@ -47,7 +46,6 @@ const ICONS: IconInfoMapping = {
|
||||
chevron: {
|
||||
viewBox: '0 0 12 7',
|
||||
path: 'M11 1L6 6L1 1',
|
||||
stroke: 'white',
|
||||
strokeOpacity: 0.5,
|
||||
strokeWidth: 1.5,
|
||||
strokeLinecap: 'round',
|
||||
@@ -67,6 +65,7 @@ export interface IconProps {
|
||||
width: number;
|
||||
height?: number;
|
||||
color?: ColorOption;
|
||||
stroke?: ColorOption;
|
||||
icon: keyof IconInfoMapping;
|
||||
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
||||
padding?: string;
|
||||
@@ -75,6 +74,7 @@ export interface IconProps {
|
||||
const PlainIcon: React.StatelessComponent<IconProps> = props => {
|
||||
const iconInfo = ICONS[props.icon];
|
||||
const colorValue = _.isUndefined(props.color) ? undefined : props.theme[props.color];
|
||||
const strokeValue = _.isUndefined(props.stroke) ? undefined : props.theme[props.stroke];
|
||||
return (
|
||||
<div onClick={props.onClick} className={props.className}>
|
||||
<svg
|
||||
@@ -89,7 +89,7 @@ const PlainIcon: React.StatelessComponent<IconProps> = props => {
|
||||
fill={colorValue}
|
||||
fillRule={iconInfo.fillRule || 'nonzero'}
|
||||
clipRule={iconInfo.clipRule || 'nonzero'}
|
||||
stroke={iconInfo.stroke}
|
||||
stroke={strokeValue}
|
||||
strokeOpacity={iconInfo.strokeOpacity}
|
||||
strokeWidth={iconInfo.strokeWidth}
|
||||
strokeLinecap={iconInfo.strokeLinecap}
|
||||
@@ -102,7 +102,8 @@ const PlainIcon: React.StatelessComponent<IconProps> = props => {
|
||||
|
||||
export const Icon = withTheme(styled(PlainIcon)`
|
||||
&& {
|
||||
cursor: ${props => (!_.isUndefined(props.onClick) ? 'pointer' : 'default')};
|
||||
display: inline-block;
|
||||
${props => (!_.isUndefined(props.onClick) ? 'cursor: pointer' : '')};
|
||||
transition: opacity 0.5s ease;
|
||||
padding: ${props => props.padding};
|
||||
opacity: ${props => (!_.isUndefined(props.onClick) ? 0.7 : 1)};
|
||||
|
||||
@@ -1,29 +1,17 @@
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
|
||||
import { ColorOption, overlayBlack, styled } from '../../style/theme';
|
||||
|
||||
import { Container } from './container';
|
||||
import { Flex } from './flex';
|
||||
import { Icon } from './icon';
|
||||
import { overlayBlack, styled } from '../../style/theme';
|
||||
import { zIndex } from '../../style/z_index';
|
||||
|
||||
export interface OverlayProps {
|
||||
className?: string;
|
||||
onClose?: () => void;
|
||||
zIndex?: number;
|
||||
backgroundColor?: string;
|
||||
}
|
||||
|
||||
const PlainOverlay: React.StatelessComponent<OverlayProps> = ({ children, className, onClose }) => (
|
||||
<Flex height="100vh" className={className}>
|
||||
<Container position="absolute" top="0px" right="0px" display={{ default: 'initial', sm: 'none' }}>
|
||||
<Icon height={18} width={18} color={ColorOption.white} icon="closeX" onClick={onClose} padding="2em 2em" />
|
||||
</Container>
|
||||
<Container width={{ default: 'auto', sm: '100%' }} height={{ default: 'auto', sm: '100%' }}>
|
||||
{children}
|
||||
</Container>
|
||||
</Flex>
|
||||
);
|
||||
export const Overlay = styled(PlainOverlay)`
|
||||
export const Overlay =
|
||||
styled.div <
|
||||
OverlayProps >
|
||||
`
|
||||
&& {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
@@ -31,12 +19,13 @@ export const Overlay = styled(PlainOverlay)`
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: ${props => props.zIndex}
|
||||
background-color: ${overlayBlack};
|
||||
background-color: ${props => props.backgroundColor};
|
||||
}
|
||||
`;
|
||||
|
||||
Overlay.defaultProps = {
|
||||
zIndex: 100,
|
||||
zIndex: zIndex.overlayDefault,
|
||||
backgroundColor: overlayBlack,
|
||||
};
|
||||
|
||||
Overlay.displayName = 'Overlay';
|
||||
|
||||
@@ -28,7 +28,6 @@ export const Text =
|
||||
TextProps >
|
||||
`
|
||||
&& {
|
||||
all: initial;
|
||||
font-family: 'Inter UI', sans-serif;
|
||||
font-style: ${props => props.fontStyle};
|
||||
font-weight: ${props => props.fontWeight};
|
||||
|
||||
@@ -3,11 +3,9 @@ import * as React from 'react';
|
||||
import { AvailableERC20TokenSelector } from '../containers/available_erc20_token_selector';
|
||||
import { LatestBuyQuoteOrderDetails } from '../containers/latest_buy_quote_order_details';
|
||||
import { LatestError } from '../containers/latest_error';
|
||||
import { SelectedAssetBuyOrderProgress } from '../containers/selected_asset_buy_order_progress';
|
||||
import { SelectedAssetBuyOrderStateButtons } from '../containers/selected_asset_buy_order_state_buttons';
|
||||
import { SelectedAssetInstantHeading } from '../containers/selected_asset_instant_heading';
|
||||
|
||||
import { SelectedAssetBuyOrderProgress } from '../containers/selected_asset_buy_order_progress';
|
||||
|
||||
import { ColorOption } from '../style/theme';
|
||||
import { zIndex } from '../style/z_index';
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { ColorOption } from '../style/theme';
|
||||
|
||||
import { Container } from './ui/container';
|
||||
import { Flex } from './ui/flex';
|
||||
import { Icon } from './ui/icon';
|
||||
import { Overlay } from './ui/overlay';
|
||||
import { ZeroExInstantContainer } from './zero_ex_instant_container';
|
||||
import { ZeroExInstantProvider, ZeroExInstantProviderProps } from './zero_ex_instant_provider';
|
||||
@@ -13,8 +18,22 @@ export const ZeroExInstantOverlay: React.StatelessComponent<ZeroExInstantOverlay
|
||||
const { onClose, zIndex, ...rest } = props;
|
||||
return (
|
||||
<ZeroExInstantProvider {...rest}>
|
||||
<Overlay onClose={onClose} zIndex={zIndex}>
|
||||
<ZeroExInstantContainer />
|
||||
<Overlay zIndex={zIndex}>
|
||||
<Flex height="100vh">
|
||||
<Container position="absolute" top="0px" right="0px" display={{ default: 'initial', sm: 'none' }}>
|
||||
<Icon
|
||||
height={18}
|
||||
width={18}
|
||||
color={ColorOption.white}
|
||||
icon="closeX"
|
||||
onClick={onClose}
|
||||
padding="2em 2em"
|
||||
/>
|
||||
</Container>
|
||||
<Container width={{ default: 'auto', sm: '100%' }} height={{ default: 'auto', sm: '100%' }}>
|
||||
<ZeroExInstantContainer />
|
||||
</Container>
|
||||
</Flex>
|
||||
</Overlay>
|
||||
</ZeroExInstantProvider>
|
||||
);
|
||||
|
||||
@@ -15,6 +15,8 @@ export enum ColorOption {
|
||||
white = 'white',
|
||||
lightOrange = 'lightOrange',
|
||||
darkOrange = 'darkOrange',
|
||||
green = 'green',
|
||||
red = 'red',
|
||||
}
|
||||
|
||||
export const theme: Theme = {
|
||||
@@ -28,9 +30,12 @@ export const theme: Theme = {
|
||||
white: 'white',
|
||||
lightOrange: '#F9F2ED',
|
||||
darkOrange: '#F2994C',
|
||||
green: '#3CB34F',
|
||||
red: '#D00000',
|
||||
};
|
||||
|
||||
export const transparentWhite = 'rgba(255,255,255,0.3)';
|
||||
export const overlayBlack = 'rgba(0, 0, 0, 0.6)';
|
||||
export const completelyTransparent = 'rga(0, 0, 0, 0)';
|
||||
|
||||
export { styled, css, keyframes, withTheme, createGlobalStyle, ThemeProvider };
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
export const zIndex = {
|
||||
errorPopBehind: 1,
|
||||
mainContainer: 2,
|
||||
panel: 3,
|
||||
errorPopUp: 4,
|
||||
errorPopBehind: 10,
|
||||
mainContainer: 20,
|
||||
dropdownItems: 30,
|
||||
panel: 40,
|
||||
errorPopup: 50,
|
||||
overlayDefault: 100,
|
||||
};
|
||||
|
||||
@@ -21,4 +21,11 @@ export const etherscanUtil = {
|
||||
}
|
||||
return `https://${prefix}etherscan.io/tx/${txHash}`;
|
||||
},
|
||||
getEtherScanEthAddressIfExists: (ethAddress: string, networkId: number) => {
|
||||
const prefix = etherscanPrefix(networkId);
|
||||
if (_.isUndefined(prefix)) {
|
||||
return;
|
||||
}
|
||||
return `https://${prefix}etherscan.io/address/${ethAddress}`;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -50,4 +50,7 @@ export const format = {
|
||||
}
|
||||
return `$${ethUnitAmount.mul(ethUsdPrice).toFixed(decimalPlaces)}`;
|
||||
},
|
||||
ethAddress: (address: string): string => {
|
||||
return `0x${address.slice(2, 7)}…${address.slice(-5)}`;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -4395,6 +4395,12 @@ copy-to-clipboard@^3:
|
||||
dependencies:
|
||||
toggle-selection "^1.0.3"
|
||||
|
||||
copy-to-clipboard@^3.0.8:
|
||||
version "3.0.8"
|
||||
resolved "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.0.8.tgz#f4e82f4a8830dce4666b7eb8ded0c9bcc313aba9"
|
||||
dependencies:
|
||||
toggle-selection "^1.0.3"
|
||||
|
||||
copyfiles@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-2.0.0.tgz#bbd78bb78e8fd6db5c67adf54249317b24560f2a"
|
||||
|
||||
Reference in New Issue
Block a user