aboutsummaryrefslogtreecommitdiffstats
path: root/packages/instant/src/components/ui
diff options
context:
space:
mode:
authorfragosti <francesco.agosti93@gmail.com>2018-11-08 12:30:45 +0800
committerfragosti <francesco.agosti93@gmail.com>2018-11-08 12:30:45 +0800
commitc0d8ceca82a91a3a6c222e71ecb58f2cd95da62e (patch)
treeb23979fe0389a2644ea9ada3a6b195c38a4e6147 /packages/instant/src/components/ui
parent95b2898b9c0898c7e2d98ee603bff0604bf2a829 (diff)
downloaddexon-0x-contracts-c0d8ceca82a91a3a6c222e71ecb58f2cd95da62e.tar.gz
dexon-0x-contracts-c0d8ceca82a91a3a6c222e71ecb58f2cd95da62e.tar.zst
dexon-0x-contracts-c0d8ceca82a91a3a6c222e71ecb58f2cd95da62e.zip
feat: implement basic dropdown component
Diffstat (limited to 'packages/instant/src/components/ui')
-rw-r--r--packages/instant/src/components/ui/dropdown.tsx127
-rw-r--r--packages/instant/src/components/ui/icon.tsx9
2 files changed, 132 insertions, 4 deletions
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)};