diff options
-rw-r--r-- | packages/instant/package.json | 8 | ||||
-rw-r--r-- | packages/instant/public/index.html | 6 | ||||
-rw-r--r-- | packages/instant/src/components/ui/button.tsx | 68 | ||||
-rw-r--r-- | packages/instant/src/components/ui/container.tsx | 55 | ||||
-rw-r--r-- | packages/instant/src/components/ui/flex.tsx | 34 | ||||
-rw-r--r-- | packages/instant/src/components/ui/index.ts | 4 | ||||
-rw-r--r-- | packages/instant/src/components/ui/text.tsx | 80 | ||||
-rw-r--r-- | packages/instant/src/components/zero_ex_instant.tsx | 17 | ||||
-rw-r--r-- | packages/instant/src/components/zero_ex_instant_container.tsx | 38 | ||||
-rw-r--r-- | packages/instant/src/redux/reducer.ts | 23 | ||||
-rw-r--r-- | packages/instant/src/redux/store.ts | 6 | ||||
-rw-r--r-- | packages/instant/src/style/fonts.ts | 10 | ||||
-rw-r--r-- | packages/instant/src/style/theme.ts | 29 | ||||
-rw-r--r-- | packages/instant/src/style/util.ts | 10 | ||||
-rw-r--r-- | packages/instant/src/types.ts | 8 | ||||
-rw-r--r-- | packages/instant/tslint.json | 5 | ||||
-rw-r--r-- | yarn.lock | 37 |
17 files changed, 430 insertions, 8 deletions
diff --git a/packages/instant/package.json b/packages/instant/package.json index 365312a70..57b094626 100644 --- a/packages/instant/package.json +++ b/packages/instant/package.json @@ -50,8 +50,12 @@ "@0xproject/web3-wrapper": "^3.0.1", "ethereum-types": "^1.0.8", "lodash": "^4.17.10", + "polished": "^2.2.0", "react": "^16.5.2", - "react-dom": "^16.5.2" + "react-dom": "^16.5.2", + "react-redux": "^5.0.7", + "redux": "^4.0.0", + "styled-components": "^3.4.9" }, "devDependencies": { "@0xproject/tslint-config": "^1.0.7", @@ -61,6 +65,8 @@ "@types/node": "*", "@types/react": "16.4.7", "@types/react-dom": "^16.0.8", + "@types/react-redux": "^6.0.9", + "@types/redux": "^3.6.0", "awesome-typescript-loader": "^5.2.1", "copyfiles": "^1.2.0", "enzyme": "^3.6.0", diff --git a/packages/instant/public/index.html b/packages/instant/public/index.html index 45968a3c9..d673dafd8 100644 --- a/packages/instant/public/index.html +++ b/packages/instant/public/index.html @@ -6,6 +6,12 @@ <meta name="viewport" content="width=device-width, initial-scale=1"> <title>0x Instant Dev Environment</title> <script type="text/javascript" src="/main.bundle.js" charset="utf-8"></script> + <style> + #zeroExInstantContainer { + margin-left: 30px; + margin-top: 30px; + } + </style> </head> <body> diff --git a/packages/instant/src/components/ui/button.tsx b/packages/instant/src/components/ui/button.tsx new file mode 100644 index 000000000..ec0a87345 --- /dev/null +++ b/packages/instant/src/components/ui/button.tsx @@ -0,0 +1,68 @@ +import { darken, saturate } from 'polished'; +import * as React from 'react'; + +import { ColorOption, styled } from '../../style/theme'; + +export interface ButtonProps { + fontColor: ColorOption; + backgroundColor: ColorOption; + borderColor?: ColorOption; + fontSize?: string; + fontFamily?: string; + width?: string; + padding?: string; + type?: string; + isDisabled?: boolean; + onClick?: (event: React.MouseEvent<HTMLElement>) => void; + className?: string; +} + +const PlainButton: React.StatelessComponent<ButtonProps> = ({ children, isDisabled, onClick, type, className }) => ( + <button type={type} className={className} onClick={isDisabled ? undefined : onClick} disabled={isDisabled}> + {children} + </button> +); + +const darkenOnHoverAmount = 0.1; +const darkenOnActiveAmount = 0.2; +const saturateOnFocusAmount = 0.2; +export const Button = styled(PlainButton)` + cursor: ${props => (props.isDisabled ? 'default' : 'pointer')}; + font-size: ${props => props.fontSize}; + color: ${props => props.fontColor}; + transition: background-color, opacity 0.5s ease; + padding: ${props => props.padding}; + border-radius: 6px; + font-weight: 500; + outline: none; + font-family: ${props => props.fontFamily}; + width: ${props => props.width}; + background-color: ${props => props.backgroundColor}; + border: ${props => (props.borderColor ? `1px solid ${props.theme[props.borderColor]}` : 'none')}; + &:hover { + background-color: ${props => + !props.isDisabled ? darken(darkenOnHoverAmount, props.theme[props.backgroundColor]) : ''} !important; + } + &:active { + background-color: ${props => + !props.isDisabled ? darken(darkenOnActiveAmount, props.theme[props.backgroundColor]) : ''}; + } + &:disabled { + opacity: 0.5; + } + &:focus { + background-color: ${props => saturate(saturateOnFocusAmount, props.theme[props.backgroundColor])}; + } +`; + +Button.defaultProps = { + fontSize: '12px', + fontColor: ColorOption.white, + backgroundColor: ColorOption.primaryColor, + width: 'auto', + fontFamily: 'Inter UI', + isDisabled: false, + padding: '0.8em 2.2em', +}; + +Button.displayName = 'Button'; diff --git a/packages/instant/src/components/ui/container.tsx b/packages/instant/src/components/ui/container.tsx new file mode 100644 index 000000000..8366d5748 --- /dev/null +++ b/packages/instant/src/components/ui/container.tsx @@ -0,0 +1,55 @@ +import * as React from 'react'; + +import { ColorOption, styled } from '../../style/theme'; +import { cssRuleIfExists } from '../../style/util'; + +export interface ContainerProps { + display?: string; + position?: string; + top?: string; + right?: string; + bottom?: string; + left?: string; + width?: string; + maxWidth?: string; + margin?: string; + marginTop?: string; + marginRight?: string; + marginBottom?: string; + marginLeft?: string; + padding?: string; + boxShadow?: string; + borderRadius?: string; + className?: string; + backgroundColor?: ColorOption; +} + +const PlainContainer: React.StatelessComponent<ContainerProps> = ({ children, className }) => ( + <div className={className}>{children}</div> +); + +export const Container = styled(PlainContainer)` + ${props => cssRuleIfExists(props, 'display')} + ${props => cssRuleIfExists(props, 'position')} + ${props => cssRuleIfExists(props, 'top')} + ${props => cssRuleIfExists(props, 'right')} + ${props => cssRuleIfExists(props, 'bottom')} + ${props => cssRuleIfExists(props, 'left')} + ${props => cssRuleIfExists(props, 'width')} + ${props => cssRuleIfExists(props, 'max-width')} + ${props => cssRuleIfExists(props, 'margin')} + ${props => cssRuleIfExists(props, 'margin-top')} + ${props => cssRuleIfExists(props, 'margin-right')} + ${props => cssRuleIfExists(props, 'margin-bottom')} + ${props => cssRuleIfExists(props, 'margin-left')} + ${props => cssRuleIfExists(props, 'padding')} + ${props => cssRuleIfExists(props, 'box-shadow')} + ${props => cssRuleIfExists(props, 'border-radius')} + background-color: ${props => (props.backgroundColor ? props.theme[props.backgroundColor] : 'none')}; +`; + +Container.defaultProps = { + display: 'inline-block', +}; + +Container.displayName = 'Container'; diff --git a/packages/instant/src/components/ui/flex.tsx b/packages/instant/src/components/ui/flex.tsx new file mode 100644 index 000000000..f55f5f8ba --- /dev/null +++ b/packages/instant/src/components/ui/flex.tsx @@ -0,0 +1,34 @@ +import * as React from 'react'; + +import { ColorOption, styled } from '../../style/theme'; + +export interface FlexProps { + direction?: 'row' | 'column'; + flexWrap?: 'wrap' | 'nowrap'; + justify?: 'flex-start' | 'center' | 'space-around' | 'space-between' | 'space-evenly' | 'flex-end'; + align?: 'flex-start' | 'center' | 'space-around' | 'space-between' | 'space-evenly' | 'flex-end'; + backgroundColor?: ColorOption; + className?: string; +} + +const PlainFlex: React.StatelessComponent<FlexProps> = ({ children, className }) => ( + <div className={className}>{children}</div> +); + +export const Flex = styled(PlainFlex)` + display: flex; + flex-direction: ${props => props.direction}; + flex-wrap: ${props => props.flexWrap}; + justify-content: ${props => props.justify}; + align-items: ${props => props.align}; + background-color: ${props => (props.backgroundColor ? props.theme[props.backgroundColor] : 'none')}; +`; + +Flex.defaultProps = { + direction: 'row', + flexWrap: 'nowrap', + justify: 'center', + align: 'center', +}; + +Flex.displayName = 'Flex'; diff --git a/packages/instant/src/components/ui/index.ts b/packages/instant/src/components/ui/index.ts new file mode 100644 index 000000000..dca63b65c --- /dev/null +++ b/packages/instant/src/components/ui/index.ts @@ -0,0 +1,4 @@ +export { Text, Title } from './text'; +export { Button } from './button'; +export { Flex } from './flex'; +export { Container } from './container'; diff --git a/packages/instant/src/components/ui/text.tsx b/packages/instant/src/components/ui/text.tsx new file mode 100644 index 000000000..0bc387644 --- /dev/null +++ b/packages/instant/src/components/ui/text.tsx @@ -0,0 +1,80 @@ +import { darken } from 'polished'; +import * as React from 'react'; + +import { ColorOption, styled } from '../../style/theme'; + +export interface TextProps { + fontColor?: ColorOption; + fontFamily?: string; + fontStyle?: string; + fontSize?: string; + opacity?: number; + letterSpacing?: string; + textTransform?: string; + lineHeight?: string; + className?: string; + minHeight?: string; + center?: boolean; + fontWeight?: number | string; + textDecorationLine?: string; + onClick?: (event: React.MouseEvent<HTMLElement>) => void; + hoverColor?: string; + noWrap?: boolean; + display?: string; +} + +const PlainText: React.StatelessComponent<TextProps> = ({ children, className, onClick }) => ( + <p className={className} onClick={onClick}> + {children} + </p> +); + +const darkenOnHoverAmount = 0.3; +export const Text = styled(PlainText)` + font-family: ${props => props.fontFamily}; + font-style: ${props => props.fontStyle}; + font-weight: ${props => props.fontWeight}; + font-size: ${props => props.fontSize}; + opacity: ${props => props.opacity}; + text-decoration-line: ${props => props.textDecorationLine}; + ${props => (props.lineHeight ? `line-height: ${props.lineHeight}` : '')}; + ${props => (props.center ? 'text-align: center' : '')}; + color: ${props => props.fontColor && props.theme[props.fontColor]}; + ${props => (props.minHeight ? `min-height: ${props.minHeight}` : '')}; + ${props => (props.onClick ? 'cursor: pointer' : '')}; + transition: color 0.5s ease; + ${props => (props.noWrap ? 'white-space: nowrap' : '')}; + ${props => (props.display ? `display: ${props.display}` : '')}; + ${props => (props.letterSpacing ? `letter-spacing: ${props.letterSpacing}` : '')}; + ${props => (props.textTransform ? `text-transform: ${props.textTransform}` : '')}; + &:hover { + ${props => + props.onClick + ? `color: ${props.hoverColor || darken(darkenOnHoverAmount, props.theme[props.fontColor || 'white'])}` + : ''}; + } +`; + +Text.defaultProps = { + fontFamily: 'Inter UI', + fontStyle: 'normal', + fontWeight: 400, + fontColor: ColorOption.black, + fontSize: '15px', + lineHeight: '1.5em', + textDecorationLine: 'none', + noWrap: false, +}; + +Text.displayName = 'Text'; + +export const Title: React.StatelessComponent<TextProps> = props => <Text {...props} />; + +Title.defaultProps = { + fontSize: '20px', + fontWeight: 600, + opacity: 1, + fontColor: ColorOption.primaryColor, +}; + +Title.displayName = 'Title'; diff --git a/packages/instant/src/components/zero_ex_instant.tsx b/packages/instant/src/components/zero_ex_instant.tsx index 67e1b683d..0e6230d1b 100644 --- a/packages/instant/src/components/zero_ex_instant.tsx +++ b/packages/instant/src/components/zero_ex_instant.tsx @@ -1,5 +1,20 @@ import * as React from 'react'; +import { Provider } from 'react-redux'; + +import { store } from '../redux/store'; +import { fonts } from '../style/fonts'; +import { theme, ThemeProvider } from '../style/theme'; + +import { ZeroExInstantContainer } from './zero_ex_instant_container'; + +fonts.include(); export interface ZeroExInstantProps {} -export const ZeroExInstant: React.StatelessComponent<ZeroExInstantProps> = () => <div>ZeroExInstant</div>; +export const ZeroExInstant: React.StatelessComponent<ZeroExInstantProps> = () => ( + <Provider store={store}> + <ThemeProvider theme={theme}> + <ZeroExInstantContainer /> + </ThemeProvider> + </Provider> +); diff --git a/packages/instant/src/components/zero_ex_instant_container.tsx b/packages/instant/src/components/zero_ex_instant_container.tsx new file mode 100644 index 000000000..fc936c3f2 --- /dev/null +++ b/packages/instant/src/components/zero_ex_instant_container.tsx @@ -0,0 +1,38 @@ +import * as React from 'react'; + +import { ColorOption } from '../style/theme'; + +import { Container, Flex, Text } from './ui'; + +export interface ZeroExInstantContainerProps {} + +export const ZeroExInstantContainer: React.StatelessComponent<ZeroExInstantContainerProps> = props => ( + <Container width="350px" borderRadius="3px"> + <Flex direction="column"> + <Container backgroundColor={ColorOption.primaryColor} padding="20px"> + <Text + letterSpacing="1px" + fontColor={ColorOption.white} + opacity={0.7} + fontWeight={600} + textTransform="uppercase" + > + I want to buy + </Text> + <Flex direction="row" justify="space-between"> + <Container> + <Text textTransform="uppercase">0.00</Text> + <Text textTransform="uppercase"> rep </Text> + </Container> + <Flex direction="column"> + <Text> 0 ETH </Text> + <Text> $0.00 </Text> + </Flex> + </Flex> + </Container> + <Container padding="20px" backgroundColor={ColorOption.white}> + <Text>hey</Text> + </Container> + </Flex> + </Container> +); diff --git a/packages/instant/src/redux/reducer.ts b/packages/instant/src/redux/reducer.ts new file mode 100644 index 000000000..e4578d620 --- /dev/null +++ b/packages/instant/src/redux/reducer.ts @@ -0,0 +1,23 @@ +import * as _ from 'lodash'; + +import { Action, ActionTypes } from '../types'; + +export interface State { + ethUsdPrice?: string; +} + +export const INITIAL_STATE: State = { + ethUsdPrice: undefined, +}; + +export const reducer = (state: State = INITIAL_STATE, action: Action): State => { + switch (action.type) { + case ActionTypes.UPDATE_ETH_USD_PRICE: + return { + ...state, + ethUsdPrice: action.data, + }; + default: + return state; + } +}; diff --git a/packages/instant/src/redux/store.ts b/packages/instant/src/redux/store.ts new file mode 100644 index 000000000..fcd19f9a8 --- /dev/null +++ b/packages/instant/src/redux/store.ts @@ -0,0 +1,6 @@ +import * as _ from 'lodash'; +import { createStore, Store as ReduxStore } from 'redux'; + +import { reducer, State } from './reducer'; + +export const store: ReduxStore<State> = createStore(reducer); diff --git a/packages/instant/src/style/fonts.ts b/packages/instant/src/style/fonts.ts new file mode 100644 index 000000000..975a30a61 --- /dev/null +++ b/packages/instant/src/style/fonts.ts @@ -0,0 +1,10 @@ +import { injectGlobal } from './theme'; + +export const fonts = { + include: () => { + // Inject the inter-ui font into the page + return injectGlobal` + @import url('https://rsms.me/inter/inter-ui.css'); + `; + }, +}; diff --git a/packages/instant/src/style/theme.ts b/packages/instant/src/style/theme.ts new file mode 100644 index 000000000..9eb6ccb56 --- /dev/null +++ b/packages/instant/src/style/theme.ts @@ -0,0 +1,29 @@ +import * as styledComponents from 'styled-components'; + +const { + default: styled, + css, + injectGlobal, + keyframes, + ThemeProvider, +} = styledComponents; + +export type Theme = { [key in ColorOption]: string }; + +export enum ColorOption { + primaryColor = 'primaryColor', + black = 'black', + lightGrey = 'lightGrey', + darkGrey = 'darkGrey', + white = 'white', +} + +export const theme: Theme = { + primaryColor: '#512D80', + black: 'black', + lightGrey: '#999999', + darkGrey: '#333333', + white: 'white', +}; + +export { styled, css, injectGlobal, keyframes, ThemeProvider }; diff --git a/packages/instant/src/style/util.ts b/packages/instant/src/style/util.ts new file mode 100644 index 000000000..7cf13133f --- /dev/null +++ b/packages/instant/src/style/util.ts @@ -0,0 +1,10 @@ +import * as _ from 'lodash'; + +export const cssRuleIfExists = (props: any, rule: string): string => { + const camelCaseRule = _.camelCase(rule); + const ruleValueIfExists = props[camelCaseRule]; + if (!_.isUndefined(ruleValueIfExists)) { + return `${rule}: ${ruleValueIfExists};`; + } + return ''; +}; diff --git a/packages/instant/src/types.ts b/packages/instant/src/types.ts new file mode 100644 index 000000000..3ba5a9b94 --- /dev/null +++ b/packages/instant/src/types.ts @@ -0,0 +1,8 @@ +export enum ActionTypes { + UPDATE_ETH_USD_PRICE, +} + +export interface Action { + type: ActionTypes; + data?: any; +} diff --git a/packages/instant/tslint.json b/packages/instant/tslint.json index ffaefe83a..1ab924e47 100644 --- a/packages/instant/tslint.json +++ b/packages/instant/tslint.json @@ -1,3 +1,6 @@ { - "extends": ["@0xproject/tslint-config"] + "extends": ["@0xproject/tslint-config"], + "rules": { + "custom-no-magic-numbers": false + } } @@ -1223,6 +1223,13 @@ "@types/react" "*" redux "^3.6.0" +"@types/react-redux@^6.0.9": + version "6.0.9" + resolved "http://localhost:4873/@types%2freact-redux/-/react-redux-6.0.9.tgz#96aa7f5b0716bcc3bfb36ceaa1223118d509f79a" + dependencies: + "@types/react" "*" + redux "^4.0.0" + "@types/react-router-dom@^4.0.4": version "4.2.6" resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.2.6.tgz#9f7eb3c0e6661a9607d878ff8675cc4ea95cd276" @@ -1275,7 +1282,7 @@ "@types/redux@^3.6.0": version "3.6.0" - resolved "https://registry.yarnpkg.com/@types/redux/-/redux-3.6.0.tgz#f1ebe1e5411518072e4fdfca5c76e16e74c1399a" + resolved "http://localhost:4873/@types%2fredux/-/redux-3.6.0.tgz#f1ebe1e5411518072e4fdfca5c76e16e74c1399a" dependencies: redux "*" @@ -11683,6 +11690,12 @@ polished@^1.9.3: version "1.9.3" resolved "https://registry.npmjs.org/polished/-/polished-1.9.3.tgz#d61b8a0c4624efe31e2583ff24a358932b6b75e1" +polished@^2.2.0: + version "2.2.0" + resolved "http://localhost:4873/polished/-/polished-2.2.0.tgz#5ca7e178cc5352bd7fd1efc45342f7c6d59cc982" + dependencies: + "@babel/runtime" "^7.0.0" + popper.js@1.14.3, popper.js@^1.14.1: version "1.14.3" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095" @@ -12643,9 +12656,9 @@ react-popper@^1.0.0-beta.6: typed-styles "^0.0.5" warning "^3.0.0" -react-redux@^5.0.3: +react-redux@^5.0.3, react-redux@^5.0.7: version "5.0.7" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.7.tgz#0dc1076d9afb4670f993ffaef44b8f8c1155a4c8" + resolved "http://localhost:4873/react-redux/-/react-redux-5.0.7.tgz#0dc1076d9afb4670f993ffaef44b8f8c1155a4c8" dependencies: hoist-non-react-statics "^2.5.0" invariant "^2.0.0" @@ -13022,9 +13035,9 @@ redux-devtools-extension@^2.13.2: version "2.13.2" resolved "https://registry.yarnpkg.com/redux-devtools-extension/-/redux-devtools-extension-2.13.2.tgz#e0f9a8e8dfca7c17be92c7124958a3b94eb2911d" -redux@*: +redux@*, redux@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.0.tgz#aa698a92b729315d22b34a0553d7e6533555cc03" + resolved "http://localhost:4873/redux/-/redux-4.0.0.tgz#aa698a92b729315d22b34a0553d7e6533555cc03" dependencies: loose-envify "^1.1.0" symbol-observable "^1.2.0" @@ -14619,6 +14632,20 @@ styled-components@^3.3.3: stylis-rule-sheet "^0.0.10" supports-color "^3.2.3" +styled-components@^3.4.9: + version "3.4.9" + resolved "http://localhost:4873/styled-components/-/styled-components-3.4.9.tgz#519abeb351b37be5b7de6a15ff9e4efeb9d772da" + dependencies: + buffer "^5.0.3" + css-to-react-native "^2.0.3" + fbjs "^0.8.16" + hoist-non-react-statics "^2.5.0" + prop-types "^15.5.4" + react-is "^16.3.1" + stylis "^3.5.0" + stylis-rule-sheet "^0.0.10" + supports-color "^3.2.3" + stylis-rule-sheet@^0.0.10: version "0.0.10" resolved "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430" |