aboutsummaryrefslogtreecommitdiffstats
path: root/packages/instant/src/components/ui
diff options
context:
space:
mode:
authorFrancesco Agosti <francesco.agosti93@gmail.com>2018-11-09 08:29:34 +0800
committerGitHub <noreply@github.com>2018-11-09 08:29:34 +0800
commit3eac119399d3e2729ce65f748d9fb31207ac2540 (patch)
tree558aa4bb76eae3418cf411fcfba089ef8edf19ef /packages/instant/src/components/ui
parent117e2f583ff44bdb63340a2134edea0f3ecb77b3 (diff)
parentcd44470a29c48275e6a2a4bba42734d8f900d387 (diff)
downloaddexon-sol-tools-3eac119399d3e2729ce65f748d9fb31207ac2540.tar
dexon-sol-tools-3eac119399d3e2729ce65f748d9fb31207ac2540.tar.gz
dexon-sol-tools-3eac119399d3e2729ce65f748d9fb31207ac2540.tar.bz2
dexon-sol-tools-3eac119399d3e2729ce65f748d9fb31207ac2540.tar.lz
dexon-sol-tools-3eac119399d3e2729ce65f748d9fb31207ac2540.tar.xz
dexon-sol-tools-3eac119399d3e2729ce65f748d9fb31207ac2540.tar.zst
dexon-sol-tools-3eac119399d3e2729ce65f748d9fb31207ac2540.zip
Merge pull request #1230 from 0xProject/feature/instant/dropdown-ui
[instant] Dropdown Component Skeleton
Diffstat (limited to 'packages/instant/src/components/ui')
-rw-r--r--packages/instant/src/components/ui/circle.tsx19
-rw-r--r--packages/instant/src/components/ui/container.tsx3
-rw-r--r--packages/instant/src/components/ui/dropdown.tsx134
-rw-r--r--packages/instant/src/components/ui/flex.tsx1
-rw-r--r--packages/instant/src/components/ui/icon.tsx9
-rw-r--r--packages/instant/src/components/ui/overlay.tsx31
-rw-r--r--packages/instant/src/components/ui/text.tsx1
7 files changed, 162 insertions, 36 deletions
diff --git a/packages/instant/src/components/ui/circle.tsx b/packages/instant/src/components/ui/circle.tsx
index 26764ec71..4f9f56f12 100644
--- a/packages/instant/src/components/ui/circle.tsx
+++ b/packages/instant/src/components/ui/circle.tsx
@@ -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,
};
diff --git a/packages/instant/src/components/ui/container.tsx b/packages/instant/src/components/ui/container.tsx
index c42082ed5..8aa5db9e5 100644
--- a/packages/instant/src/components/ui/container.tsx
+++ b/packages/instant/src/components/ui/container.tsx
@@ -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)' : '')};
}
}
`;
diff --git a/packages/instant/src/components/ui/dropdown.tsx b/packages/instant/src/components/ui/dropdown.tsx
new file mode 100644
index 000000000..3a23f456d
--- /dev/null
+++ b/packages/instant/src/components/ui/dropdown.tsx
@@ -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>
+);
diff --git a/packages/instant/src/components/ui/flex.tsx b/packages/instant/src/components/ui/flex.tsx
index 5b00138b8..274c46b9e 100644
--- a/packages/instant/src/components/ui/flex.tsx
+++ b/packages/instant/src/components/ui/flex.tsx
@@ -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};
diff --git a/packages/instant/src/components/ui/icon.tsx b/packages/instant/src/components/ui/icon.tsx
index 2679dad1a..a88fa87dd 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}
@@ -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)};
diff --git a/packages/instant/src/components/ui/overlay.tsx b/packages/instant/src/components/ui/overlay.tsx
index 8c9572615..c5f55f9c0 100644
--- a/packages/instant/src/components/ui/overlay.tsx
+++ b/packages/instant/src/components/ui/overlay.tsx
@@ -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';
diff --git a/packages/instant/src/components/ui/text.tsx b/packages/instant/src/components/ui/text.tsx
index c6a76ff18..4fe429d25 100644
--- a/packages/instant/src/components/ui/text.tsx
+++ b/packages/instant/src/components/ui/text.tsx
@@ -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};