diff options
author | fragosti <francesco.agosti93@gmail.com> | 2018-11-08 12:30:45 +0800 |
---|---|---|
committer | fragosti <francesco.agosti93@gmail.com> | 2018-11-08 12:30:45 +0800 |
commit | c0d8ceca82a91a3a6c222e71ecb58f2cd95da62e (patch) | |
tree | b23979fe0389a2644ea9ada3a6b195c38a4e6147 /packages/instant/src/components | |
parent | 95b2898b9c0898c7e2d98ee603bff0604bf2a829 (diff) | |
download | dexon-sol-tools-c0d8ceca82a91a3a6c222e71ecb58f2cd95da62e.tar.gz dexon-sol-tools-c0d8ceca82a91a3a6c222e71ecb58f2cd95da62e.tar.zst dexon-sol-tools-c0d8ceca82a91a3a6c222e71ecb58f2cd95da62e.zip |
feat: implement basic dropdown component
Diffstat (limited to 'packages/instant/src/components')
5 files changed, 167 insertions, 7 deletions
diff --git a/packages/instant/src/components/erc20_asset_amount_input.tsx b/packages/instant/src/components/erc20_asset_amount_input.tsx index f21c21b87..520ac33d5 100644 --- a/packages/instant/src/components/erc20_asset_amount_input.tsx +++ b/packages/instant/src/components/erc20_asset_amount_input.tsx @@ -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> ); }; diff --git a/packages/instant/src/components/payment_method.tsx b/packages/instant/src/components/payment_method.tsx new file mode 100644 index 000000000..125b54bad --- /dev/null +++ b/packages/instant/src/components/payment_method.tsx @@ -0,0 +1,31 @@ +import * as _ from 'lodash'; +import * as React from 'react'; + +import { ColorOption } from '../style/theme'; + +import { Container } from './ui/container'; +import { Dropdown } from './ui/dropdown'; +import { Text } from './ui/text'; + +export interface PaymentMethodProps {} + +export class PaymentMethod extends React.Component<PaymentMethodProps> { + public render(): React.ReactNode { + return ( + <Container padding="20px" width="100%"> + <Container marginBottom="10px"> + <Text + letterSpacing="1px" + fontColor={ColorOption.primaryColor} + fontWeight={600} + textTransform="uppercase" + fontSize="14px" + > + Payment Method + </Text> + </Container> + <Dropdown value="0x00000000000000" label="25.33 ETH" /> + </Container> + ); + } +} diff --git a/packages/instant/src/components/ui/dropdown.tsx b/packages/instant/src/components/ui/dropdown.tsx new file mode 100644 index 000000000..2bc552ab4 --- /dev/null +++ b/packages/instant/src/components/ui/dropdown.tsx @@ -0,0 +1,127 @@ +import * as _ from 'lodash'; +import * as React from 'react'; + +import { ColorOption } from '../../style/theme'; +import { zIndex } from '../../style/z_index'; + +import { Container } from './container'; +import { Flex } from './flex'; +import { Icon } from './icon'; +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: [ + { + text: 'Item 1', + }, + { + text: 'Item 2', + }, + ], + }; + 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 ( + <Container position="relative"> + <Container + cursor={hasItems ? 'pointer' : undefined} + onClick={this._handleDropdownClick} + hasBoxShadow={true} + borderRadius={borderRadius} + border="1px solid" + borderColor={ColorOption.feintGrey} + padding="0.8em" + borderBottom="1px solid" + > + <Flex justify="space-between"> + <Text fontSize="16px" lineHeight="19px" fontColor={ColorOption.darkGrey}> + {value} + </Text> + <Container> + <Text fontSize="16px" lineHeight="17px" 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> + ); + } + 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>{text}</Text> + </Container> +); diff --git a/packages/instant/src/components/ui/icon.tsx b/packages/instant/src/components/ui/icon.tsx index 94ea26900..707aee24f 100644 --- a/packages/instant/src/components/ui/icon.tsx +++ b/packages/instant/src/components/ui/icon.tsx @@ -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} @@ -101,7 +101,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)}; diff --git a/packages/instant/src/components/zero_ex_instant_container.tsx b/packages/instant/src/components/zero_ex_instant_container.tsx index 851dfa2db..0543a8e4e 100644 --- a/packages/instant/src/components/zero_ex_instant_container.tsx +++ b/packages/instant/src/components/zero_ex_instant_container.tsx @@ -3,15 +3,15 @@ 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'; import { SlideAnimationState } from './animations/slide_animation'; +import { PaymentMethod } from './payment_method'; import { SlidingPanel } from './sliding_panel'; import { Container } from './ui/container'; import { Flex } from './ui/flex'; @@ -41,6 +41,7 @@ export class ZeroExInstantContainer extends React.Component<ZeroExInstantContain > <Flex direction="column" justify="flex-start"> <SelectedAssetInstantHeading onSelectAssetClick={this._handleSymbolClick} /> + <PaymentMethod /> <SelectedAssetBuyOrderProgress /> <LatestBuyQuoteOrderDetails /> <Container padding="20px" width="100%"> |