diff options
Diffstat (limited to 'packages/instant/src/components/ui')
-rw-r--r-- | packages/instant/src/components/ui/circle.tsx | 19 | ||||
-rw-r--r-- | packages/instant/src/components/ui/container.tsx | 3 | ||||
-rw-r--r-- | packages/instant/src/components/ui/dropdown.tsx | 134 | ||||
-rw-r--r-- | packages/instant/src/components/ui/flex.tsx | 1 | ||||
-rw-r--r-- | packages/instant/src/components/ui/icon.tsx | 9 | ||||
-rw-r--r-- | packages/instant/src/components/ui/overlay.tsx | 31 | ||||
-rw-r--r-- | packages/instant/src/components/ui/text.tsx | 1 |
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}; |