diff options
Diffstat (limited to 'packages/website/ts/components/ui')
-rw-r--r-- | packages/website/ts/components/ui/animation.tsx | 42 | ||||
-rw-r--r-- | packages/website/ts/components/ui/check_mark.tsx | 31 | ||||
-rw-r--r-- | packages/website/ts/components/ui/container.tsx | 43 | ||||
-rw-r--r-- | packages/website/ts/components/ui/ease_up_from_bottom_animation.tsx | 31 | ||||
-rw-r--r-- | packages/website/ts/components/ui/filled_image.tsx | 18 | ||||
-rw-r--r-- | packages/website/ts/components/ui/image.tsx | 2 | ||||
-rw-r--r-- | packages/website/ts/components/ui/input.tsx | 43 | ||||
-rw-r--r-- | packages/website/ts/components/ui/multi_select.tsx | 66 | ||||
-rw-r--r-- | packages/website/ts/components/ui/simple_loading.tsx | 17 | ||||
-rw-r--r-- | packages/website/ts/components/ui/text.tsx | 3 | ||||
-rw-r--r-- | packages/website/ts/components/ui/typed_text.tsx | 75 |
11 files changed, 173 insertions, 198 deletions
diff --git a/packages/website/ts/components/ui/animation.tsx b/packages/website/ts/components/ui/animation.tsx deleted file mode 100644 index 943e3bf28..000000000 --- a/packages/website/ts/components/ui/animation.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import * as React from 'react'; -import { keyframes, styled } from 'ts/style/theme'; - -export type AnimationType = 'easeUpFromBottom'; - -export interface AnimationProps { - type: AnimationType; -} - -const PlainAnimation: React.StatelessComponent<AnimationProps> = props => <div {...props} />; - -const appearFromBottomFrames = keyframes` - from { - position: fixed; - bottom: -500px; - left: 0px; - right: 0px; - } - - to { - position: fixed; - bottom: 0px; - left: 0px; - right: 0px; - } -`; - -const stylesForAnimation: { [K in AnimationType]: string } = { - // Needed for safari - easeUpFromBottom: `position: fixed`, -}; - -const animations: { [K in AnimationType]: string } = { - easeUpFromBottom: `${appearFromBottomFrames} 1s ease 0s 1 forwards`, -}; - -export const Animation = styled(PlainAnimation)` - animation: ${props => animations[props.type]}; - ${props => stylesForAnimation[props.type]}; -`; - -Animation.displayName = 'Animation'; diff --git a/packages/website/ts/components/ui/check_mark.tsx b/packages/website/ts/components/ui/check_mark.tsx new file mode 100644 index 000000000..86e427c8b --- /dev/null +++ b/packages/website/ts/components/ui/check_mark.tsx @@ -0,0 +1,31 @@ +import * as React from 'react'; + +import { colors } from '@0x/react-shared'; + +export interface CheckMarkProps { + color?: string; + isChecked?: boolean; +} + +export const CheckMark: React.StatelessComponent<CheckMarkProps> = ({ color, isChecked }) => ( + <svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg"> + <circle + cx="8.5" + cy="8.5" + r="8.5" + fill={isChecked ? color : 'white'} + stroke={isChecked ? undefined : '#CCCCCC'} + /> + <path + d="M2.5 4.5L1.79289 5.20711L2.5 5.91421L3.20711 5.20711L2.5 4.5ZM-0.707107 2.70711L1.79289 5.20711L3.20711 3.79289L0.707107 1.29289L-0.707107 2.70711ZM3.20711 5.20711L7.70711 0.707107L6.29289 -0.707107L1.79289 3.79289L3.20711 5.20711Z" + transform="translate(5 6.5)" + fill="white" + /> + </svg> +); + +CheckMark.displayName = 'Check'; + +CheckMark.defaultProps = { + color: colors.mediumBlue, +}; diff --git a/packages/website/ts/components/ui/container.tsx b/packages/website/ts/components/ui/container.tsx index 7eab2a50f..778f59f27 100644 --- a/packages/website/ts/components/ui/container.tsx +++ b/packages/website/ts/components/ui/container.tsx @@ -1,11 +1,15 @@ import { TextAlignProperty } from 'csstype'; +import { darken } from 'polished'; import * as React from 'react'; +import { styled } from 'ts/style/theme'; + type StringOrNum = string | number; export type ContainerTag = 'div' | 'span'; export interface ContainerProps { + margin?: string; marginTop?: StringOrNum; marginBottom?: StringOrNum; marginRight?: StringOrNum; @@ -17,10 +21,14 @@ export interface ContainerProps { paddingLeft?: StringOrNum; backgroundColor?: string; background?: string; + border?: string; + borderTop?: string; borderRadius?: StringOrNum; borderBottomLeftRadius?: StringOrNum; borderBottomRightRadius?: StringOrNum; borderBottom?: StringOrNum; + borderColor?: string; + children?: React.ReactNode; maxWidth?: StringOrNum; maxHeight?: StringOrNum; width?: StringOrNum; @@ -37,15 +45,32 @@ export interface ContainerProps { right?: string; bottom?: string; zIndex?: number; + float?: 'right' | 'left'; Tag?: ContainerTag; cursor?: string; id?: string; onClick?: (event: React.MouseEvent<HTMLElement>) => void; overflowX?: 'scroll' | 'hidden' | 'auto' | 'visible'; + overflowY?: 'scroll' | 'hidden' | 'auto' | 'visible'; + shouldDarkenOnHover?: boolean; + hasBoxShadow?: boolean; + shouldAddBoxShadowOnHover?: boolean; } -export const Container: React.StatelessComponent<ContainerProps> = props => { - const { children, className, Tag, isHidden, id, onClick, ...style } = props; +export const PlainContainer: React.StatelessComponent<ContainerProps> = props => { + const { + children, + className, + Tag, + isHidden, + id, + onClick, + shouldDarkenOnHover, + shouldAddBoxShadowOnHover, + hasBoxShadow, + // tslint:disable-next-line:trailing-comma + ...style + } = props; const visibility = isHidden ? 'hidden' : undefined; return ( <Tag id={id} style={{ ...style, visibility }} className={className} onClick={onClick}> @@ -54,6 +79,20 @@ export const Container: React.StatelessComponent<ContainerProps> = props => { ); }; +const BOX_SHADOW = '0px 3px 10px rgba(0, 0, 0, 0.3)'; + +export const Container = styled(PlainContainer)` + box-sizing: border-box; + ${props => (props.hasBoxShadow ? `box-shadow: ${BOX_SHADOW}` : '')}; + &:hover { + ${props => + props.shouldDarkenOnHover + ? `background-color: ${props.backgroundColor ? darken(0.05, props.backgroundColor) : 'none'} !important` + : ''}; + ${props => (props.shouldAddBoxShadowOnHover ? `box-shadow: ${BOX_SHADOW}` : '')}; + } +`; + Container.defaultProps = { Tag: 'div', }; diff --git a/packages/website/ts/components/ui/ease_up_from_bottom_animation.tsx b/packages/website/ts/components/ui/ease_up_from_bottom_animation.tsx new file mode 100644 index 000000000..ba141c01e --- /dev/null +++ b/packages/website/ts/components/ui/ease_up_from_bottom_animation.tsx @@ -0,0 +1,31 @@ +import { css, keyframes, styled } from 'ts/style/theme'; + +const appearFromBottomFrames = keyframes` + from { + position: fixed; + bottom: -500px; + left: 0px; + right: 0px; + } + + to { + position: fixed; + bottom: 0px; + left: 0px; + right: 0px; + } +`; + +const stylesForAnimation = css` + position: fixed; +`; +const animations = css` + animation: ${appearFromBottomFrames} 1s ease 0s 1 forwards; +`; + +export const EaseUpFromBottomAnimation = styled.div` + ${props => animations}; + ${props => stylesForAnimation}; +`; + +EaseUpFromBottomAnimation.displayName = 'EaseUpFromBottomAnimation'; diff --git a/packages/website/ts/components/ui/filled_image.tsx b/packages/website/ts/components/ui/filled_image.tsx deleted file mode 100644 index 7f58ee5b9..000000000 --- a/packages/website/ts/components/ui/filled_image.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import * as React from 'react'; - -export interface FilledImageProps { - src: string; -} -export const FilledImage = (props: FilledImageProps) => ( - <div - style={{ - width: '100%', - height: '100%', - objectFit: 'cover', - backgroundImage: `url(${props.src})`, - backgroundRepeat: 'no-repeat', - backgroundPosition: 'center', - backgroundSize: 'cover', - }} - /> -); diff --git a/packages/website/ts/components/ui/image.tsx b/packages/website/ts/components/ui/image.tsx index c8d39352b..d698ddaa0 100644 --- a/packages/website/ts/components/ui/image.tsx +++ b/packages/website/ts/components/ui/image.tsx @@ -10,6 +10,7 @@ export interface ImageProps { height?: string | number; maxWidth?: string | number; maxHeight?: string | number; + additionalStyle?: React.CSSProperties; } interface ImageState { imageLoadFailed: boolean; @@ -30,6 +31,7 @@ export class Image extends React.Component<ImageProps, ImageState> { onError={this._onError.bind(this)} src={src} style={{ + ...this.props.additionalStyle, borderRadius: this.props.borderRadius, maxWidth: this.props.maxWidth, maxHeight: this.props.maxHeight, diff --git a/packages/website/ts/components/ui/input.tsx b/packages/website/ts/components/ui/input.tsx deleted file mode 100644 index e5f4f6c70..000000000 --- a/packages/website/ts/components/ui/input.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { colors } from '@0x/react-shared'; -import * as React from 'react'; -import { styled } from 'ts/style/theme'; - -export interface InputProps { - className?: string; - value?: string; - width?: string; - fontSize?: string; - fontColor?: string; - placeholderColor?: string; - placeholder?: string; - backgroundColor?: string; - onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void; -} - -const PlainInput: React.StatelessComponent<InputProps> = ({ value, className, placeholder, onChange }) => ( - <input className={className} value={value} onChange={onChange} placeholder={placeholder} /> -); - -export const Input = styled(PlainInput)` - font-size: ${props => props.fontSize}; - width: ${props => props.width}; - padding: 0.8em 1.2em; - border-radius: 3px; - font-family: 'Roboto Mono'; - color: ${props => props.fontColor}; - border: none; - background-color: ${props => props.backgroundColor}; - &::placeholder { - color: ${props => props.placeholderColor}; - } -`; - -Input.defaultProps = { - width: 'auto', - backgroundColor: colors.white, - fontColor: colors.darkestGrey, - placeholderColor: colors.darkGrey, - fontSize: '12px', -}; - -Input.displayName = 'Input'; diff --git a/packages/website/ts/components/ui/multi_select.tsx b/packages/website/ts/components/ui/multi_select.tsx new file mode 100644 index 000000000..2cf44cae1 --- /dev/null +++ b/packages/website/ts/components/ui/multi_select.tsx @@ -0,0 +1,66 @@ +import { colors } from '@0x/react-shared'; +import * as _ from 'lodash'; +import * as React from 'react'; + +import { Container } from './container'; + +export interface MultiSelectItemConfig { + value: string; + renderItemContent: (isSelected: boolean) => React.ReactNode; + onClick?: () => void; +} + +export interface MultiSelectProps { + selectedValues?: string[]; + items: MultiSelectItemConfig[]; + backgroundColor?: string; + height?: string; +} + +export class MultiSelect extends React.Component<MultiSelectProps> { + public static defaultProps = { + backgroundColor: colors.white, + }; + public render(): React.ReactNode { + const { items, backgroundColor, selectedValues, height } = this.props; + return ( + <Container + backgroundColor={backgroundColor} + borderRadius="4px" + width="100%" + height={height} + overflowY="scroll" + > + {_.map(items, item => ( + <MultiSelectItem + key={item.value} + renderItemContent={item.renderItemContent} + backgroundColor={backgroundColor} + onClick={item.onClick} + isSelected={_.isUndefined(selectedValues) || _.includes(selectedValues, item.value)} + /> + ))} + </Container> + ); + } +} + +export interface MultiSelectItemProps { + renderItemContent: (isSelected: boolean) => React.ReactNode; + isSelected?: boolean; + onClick?: () => void; + backgroundColor?: string; +} + +export const MultiSelectItem: React.StatelessComponent<MultiSelectItemProps> = ({ + renderItemContent, + isSelected, + onClick, + backgroundColor, +}) => ( + <Container cursor="pointer" shouldDarkenOnHover={true} onClick={onClick} backgroundColor={backgroundColor}> + <Container borderBottom={`1px solid ${colors.lightestGrey}`} margin="0px 15px" padding="10px 0px"> + {renderItemContent(isSelected)} + </Container> + </Container> +); diff --git a/packages/website/ts/components/ui/simple_loading.tsx b/packages/website/ts/components/ui/simple_loading.tsx deleted file mode 100644 index 81744196d..000000000 --- a/packages/website/ts/components/ui/simple_loading.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import CircularProgress from 'material-ui/CircularProgress'; -import * as React from 'react'; - -export interface SimpleLoadingProps { - message: string; -} - -export const SimpleLoading = (props: SimpleLoadingProps) => { - return ( - <div className="mx-auto pt3" style={{ maxWidth: 400, height: 409 }}> - <div className="relative" style={{ top: '50%', transform: 'translateY(-50%)', height: 95 }}> - <CircularProgress /> - <div className="pt3 pb3">{props.message}</div> - </div> - </div> - ); -}; diff --git a/packages/website/ts/components/ui/text.tsx b/packages/website/ts/components/ui/text.tsx index c13e21913..046442ee5 100644 --- a/packages/website/ts/components/ui/text.tsx +++ b/packages/website/ts/components/ui/text.tsx @@ -3,10 +3,11 @@ import { darken } from 'polished'; import * as React from 'react'; import { styled } from 'ts/style/theme'; -export type TextTag = 'p' | 'div' | 'span' | 'label' | 'h1' | 'h2' | 'h3' | 'h4' | 'i'; +export type TextTag = 'p' | 'div' | 'span' | 'label' | 'h1' | 'h2' | 'h3' | 'h4' | 'i' | 'span'; export interface TextProps { className?: string; + children?: any; Tag?: TextTag; fontSize?: string; fontFamily?: string; diff --git a/packages/website/ts/components/ui/typed_text.tsx b/packages/website/ts/components/ui/typed_text.tsx deleted file mode 100644 index 6d38580b9..000000000 --- a/packages/website/ts/components/ui/typed_text.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; -import Typist from 'react-typist'; - -import { Text, TextProps } from 'ts/components/ui/text'; - -import 'react-typist/dist/Typist.css'; - -export interface TypedTextProps extends TextProps { - textList: string[]; - shouldRepeat?: boolean; - wordDelayMs?: number; - avgKeystrokeDelayMs?: number; - stdKeystrokeDelay?: number; -} - -export interface TypedTextState { - cycleCount: number; -} - -export class TypedText extends React.Component<TypedTextProps, TypedTextState> { - public static defaultProps = { - shouldRepeat: false, - avgKeystrokeDelayMs: 90, - wordDelayMs: 1000, - }; - public state = { - cycleCount: 0, - }; - public render(): React.ReactNode { - const { - textList, - shouldRepeat, - wordDelayMs, - avgKeystrokeDelayMs, - stdKeystrokeDelay, - // tslint:disable-next-line - ...textProps - } = this.props; - const { cycleCount } = this.state; - if (_.isEmpty(textList)) { - return null; - } - const typistChildren: React.ReactNode[] = []; - _.forEach(textList, text => { - typistChildren.push( - <Text key={`text-${text}-${cycleCount}`} {...textProps}> - {text} - </Text>, - ); - if (wordDelayMs) { - typistChildren.push(<Typist.Delay key={`delay-${text}-${cycleCount}`} ms={wordDelayMs} />); - } - typistChildren.push(<Typist.Backspace key={`backspace-${text}-${cycleCount}`} count={text.length} />); - }); - return ( - <Typist - avgTypingDelay={avgKeystrokeDelayMs} - stdTypingDelay={stdKeystrokeDelay} - className="inline" - key={`typist-key-${cycleCount}`} - onTypingDone={this._onTypingDone.bind(this)} - > - {typistChildren} - </Typist> - ); - } - private _onTypingDone(): void { - if (this.props.shouldRepeat) { - this.setState({ - cycleCount: this.state.cycleCount + 1, - }); - } - } -} |