aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfragosti <francesco.agosti93@gmail.com>2018-11-30 07:57:35 +0800
committerFred Carlsen <fred@sjelfull.no>2018-12-06 18:56:11 +0800
commit9ebb0960254f1dcfb9513cbc6203840a87ee60e4 (patch)
tree222218f42cdf3cf964725cec8a8c0752f4035a3d
parentf8b925c9adcc9fecf237d29e002fe993ca4f41a8 (diff)
downloaddexon-sol-tools-9ebb0960254f1dcfb9513cbc6203840a87ee60e4.tar.gz
dexon-sol-tools-9ebb0960254f1dcfb9513cbc6203840a87ee60e4.tar.zst
dexon-sol-tools-9ebb0960254f1dcfb9513cbc6203840a87ee60e4.zip
feat: add Select component and use for configurator
-rw-r--r--packages/website/ts/components/ui/container.tsx33
-rw-r--r--packages/website/ts/components/ui/select.tsx168
-rw-r--r--packages/website/ts/pages/instant/action_link.tsx2
-rw-r--r--packages/website/ts/pages/instant/code_demo.tsx3
-rw-r--r--packages/website/ts/pages/instant/config_generator.tsx38
-rw-r--r--packages/website/ts/pages/instant/configurator.tsx70
-rw-r--r--packages/website/ts/pages/instant/features.tsx2
7 files changed, 285 insertions, 31 deletions
diff --git a/packages/website/ts/components/ui/container.tsx b/packages/website/ts/components/ui/container.tsx
index 7eab2a50f..cd0ed9986 100644
--- a/packages/website/ts/components/ui/container.tsx
+++ b/packages/website/ts/components/ui/container.tsx
@@ -1,6 +1,9 @@
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';
@@ -17,10 +20,13 @@ export interface ContainerProps {
paddingLeft?: StringOrNum;
backgroundColor?: string;
background?: string;
+ border?: string;
+ borderTop?: string;
borderRadius?: StringOrNum;
borderBottomLeftRadius?: StringOrNum;
borderBottomRightRadius?: StringOrNum;
borderBottom?: StringOrNum;
+ borderColor?: string;
maxWidth?: StringOrNum;
maxHeight?: StringOrNum;
width?: StringOrNum;
@@ -42,10 +48,23 @@ export interface ContainerProps {
id?: string;
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
overflowX?: 'scroll' | 'hidden' | 'auto' | 'visible';
+ shouldDarkenOnHover?: 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,
+ // 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 +73,16 @@ export const Container: React.StatelessComponent<ContainerProps> = props => {
);
};
+export const Container = styled(PlainContainer)`
+ &:hover {
+ ${props =>
+ props.shouldDarkenOnHover
+ ? `background-color: ${props.backgroundColor ? darken(0.05, props.backgroundColor) : 'none'} !important`
+ : ''};
+ ${props => (props.shouldAddBoxShadowOnHover ? 'box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1)' : '')};
+ }
+`;
+
Container.defaultProps = {
Tag: 'div',
};
diff --git a/packages/website/ts/components/ui/select.tsx b/packages/website/ts/components/ui/select.tsx
new file mode 100644
index 000000000..abf202c67
--- /dev/null
+++ b/packages/website/ts/components/ui/select.tsx
@@ -0,0 +1,168 @@
+import { colors } from '@0x/react-shared';
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { zIndex } from 'ts/style/z_index';
+
+import { Container } from './container';
+import { Overlay } from './overlay';
+import { Text } from './text';
+
+export interface SelectItemConfig {
+ text: string;
+ onClick?: () => void;
+}
+
+export interface SelectProps {
+ value: string;
+ label?: string;
+ items: SelectItemConfig[];
+ onOpen?: () => void;
+ border?: string;
+ fontSize?: string;
+ iconSize?: number;
+ textColor?: string;
+ labelColor?: string;
+ backgroundColor?: string;
+}
+
+export interface SelectState {
+ isOpen: boolean;
+}
+
+export class Select extends React.Component<SelectProps, SelectState> {
+ public static defaultProps = {
+ items: [] as SelectItemConfig[],
+ textColor: colors.black,
+ backgroundColor: colors.white,
+ fontSize: '16px',
+ iconSize: 25,
+ };
+ public state: SelectState = {
+ isOpen: false,
+ };
+ public render(): React.ReactNode {
+ const { value, label, items, border, textColor, labelColor, backgroundColor, fontSize, iconSize } = this.props;
+ const { isOpen } = this.state;
+ const hasItems = !_.isEmpty(items);
+ const borderRadius = isOpen ? '4px 4px 0px 0px' : '4px';
+ return (
+ <React.Fragment>
+ {isOpen && (
+ <Overlay
+ style={{
+ zIndex: zIndex.overlay,
+ backgroundColor: 'rgba(255, 255, 255, 0)',
+ }}
+ onClick={this._closeDropdown}
+ />
+ )}
+ <Container position="relative">
+ <Container
+ cursor={hasItems ? 'pointer' : undefined}
+ onClick={this._handleDropdownClick}
+ borderRadius={borderRadius}
+ border={border}
+ backgroundColor={backgroundColor}
+ padding="0.8em"
+ width="100%"
+ >
+ <Container className="flex justify-between">
+ <Text fontSize={fontSize} fontColor={textColor}>
+ {value}
+ </Text>
+ <Container>
+ {label && (
+ <Text fontSize={fontSize} fontColor={labelColor}>
+ {label}
+ </Text>
+ )}
+ {hasItems && (
+ <Container marginLeft="5px" display="inline-block" position="relative" bottom="2px">
+ <i
+ className="zmdi zmdi-chevron-down"
+ style={{ fontSize: iconSize, color: colors.darkGrey }}
+ />
+ </Container>
+ )}
+ </Container>
+ </Container>
+ </Container>
+ {isOpen && (
+ <Container
+ width="100%"
+ position="absolute"
+ onClick={this._closeDropdown}
+ zIndex={zIndex.aboveOverlay}
+ >
+ {_.map(items, (item, index) => (
+ <SelectItem
+ key={item.text}
+ {...item}
+ isLast={index === items.length - 1}
+ backgroundColor={backgroundColor}
+ textColor={textColor}
+ border={border}
+ />
+ ))}
+ </Container>
+ )}
+ </Container>
+ </React.Fragment>
+ );
+ }
+ private readonly _handleDropdownClick = (): void => {
+ if (_.isEmpty(this.props.items)) {
+ return;
+ }
+ const isOpen = !this.state.isOpen;
+ this.setState({
+ isOpen,
+ });
+
+ if (isOpen && this.props.onOpen) {
+ this.props.onOpen();
+ }
+ };
+ private readonly _closeDropdown = (): void => {
+ this.setState({
+ isOpen: false,
+ });
+ };
+}
+
+export interface SelectItemProps extends SelectItemConfig {
+ text: string;
+ onClick?: () => void;
+ isLast: boolean;
+ backgroundColor?: string;
+ border?: string;
+ textColor?: string;
+ fontSize?: string;
+}
+
+export const SelectItem: React.StatelessComponent<SelectItemProps> = ({
+ text,
+ onClick,
+ isLast,
+ border,
+ backgroundColor,
+ textColor,
+ fontSize,
+}) => (
+ <Container
+ onClick={onClick}
+ cursor="pointer"
+ backgroundColor={backgroundColor}
+ padding="0.8em"
+ borderTop="0"
+ border={border}
+ shouldDarkenOnHover={true}
+ borderRadius={isLast ? '0px 0px 4px 4px' : undefined}
+ width="100%"
+ >
+ <Text fontSize={fontSize} fontColor={textColor}>
+ {text}
+ </Text>
+ </Container>
+);
diff --git a/packages/website/ts/pages/instant/action_link.tsx b/packages/website/ts/pages/instant/action_link.tsx
index 8a0bf24ff..5612dc25b 100644
--- a/packages/website/ts/pages/instant/action_link.tsx
+++ b/packages/website/ts/pages/instant/action_link.tsx
@@ -41,7 +41,7 @@ export class ActionLink extends React.Component<ActionLinkProps> {
);
}
- private _handleClick = (event: React.MouseEvent<HTMLElement>) => {
+ private readonly _handleClick = (event: React.MouseEvent<HTMLElement>) => {
if (!_.isUndefined(this.props.onClick)) {
this.props.onClick();
} else if (!_.isUndefined(this.props.linkSrc)) {
diff --git a/packages/website/ts/pages/instant/code_demo.tsx b/packages/website/ts/pages/instant/code_demo.tsx
index 4f44a6160..e9ecad40d 100644
--- a/packages/website/ts/pages/instant/code_demo.tsx
+++ b/packages/website/ts/pages/instant/code_demo.tsx
@@ -1,11 +1,8 @@
import * as React from 'react';
import SyntaxHighlighter from 'react-syntax-highlighter';
-import { atelierCaveDark } from 'react-syntax-highlighter/styles/hljs';
import { colors } from 'ts/style/colors';
import { styled } from 'ts/style/theme';
-import { Container } from 'ts/components/ui/container';
-
const CustomPre = styled.pre`
margin: 0px;
line-height: 24px;
diff --git a/packages/website/ts/pages/instant/config_generator.tsx b/packages/website/ts/pages/instant/config_generator.tsx
new file mode 100644
index 000000000..d63975e31
--- /dev/null
+++ b/packages/website/ts/pages/instant/config_generator.tsx
@@ -0,0 +1,38 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { Container } from 'ts/components/ui/container';
+import { Select, SelectItemConfig } from 'ts/components/ui/select';
+
+import { ZeroExInstantBaseConfig } from '../../../../instant/src/types';
+
+export interface ConfigGeneratorProps {
+ value: ZeroExInstantBaseConfig;
+ onConfigChange: (config: ZeroExInstantBaseConfig) => void;
+}
+
+const SRA_ENDPOINTS = ['https://api.radarrelay.com/0x/v2/', 'https://api.openrelay.xyz/v2/'];
+
+export class ConfigGenerator extends React.Component<ConfigGeneratorProps> {
+ public render(): React.ReactNode {
+ const { value } = this.props;
+ return (
+ <Container>
+ <Select value={value.orderSource as string} items={this._generateItems()} />
+ </Container>
+ );
+ }
+ private readonly _generateItems = (): SelectItemConfig[] => {
+ return _.map(SRA_ENDPOINTS, endpoint => ({
+ text: endpoint,
+ onClick: this._handleSRASelection.bind(this, endpoint),
+ }));
+ };
+ private readonly _handleSRASelection = (sraEndpoint: string) => {
+ const newConfig = {
+ ...this.props.value,
+ orderSource: sraEndpoint,
+ };
+ this.props.onConfigChange(newConfig);
+ };
+}
diff --git a/packages/website/ts/pages/instant/configurator.tsx b/packages/website/ts/pages/instant/configurator.tsx
index 29a3e2b1e..cf9985675 100644
--- a/packages/website/ts/pages/instant/configurator.tsx
+++ b/packages/website/ts/pages/instant/configurator.tsx
@@ -4,34 +4,56 @@ import { Container } from 'ts/components/ui/container';
import { Text } from 'ts/components/ui/text';
import { ActionLink } from 'ts/pages/instant/action_link';
import { CodeDemo } from 'ts/pages/instant/code_demo';
+import { ConfigGenerator } from 'ts/pages/instant/config_generator';
import { colors } from 'ts/style/colors';
+import { ZeroExInstantBaseConfig } from '../../../../instant/src/types';
+
export interface ConfiguratorProps {
hash: string;
}
-export const Configurator = (props: ConfiguratorProps) => (
- <Container
- className="flex justify-center py4 px3"
- id={props.hash}
- backgroundColor={colors.instantTertiaryBackground}
- >
- <Container className="mx3">
- <Container className="mb3">
- <Text fontSize="20px" lineHeight="28px" fontColor={colors.white} fontWeight={500}>
- 0x Instant Configurator
- </Text>
- </Container>
- <Container height="400px" width="300px" backgroundColor="white" />
- </Container>
- <Container className="mx3">
- <Container className="mb3 flex justify-between">
- <Text fontSize="20px" lineHeight="28px" fontColor={colors.white} fontWeight={500}>
- Code Snippet
- </Text>
- <ActionLink displayText="Explore the Docs" linkSrc="/docs/instant" color={colors.grey} />
+export interface ConfiguratorState {
+ instantConfig: ZeroExInstantBaseConfig;
+}
+
+export class Configurator extends React.Component<ConfiguratorProps> {
+ public state = {
+ instantConfig: {
+ orderSource: 'https://api.radarrelay.com/0x/v2/',
+ },
+ };
+ public render(): React.ReactNode {
+ const { hash } = this.props;
+ return (
+ <Container
+ className="flex justify-center py4 px3"
+ id={hash}
+ backgroundColor={colors.instantTertiaryBackground}
+ >
+ <Container className="mx3">
+ <Container className="mb3">
+ <Text fontSize="20px" lineHeight="28px" fontColor={colors.white} fontWeight={500}>
+ 0x Instant Configurator
+ </Text>
+ </Container>
+ <ConfigGenerator value={this.state.instantConfig} onConfigChange={this._handleConfigChange} />
+ </Container>
+ <Container className="mx3">
+ <Container className="mb3 flex justify-between">
+ <Text fontSize="20px" lineHeight="28px" fontColor={colors.white} fontWeight={500}>
+ Code Snippet
+ </Text>
+ <ActionLink displayText="Explore the Docs" linkSrc="/docs/instant" color={colors.grey} />
+ </Container>
+ <CodeDemo />
+ </Container>
</Container>
- <CodeDemo />
- </Container>
- </Container>
-);
+ );
+ }
+ private readonly _handleConfigChange = (config: ZeroExInstantBaseConfig) => {
+ this.setState({
+ instantConfig: config,
+ });
+ };
+}
diff --git a/packages/website/ts/pages/instant/features.tsx b/packages/website/ts/pages/instant/features.tsx
index 6c6835311..1e187c9da 100644
--- a/packages/website/ts/pages/instant/features.tsx
+++ b/packages/website/ts/pages/instant/features.tsx
@@ -2,9 +2,9 @@ import * as _ from 'lodash';
import * as React from 'react';
import { Container } from 'ts/components/ui/container';
-import { ActionLink, ActionLinkProps } from 'ts/pages/instant/action_link';
import { Image } from 'ts/components/ui/image';
import { Text } from 'ts/components/ui/text';
+import { ActionLink, ActionLinkProps } from 'ts/pages/instant/action_link';
import { colors } from 'ts/style/colors';
import { ScreenWidths } from 'ts/types';
import { utils } from 'ts/utils/utils';