diff options
author | Fabio Berger <me@fabioberger.com> | 2018-10-09 02:12:52 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-09 02:12:52 +0800 |
commit | 9654397b292ee03c503313e3fbb127ebb4b7d76b (patch) | |
tree | b1c9423b9b1c41de8481db83c4987cfeb500e216 /packages/website/ts/components | |
parent | 3991e66a58f28dbed5e75f74ef4aaaf6bb3a4d3e (diff) | |
parent | 6cc9631ef6458d88249a5abd5c7c5ee7b3614e62 (diff) | |
download | dexon-sol-tools-9654397b292ee03c503313e3fbb127ebb4b7d76b.tar dexon-sol-tools-9654397b292ee03c503313e3fbb127ebb4b7d76b.tar.gz dexon-sol-tools-9654397b292ee03c503313e3fbb127ebb4b7d76b.tar.bz2 dexon-sol-tools-9654397b292ee03c503313e3fbb127ebb4b7d76b.tar.lz dexon-sol-tools-9654397b292ee03c503313e3fbb127ebb4b7d76b.tar.xz dexon-sol-tools-9654397b292ee03c503313e3fbb127ebb4b7d76b.tar.zst dexon-sol-tools-9654397b292ee03c503313e3fbb127ebb4b7d76b.zip |
Merge pull request #1103 from 0xProject/doc-overview-page
Implement Developer Home
Diffstat (limited to 'packages/website/ts/components')
17 files changed, 445 insertions, 269 deletions
diff --git a/packages/website/ts/components/documentation/docs_logo.tsx b/packages/website/ts/components/documentation/docs_logo.tsx new file mode 100644 index 000000000..b727fea36 --- /dev/null +++ b/packages/website/ts/components/documentation/docs_logo.tsx @@ -0,0 +1,20 @@ +import { Link } from '@0xproject/react-shared'; +import * as React from 'react'; +import { WebsitePaths } from 'ts/types'; + +export interface DocsLogoProps { + height: number; + containerStyle?: React.CSSProperties; +} + +export const DocsLogo: React.StatelessComponent<DocsLogoProps> = props => { + return ( + <Link to={WebsitePaths.Docs}> + <img src="/images/docs_logo.svg" height={props.height} /> + </Link> + ); +}; + +DocsLogo.defaultProps = { + containerStyle: {}, +}; diff --git a/packages/website/ts/components/documentation/docs_top_bar.tsx b/packages/website/ts/components/documentation/docs_top_bar.tsx new file mode 100644 index 000000000..9a2146f9c --- /dev/null +++ b/packages/website/ts/components/documentation/docs_top_bar.tsx @@ -0,0 +1,162 @@ +import { ALink, colors, Link, NestedSidebarMenu } from '@0xproject/react-shared'; +import { ObjectMap } from '@0xproject/types'; +import * as _ from 'lodash'; +import Drawer from 'material-ui/Drawer'; +import * as React from 'react'; +import { DocsLogo } from 'ts/components/documentation/docs_logo'; +import { Container } from 'ts/components/ui/container'; +import { Text } from 'ts/components/ui/text'; +import { Deco, Key, WebsitePaths } from 'ts/types'; +import { constants } from 'ts/utils/constants'; +import { Translate } from 'ts/utils/translate'; + +export interface DocsTopBarProps { + location: Location; + translate: Translate; + sectionNameToLinks?: ObjectMap<ALink[]>; +} + +interface DocsTopBarState { + isDrawerOpen: boolean; +} + +interface MenuItemInfo { + title: string; + url: string; + iconUrl: string; + fontColor: string; + fontWeight?: string; +} + +export class DocsTopBar extends React.Component<DocsTopBarProps, DocsTopBarState> { + constructor(props: DocsTopBarProps) { + super(props); + this.state = { + isDrawerOpen: false, + }; + } + public componentWillReceiveProps(nextProps: DocsTopBarProps): void { + if (nextProps.location.pathname !== this.props.location.pathname) { + this.setState({ + isDrawerOpen: false, + }); + } + } + public render(): React.ReactNode { + const menuItemInfos: MenuItemInfo[] = [ + { + title: this.props.translate.get(Key.Github, Deco.Cap), + url: constants.URL_GITHUB_ORG, + iconUrl: '/images/developers/github_icon.svg', + fontColor: colors.linkSectionGrey, + }, + { + title: this.props.translate.get(Key.Forum, Deco.Cap), + url: constants.URL_FORUM, + iconUrl: '/images/developers/forum_icon.svg', + fontColor: colors.linkSectionGrey, + }, + { + title: this.props.translate.get(Key.LiveChat, Deco.Cap), + url: constants.URL_ZEROEX_CHAT, + iconUrl: '/images/developers/chat_icon.svg', + fontColor: colors.lightLinkBlue, + fontWeight: 'bold', + }, + ]; + return ( + <Container height={80}> + <Container className="flex items-center lg-pt3 md-pt3 sm-pt1 relative" width="100%"> + <Container className="col col-2 sm-hide xs-hide"> + <Link + to={WebsitePaths.Home} + fontColor={colors.linkSectionGrey} + className="flex items-center text-decoration-none" + > + <i className="zmdi zmdi-chevron-left bold" style={{ fontSize: 16 }} /> + <Container paddingLeft="8px"> + <Text fontSize="16px" fontColor={colors.linkSectionGrey}> + 0xproject.com + </Text> + </Container> + </Link> + </Container> + <Container className="col col-4 md-hide sm-hide xs-hide" /> + <Container className="col col-6 md-pl4 md-ml4 sm-hide xs-hide"> + <Container className="flex items-center justify-between right" width="300px"> + {this._renderMenuItems(menuItemInfos)} + </Container> + </Container> + <Container className="lg-hide md-hide"> + <Container paddingTop="6px" paddingLeft="18px"> + <DocsLogo height={30} /> + </Container> + </Container> + <Container className="md-hide lg-hide absolute" right="18px" top="12px"> + <i + className="zmdi zmdi-menu" + style={{ + color: colors.grey700, + fontSize: 30, + cursor: 'pointer', + }} + onClick={this._onMenuButtonClick.bind(this)} + /> + </Container> + </Container> + <Container width={'100%'} height={'1px'} backgroundColor={colors.grey300} marginTop={'11px'} /> + {this._renderDrawer()} + </Container> + ); + } + private _renderMenuItems(menuItemInfos: MenuItemInfo[]): React.ReactNode { + const menuItems = _.map(menuItemInfos, menuItemInfo => { + return ( + <a + key={`menu-item-${menuItemInfo.title}`} + href={menuItemInfo.url} + target="_blank" + className="text-decoration-none" + > + <Container className="flex"> + <img src={menuItemInfo.iconUrl} width="18" /> + <Container className="flex items-center" paddingLeft="4px"> + <Text + fontSize="16px" + fontWeight={menuItemInfo.fontWeight || 'normal'} + fontColor={menuItemInfo.fontColor} + > + {menuItemInfo.title} + </Text> + </Container> + </Container> + </a> + ); + }); + return menuItems; + } + private _renderDrawer(): React.ReactNode { + return ( + <Drawer + open={this.state.isDrawerOpen} + docked={false} + openSecondary={true} + onRequestChange={this._onMenuButtonClick.bind(this)} + > + <Container className="clearfix pl1"> + <NestedSidebarMenu + sectionNameToLinks={this.props.sectionNameToLinks} + shouldDisplaySectionHeaders={true} + shouldReformatMenuItemNames={false} + onMenuItemClick={this._onMenuButtonClick.bind(this)} + /> + </Container> + </Drawer> + ); + } + private _onMenuButtonClick(): void { + this.setState({ + isDrawerOpen: !this.state.isDrawerOpen, + }); + } +} diff --git a/packages/website/ts/components/documentation/tutorial_button.tsx b/packages/website/ts/components/documentation/tutorial_button.tsx new file mode 100644 index 000000000..dc00bf743 --- /dev/null +++ b/packages/website/ts/components/documentation/tutorial_button.tsx @@ -0,0 +1,59 @@ +import { colors, Link } from '@0xproject/react-shared'; +import * as _ from 'lodash'; +import * as React from 'react'; +import { Container } from 'ts/components/ui/container'; +import { Text } from 'ts/components/ui/text'; +import { Deco, Key, TutorialInfo } from 'ts/types'; +import { Translate } from 'ts/utils/translate'; + +import { styled } from 'ts/style/theme'; + +export interface TutorialButtonProps { + className?: string; + translate: Translate; + tutorialInfo: TutorialInfo; +} + +const PlainTutorialButton: React.StatelessComponent<TutorialButtonProps> = ({ translate, tutorialInfo, className }) => ( + <Container className={className}> + <Link to={tutorialInfo.link.to} shouldOpenInNewTab={tutorialInfo.link.shouldOpenInNewTab}> + <div className="flex relative"> + <div className="col col-1 flex items-center sm-pr3"> + <img src={tutorialInfo.iconUrl} height={40} /> + </div> + <div className="lg-pl2 md-pl2 sm-pl3 col col-10"> + <Text Tag="div" fontSize="18" fontColor={colors.lightLinkBlue} fontWeight="bold"> + {translate.get(tutorialInfo.link.title as Key, Deco.Cap)} + </Text> + <Text Tag="div" fontColor={colors.grey750} fontSize="16"> + {translate.get(tutorialInfo.description as Key, Deco.Cap)} + </Text> + </div> + <div className="col col-1 flex items-center justify-end"> + <div className="right"> + <i + className="zmdi zmdi-chevron-right bold" + style={{ fontSize: 26, color: colors.lightLinkBlue }} + /> + </div> + </div> + </div> + </Link> + </Container> +); + +export const TutorialButton = styled(PlainTutorialButton)` + border-radius: 4px; + border: 1px solid ${colors.grey325}; + background-color: ${colors.white}; + &:hover { + border: 1px solid ${colors.lightLinkBlue}; + background-color: ${colors.lightestBlue}; + } + padding: 20px; + margin-bottom: 15px; +`; + +TutorialButton.defaultProps = {}; + +TutorialButton.displayName = 'TutorialButton'; diff --git a/packages/website/ts/components/dropdowns/developers_drop_down.tsx b/packages/website/ts/components/dropdowns/developers_drop_down.tsx index d66e75722..df5dc173d 100644 --- a/packages/website/ts/components/dropdowns/developers_drop_down.tsx +++ b/packages/website/ts/components/dropdowns/developers_drop_down.tsx @@ -1,69 +1,67 @@ -import { colors } from '@0xproject/react-shared'; +import { ALink, colors, Link } from '@0xproject/react-shared'; import * as _ from 'lodash'; import * as React from 'react'; -import { Link } from 'react-router-dom'; import { Container } from 'ts/components/ui/container'; import { DropDown } from 'ts/components/ui/drop_down'; import { Text } from 'ts/components/ui/text'; -import { Deco, Key, ObjectMap, WebsitePaths } from 'ts/types'; +import { Deco, Key, WebsitePaths } from 'ts/types'; import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; -interface LinkInfo { - link: string; - shouldOpenNewTab: boolean; -} - -const gettingStartedKeyToLinkInfo1: ObjectMap<LinkInfo> = { - [Key.BuildARelayer]: { - link: `${WebsitePaths.Wiki}#Build-A-Relayer`, - shouldOpenNewTab: false, +const gettingStartedKeyToLinkInfo1: ALink[] = [ + { + title: Key.BuildARelayer, + to: `${WebsitePaths.Wiki}#Build-A-Relayer`, }, - [Key.IntroTutorial]: { - link: `${WebsitePaths.Wiki}#Create,-Validate,-Fill-Order`, - shouldOpenNewTab: false, + { + title: Key.OrderBasics, + to: `${WebsitePaths.Wiki}#Create,-Validate,-Fill-Order`, }, -}; -const gettingStartedKeyToLinkInfo2: ObjectMap<LinkInfo> = { - [Key.TradingTutorial]: { - link: `${WebsitePaths.Wiki}#Find,-Submit,-Fill-Order-From-Relayer`, - shouldOpenNewTab: false, +]; +const gettingStartedKeyToLinkInfo2: ALink[] = [ + { + title: Key.DevelopOnEthereum, + to: `${WebsitePaths.Wiki}#Ethereum-Development`, }, - [Key.EthereumDevelopment]: { - link: `${WebsitePaths.Wiki}#Ethereum-Development`, - shouldOpenNewTab: false, + { + title: Key.UseSharedLiquidity, + to: `${WebsitePaths.Wiki}#Find,-Submit,-Fill-Order-From-Relayer`, }, -}; -const popularDocsToLinkInfos: ObjectMap<LinkInfo> = { - [Key.ZeroExJs]: { - link: WebsitePaths.ZeroExJs, - shouldOpenNewTab: false, +]; +const popularDocsToLinkInfos: ALink[] = [ + { + title: Key.ZeroExJs, + to: WebsitePaths.ZeroExJs, }, - [Key.Connect]: { - link: WebsitePaths.Connect, - shouldOpenNewTab: false, + { + title: Key.Connect, + to: WebsitePaths.Connect, }, - [Key.SmartContract]: { - link: WebsitePaths.SmartContracts, - shouldOpenNewTab: false, + { + title: Key.SmartContract, + to: WebsitePaths.SmartContracts, }, -}; -const usefulLinksToLinkInfo: ObjectMap<LinkInfo> = { - [Key.Github]: { - link: constants.URL_GITHUB_ORG, - shouldOpenNewTab: true, +]; +const usefulLinksToLinkInfo: ALink[] = [ + { + title: Key.Github, + to: constants.URL_GITHUB_ORG, + shouldOpenInNewTab: true, }, - [Key.Whitepaper]: { - link: WebsitePaths.Whitepaper, - shouldOpenNewTab: true, + { + title: Key.Whitepaper, + to: WebsitePaths.Whitepaper, + shouldOpenInNewTab: true, }, - [Key.Sandbox]: { - link: constants.URL_SANDBOX, - shouldOpenNewTab: true, + { + title: Key.Sandbox, + to: constants.URL_SANDBOX, + shouldOpenInNewTab: true, }, -}; +]; interface DevelopersDropDownProps { + location: Location; translate: Translate; menuItemStyles: React.CSSProperties; menuIconStyle: React.CSSProperties; @@ -93,96 +91,75 @@ export class DevelopersDropDown extends React.Component<DevelopersDropDownProps, } private _renderDropdownMenu(): React.ReactNode { const dropdownMenu = ( - <div> + <Container> <Container padding="1.75rem"> {this._renderTitle('Getting started')} - <div className="flex"> - <div className="pr4 mr2">{this._renderLinkSection(gettingStartedKeyToLinkInfo1)}</div> - <div>{this._renderLinkSection(gettingStartedKeyToLinkInfo2)}</div> - </div> + <Container className="flex"> + <Container className="pr4 mr2"> + {this._renderLinkSection(gettingStartedKeyToLinkInfo1)} + </Container> + <Container>{this._renderLinkSection(gettingStartedKeyToLinkInfo2)}</Container> + </Container> + </Container> + <Container width="100%" height="1px" backgroundColor={colors.grey300} /> + <Container className="flex" padding="1.75rem"> + <Container className="pr4 mr2"> + <Container>{this._renderTitle('Popular docs')}</Container> + <Container>{this._renderLinkSection(popularDocsToLinkInfos)}</Container> + </Container> + <Container> + <Container>{this._renderTitle('Useful links')}</Container> + <Container>{this._renderLinkSection(usefulLinksToLinkInfo)}</Container> + </Container> </Container> - <div - style={{ - width: '100%', - height: 1, - backgroundColor: colors.grey300, - }} - /> - <div className="flex" style={{ padding: '1.75rem' }}> - <div className="pr4 mr2"> - <div>{this._renderTitle('Popular docs')}</div> - <div>{this._renderLinkSection(popularDocsToLinkInfos)}</div> - </div> - <div> - <div>{this._renderTitle('Useful links')}</div> - <div>{this._renderLinkSection(usefulLinksToLinkInfo)}</div> - </div> - </div> - <div - style={{ - padding: '0.8rem', - textAlign: 'center', - backgroundColor: colors.lightBgGrey, - borderBottomLeftRadius: 4, - borderBottomRightRadius: 4, - }} - > - <Link - to={WebsitePaths.ZeroExJs} - className="text-decoration-none" - style={{ - color: colors.lightBlueA700, - fontWeight: 'bold', - fontSize: 14, - }} + <Link to={WebsitePaths.Docs} fontColor={colors.lightBlueA700}> + <Container + padding="0.9rem" + backgroundColor={colors.lightBgGrey} + borderBottomLeftRadius={4} + borderBottomRightRadius={4} > - {this.props.translate.get(Key.ViewAllDocumentation, Deco.Upper)} - </Link> - </div> - </div> + <Text fontColor={colors.lightBlueA700} fontWeight="bold" fontSize="14px" textAlign="center"> + {this.props.translate.get(Key.ViewAllDocumentation, Deco.Upper)} + </Text> + </Container> + </Link> + </Container> ); return dropdownMenu; } private _renderTitle(title: string): React.ReactNode { return ( - <div - style={{ - color: colors.linkSectionGrey, - fontSize: 14, - paddingBottom: 12, - fontWeight: 600, - letterSpacing: 1, - }} - > - {title.toUpperCase()} - </div> + <Container paddingBottom="12px"> + <Text letterSpacing={1} fontColor={colors.linkSectionGrey} fontSize="14px" fontWeight={600}> + {title.toUpperCase()} + </Text> + </Container> ); } - private _renderLinkSection(keyToLinkInfo: ObjectMap<LinkInfo>): React.ReactNode { - const linkStyle: React.CSSProperties = { - color: colors.lightBlueA700, - fontFamily: 'Roboto, Roboto Mono', - }; - const numLinks = _.size(keyToLinkInfo); + private _renderLinkSection(links: ALink[]): React.ReactNode { + const numLinks = links.length; let i = 0; - const links = _.map(keyToLinkInfo, (linkInfo: LinkInfo, key: string) => { + const renderLinks = _.map(links, (link: ALink) => { + const isWikiLink = _.startsWith(link.to, WebsitePaths.Wiki) && _.includes(link.to, '#'); + const isOnWiki = this.props.location.pathname === WebsitePaths.Wiki; + let to = link.to; + if (isWikiLink && isOnWiki) { + to = `${link.to.split('#')[1]}`; + } i++; const isLast = i === numLinks; - const linkText = this.props.translate.get(key as Key, Deco.CapWords); + const linkText = this.props.translate.get(link.title as Key, Deco.Cap); return ( - <div className={`pr1 pt1 ${!isLast && 'pb1'}`} key={`dev-dropdown-link-${key}`}> - {linkInfo.shouldOpenNewTab ? ( - <a target="_blank" className="text-decoration-none" style={linkStyle} href={linkInfo.link}> - {linkText} - </a> - ) : ( - <Link to={linkInfo.link} className="text-decoration-none" style={linkStyle}> + <Container className={`pr1 pt1 ${!isLast && 'pb1'}`} key={`dev-dropdown-link-${link.title}`}> + <Link to={to} shouldOpenInNewTab={!!link.shouldOpenInNewTab}> + <Text fontFamily="Roboto, Roboto Mono" fontColor={colors.lightBlueA700}> {linkText} - </Link> - )} - </div> + </Text> + </Link> + </Container> ); }); - return <div>{links}</div>; + return <Container>{renderLinks}</Container>; } } diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx index 3c3155349..c1bbadfde 100644 --- a/packages/website/ts/components/fill_order.tsx +++ b/packages/website/ts/components/fill_order.tsx @@ -1,5 +1,5 @@ import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils'; -import { colors } from '@0xproject/react-shared'; +import { colors, Link } from '@0xproject/react-shared'; import { BigNumber, logUtils } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as accounting from 'accounting'; @@ -8,7 +8,6 @@ import { Card, CardHeader, CardText } from 'material-ui/Card'; import Divider from 'material-ui/Divider'; import RaisedButton from 'material-ui/RaisedButton'; import * as React from 'react'; -import { Link } from 'react-router-dom'; import { Blockchain } from 'ts/blockchain'; import { TrackTokenConfirmationDialog } from 'ts/components/dialogs/track_token_confirmation_dialog'; import { FillOrderJSON } from 'ts/components/fill_order_json'; @@ -324,7 +323,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> { return ( <div> Order successfully filled. See the trade details in your{' '} - <Link to={`${WebsitePaths.Portal}/trades`} style={{ color: colors.white }}> + <Link to={`${WebsitePaths.Portal}/trades`} fontColor={colors.white}> trade history </Link> </div> diff --git a/packages/website/ts/components/footer.tsx b/packages/website/ts/components/footer.tsx index 6dcb5a0e9..f11ecae19 100644 --- a/packages/website/ts/components/footer.tsx +++ b/packages/website/ts/components/footer.tsx @@ -1,31 +1,17 @@ -import { colors } from '@0xproject/react-shared'; +import { ALink, colors, Link } from '@0xproject/react-shared'; +import { ObjectMap } from '@0xproject/types'; import * as _ from 'lodash'; import DropDownMenu from 'material-ui/DropDownMenu'; import MenuItem from 'material-ui/MenuItem'; import * as React from 'react'; -import { Link } from 'react-router-dom'; + import { Dispatcher } from 'ts/redux/dispatcher'; import { Deco, Key, Language, WebsitePaths } from 'ts/types'; import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; -interface MenuItemsBySection { - [sectionName: string]: FooterMenuItem[]; -} - -interface FooterMenuItem { - title: string; - path?: string; - isExternal?: boolean; -} - const ICON_DIMENSION = 16; -const linkStyle = { - color: colors.white, - cursor: 'pointer', -}; - const languageToMenuTitle = { [Language.English]: 'English', [Language.Russian]: 'Русский', @@ -51,76 +37,74 @@ export class Footer extends React.Component<FooterProps, FooterState> { }; } public render(): React.ReactNode { - const menuItemsBySection: MenuItemsBySection = { + const sectionNameToLinks: ObjectMap<ALink[]> = { [Key.Documentation]: [ { title: '0x.js', - path: WebsitePaths.ZeroExJs, + to: WebsitePaths.ZeroExJs, }, { title: this.props.translate.get(Key.SmartContracts, Deco.Cap), - path: WebsitePaths.SmartContracts, + to: WebsitePaths.SmartContracts, }, { title: this.props.translate.get(Key.Connect, Deco.Cap), - path: WebsitePaths.Connect, + to: WebsitePaths.Connect, }, { title: this.props.translate.get(Key.Whitepaper, Deco.Cap), - path: WebsitePaths.Whitepaper, - isExternal: true, + to: WebsitePaths.Whitepaper, + shouldOpenInNewTab: true, }, { title: this.props.translate.get(Key.Wiki, Deco.Cap), - path: WebsitePaths.Wiki, + to: WebsitePaths.Wiki, }, { title: this.props.translate.get(Key.Faq, Deco.Cap), - path: WebsitePaths.FAQ, + to: WebsitePaths.FAQ, }, ], [Key.Community]: [ { title: this.props.translate.get(Key.RocketChat, Deco.Cap), - isExternal: true, - path: constants.URL_ZEROEX_CHAT, + to: constants.URL_ZEROEX_CHAT, + shouldOpenInNewTab: true, }, { title: this.props.translate.get(Key.Blog, Deco.Cap), - isExternal: true, - path: constants.URL_BLOG, + to: constants.URL_BLOG, + shouldOpenInNewTab: true, }, { title: 'Twitter', - isExternal: true, - path: constants.URL_TWITTER, + to: constants.URL_TWITTER, + shouldOpenInNewTab: true, }, { title: 'Reddit', - isExternal: true, - path: constants.URL_REDDIT, + to: constants.URL_REDDIT, + shouldOpenInNewTab: true, }, { title: this.props.translate.get(Key.Forum, Deco.Cap), - isExternal: true, - path: constants.URL_DISCOURSE_FORUM, + to: constants.URL_DISCOURSE_FORUM, + shouldOpenInNewTab: true, }, ], [Key.Organization]: [ { title: this.props.translate.get(Key.About, Deco.Cap), - isExternal: false, - path: WebsitePaths.About, + to: WebsitePaths.About, }, { title: this.props.translate.get(Key.Careers, Deco.Cap), - isExternal: false, - path: WebsitePaths.Careers, + to: WebsitePaths.Careers, }, { title: this.props.translate.get(Key.Contact, Deco.Cap), - isExternal: true, - path: 'mailto:team@0xproject.com', + to: 'mailto:team@0xproject.com', + shouldOpenInNewTab: true, }, ], }; @@ -160,19 +144,19 @@ export class Footer extends React.Component<FooterProps, FooterState> { <div className="col lg-col-4 md-col-4 col-12"> <div className="lg-right md-right sm-center"> {this._renderHeader(Key.Documentation)} - {_.map(menuItemsBySection[Key.Documentation], this._renderMenuItem.bind(this))} + {_.map(sectionNameToLinks[Key.Documentation], this._renderMenuItem.bind(this))} </div> </div> <div className="col lg-col-4 md-col-4 col-12 lg-pr2 md-pr2"> <div className="lg-right md-right sm-center"> {this._renderHeader(Key.Community)} - {_.map(menuItemsBySection[Key.Community], this._renderMenuItem.bind(this))} + {_.map(sectionNameToLinks[Key.Community], this._renderMenuItem.bind(this))} </div> </div> <div className="col lg-col-4 md-col-4 col-12"> <div className="lg-right md-right sm-center"> {this._renderHeader(Key.Organization)} - {_.map(menuItemsBySection[Key.Organization], this._renderMenuItem.bind(this))} + {_.map(sectionNameToLinks[Key.Organization], this._renderMenuItem.bind(this))} </div> </div> </div> @@ -187,7 +171,7 @@ export class Footer extends React.Component<FooterProps, FooterState> { </div> ); } - private _renderMenuItem(item: FooterMenuItem): React.ReactNode { + private _renderMenuItem(link: ALink): React.ReactNode { const titleToIcon: { [title: string]: string } = { [this.props.translate.get(Key.RocketChat, Deco.Cap)]: 'rocketchat.png', [this.props.translate.get(Key.Blog, Deco.Cap)]: 'medium.png', @@ -195,30 +179,26 @@ export class Footer extends React.Component<FooterProps, FooterState> { Reddit: 'reddit.png', [this.props.translate.get(Key.Forum, Deco.Cap)]: 'discourse.png', }; - const iconIfExists = titleToIcon[item.title]; + const iconIfExists = titleToIcon[link.title]; return ( - <div key={item.title} className="sm-center" style={{ fontSize: 13, paddingTop: 25 }}> - {item.isExternal ? ( - <a className="text-decoration-none" style={linkStyle} target="_blank" href={item.path}> + <div key={link.title} className="sm-center" style={{ fontSize: 13, paddingTop: 25 }}> + <Link + to={link.to} + shouldOpenInNewTab={link.shouldOpenInNewTab} + fontColor={colors.white} + className="text-decoration-none" + > + <div> {!_.isUndefined(iconIfExists) ? ( <div className="inline-block"> <div className="pr1 table-cell">{this._renderIcon(iconIfExists)}</div> - <div className="table-cell">{item.title}</div> + <div className="table-cell">{link.title}</div> </div> ) : ( - item.title + link.title )} - </a> - ) : ( - <Link to={item.path} style={linkStyle} className="text-decoration-none"> - <div> - {!_.isUndefined(iconIfExists) && ( - <div className="pr1">{this._renderIcon(iconIfExists)}</div> - )} - {item.title} - </div> - </Link> - )} + </div> + </Link> </div> ); } diff --git a/packages/website/ts/components/inputs/token_amount_input.tsx b/packages/website/ts/components/inputs/token_amount_input.tsx index db093fb68..134d1cc76 100644 --- a/packages/website/ts/components/inputs/token_amount_input.tsx +++ b/packages/website/ts/components/inputs/token_amount_input.tsx @@ -1,9 +1,8 @@ -import { colors } from '@0xproject/react-shared'; +import { colors, Link } from '@0xproject/react-shared'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as _ from 'lodash'; import * as React from 'react'; -import { Link } from 'react-router-dom'; import { Blockchain } from 'ts/blockchain'; import { BalanceBoundedInput } from 'ts/components/inputs/balance_bounded_input'; import { Token, ValidatedBigNumberCallback, WebsitePaths } from 'ts/types'; @@ -112,7 +111,8 @@ export class TokenAmountInput extends React.Component<TokenAmountInputProps, Tok Insufficient allowance.{' '} <Link to={`${WebsitePaths.Portal}/account`} - style={{ cursor: 'pointer', color: colors.darkestGrey }} + textDecoration="underline" + fontColor={colors.darkestGrey} > Set allowance </Link> diff --git a/packages/website/ts/components/portal/back_button.tsx b/packages/website/ts/components/portal/back_button.tsx index ca35abc2b..64a332e07 100644 --- a/packages/website/ts/components/portal/back_button.tsx +++ b/packages/website/ts/components/portal/back_button.tsx @@ -1,7 +1,5 @@ -import { Styles } from '@0xproject/react-shared'; +import { Link, Styles } from '@0xproject/react-shared'; import * as React from 'react'; -import { Link } from 'react-router-dom'; - import { Island } from 'ts/components/ui/island'; import { colors } from 'ts/style/colors'; @@ -27,7 +25,7 @@ const styles: Styles = { export const BackButton = (props: BackButtonProps) => { return ( <div style={{ height: 65, paddingTop: 25 }}> - <Link to={props.to} style={{ textDecoration: 'none' }}> + <Link to={props.to}> <Island className="flex right" style={styles.backButton}> <div style={{ marginLeft: 12 }}> <i style={styles.backButtonIcon} className={`zmdi zmdi-arrow-left`} /> diff --git a/packages/website/ts/components/portal/drawer_menu.tsx b/packages/website/ts/components/portal/drawer_menu.tsx index a6707e86c..3a8c69a70 100644 --- a/packages/website/ts/components/portal/drawer_menu.tsx +++ b/packages/website/ts/components/portal/drawer_menu.tsx @@ -39,7 +39,7 @@ export interface DrawerMenuProps { } export const DrawerMenu = (props: DrawerMenuProps) => { const relayerItemEntry = { - to: `${WebsitePaths.Portal}`, + to: WebsitePaths.Portal, labelText: 'Relayer ecosystem', iconName: 'zmdi-portable-wifi', }; diff --git a/packages/website/ts/components/portal/menu.tsx b/packages/website/ts/components/portal/menu.tsx index 39dab77f5..a3352529c 100644 --- a/packages/website/ts/components/portal/menu.tsx +++ b/packages/website/ts/components/portal/menu.tsx @@ -1,7 +1,7 @@ import { Styles } from '@0xproject/react-shared'; import * as _ from 'lodash'; import * as React from 'react'; -import { MenuItem } from 'ts/components/ui/menu_item'; +import { CustomMenuItem } from 'ts/components/ui/custom_menu_item'; import { colors } from 'ts/style/colors'; import { WebsitePaths } from 'ts/types'; @@ -67,14 +67,14 @@ export const Menu: React.StatelessComponent<MenuProps> = (props: MenuProps) => { {_.map(props.menuItemEntries, entry => { const isSelected = entry.to === props.selectedPath; return ( - <MenuItem key={entry.to} to={entry.to}> + <CustomMenuItem key={entry.to} to={entry.to}> <MenuItemLabel title={entry.labelText} iconName={entry.iconName} selected={isSelected} theme={props.theme} /> - </MenuItem> + </CustomMenuItem> ); })} </div> diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index b42954f60..b8cd45661 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -1,9 +1,9 @@ -import { colors } from '@0xproject/react-shared'; +import { colors, Link } from '@0xproject/react-shared'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; import * as React from 'react'; import * as DocumentTitle from 'react-document-title'; -import { Link, Route, RouteComponentProps, Switch } from 'react-router-dom'; +import { Route, RouteComponentProps, Switch } from 'react-router-dom'; import { Blockchain } from 'ts/blockchain'; import { BlockchainErrDialog } from 'ts/components/dialogs/blockchain_err_dialog'; @@ -317,7 +317,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { }; return ( <Section - header={<BackButton to={`${WebsitePaths.Portal}`} labelText="back to Relayers" />} + header={<BackButton to={WebsitePaths.Portal} labelText="back to Relayers" />} body={<Menu selectedPath={routeComponentProps.location.pathname} theme={menuTheme} />} /> ); @@ -389,9 +389,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { </Container> ); return !shouldStartOnboarding ? ( - <Link to={{ pathname: `${WebsitePaths.Portal}/account` }} style={{ textDecoration: 'none' }}> - {startOnboarding} - </Link> + <Link to={`${WebsitePaths.Portal}/account`}>{startOnboarding}</Link> ) : ( startOnboarding ); diff --git a/packages/website/ts/components/top_bar/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx index c2d753e31..3297befad 100644 --- a/packages/website/ts/components/top_bar/top_bar.tsx +++ b/packages/website/ts/components/top_bar/top_bar.tsx @@ -1,16 +1,10 @@ -import { DocsInfo, DocsMenu } from '@0xproject/react-docs'; -import { - colors, - constants as sharedConstants, - MenuSubsectionsBySection, - NestedSidebarMenu, - Styles, -} from '@0xproject/react-shared'; +import { DocsInfo } from '@0xproject/react-docs'; +import { ALink, colors, constants as sharedConstants, Link, NestedSidebarMenu, Styles } from '@0xproject/react-shared'; +import { ObjectMap } from '@0xproject/types'; import * as _ from 'lodash'; import Drawer from 'material-ui/Drawer'; import MenuItem from 'material-ui/MenuItem'; import * as React from 'react'; -import { Link } from 'react-router-dom'; import { Blockchain } from 'ts/blockchain'; import { DevelopersDropDown } from 'ts/components/dropdowns/developers_drop_down'; import { DrawerMenu } from 'ts/components/portal/drawer_menu'; @@ -40,8 +34,8 @@ export interface TopBarProps { translate: Translate; docsVersion?: string; availableDocVersions?: string[]; - menu?: DocsMenu; - menuSubsectionsBySection?: MenuSubsectionsBySection; + sectionNameToLinks?: ObjectMap<ALink[]>; + subsectionNameToLinks?: ObjectMap<ALink[]>; displayType?: TopBarDisplayType; docsInfo?: DocsInfo; style?: React.CSSProperties; @@ -151,7 +145,7 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { paddingLeft={this.props.paddingLeft} paddingRight={this.props.paddingRight} > - <Link to={`${WebsitePaths.Home}`} className="text-decoration-none"> + <Link to={WebsitePaths.Home}> <img src={logoUrl} height="30" /> </Link> <div className="flex-auto" /> @@ -159,46 +153,43 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { <div className={menuClasses}> <div className="flex items-center justify-between"> <DevelopersDropDown + location={this.props.location} menuItemStyles={styles.menuItem} translate={this.props.translate} menuIconStyle={menuIconStyle} /> <TopBarMenuItem title={this.props.translate.get(Key.Wiki, Deco.Cap)} - path={`${WebsitePaths.Wiki}`} + path={WebsitePaths.Wiki} style={styles.menuItem} isNightVersion={isNightVersion} - isExternal={false} /> <TopBarMenuItem title={this.props.translate.get(Key.Blog, Deco.Cap)} path={constants.URL_BLOG} style={styles.menuItem} isNightVersion={isNightVersion} - isExternal={true} + shouldOpenInNewTab={true} /> <TopBarMenuItem title={this.props.translate.get(Key.About, Deco.Cap)} - path={`${WebsitePaths.About}`} + path={WebsitePaths.About} style={styles.menuItem} isNightVersion={isNightVersion} - isExternal={false} /> <TopBarMenuItem title={this.props.translate.get(Key.Careers, Deco.Cap)} - path={`${WebsitePaths.Careers}`} + path={WebsitePaths.Careers} style={styles.menuItem} isNightVersion={isNightVersion} - isExternal={false} /> <TopBarMenuItem title={this.props.translate.get(Key.TradeCallToAction, Deco.Cap)} - path={`${WebsitePaths.Portal}`} + path={WebsitePaths.Portal} isPrimary={true} style={styles.menuItem} className={`${isExpandedDisplayType && 'md-hide'}`} isNightVersion={isNightVersion} - isExternal={false} /> </div> </div> @@ -260,20 +251,16 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { <div className="pl1 py1 mt3" style={{ backgroundColor: colors.lightGrey }}> {this.props.translate.get(Key.Website, Deco.Cap)} </div> - <Link to={WebsitePaths.Home} className="text-decoration-none"> + <Link to={WebsitePaths.Home}> <MenuItem className="py2">{this.props.translate.get(Key.Home, Deco.Cap)}</MenuItem> </Link> - <Link to={`${WebsitePaths.Wiki}`} className="text-decoration-none"> + <Link to={WebsitePaths.Wiki}> <MenuItem className="py2">{this.props.translate.get(Key.Wiki, Deco.Cap)}</MenuItem> </Link> {_.map(DOC_WEBSITE_PATHS_TO_KEY, (key, websitePath) => { if (!this._doesUrlInclude(websitePath)) { return ( - <Link - key={`drawer-menu-item-${websitePath}`} - to={websitePath} - className="text-decoration-none" - > + <Link key={`drawer-menu-item-${websitePath}`} to={websitePath}> <MenuItem className="py2"> {this.props.translate.get(key, Deco.Cap)}{' '} {this.props.translate.get(Key.Docs, Deco.Cap)} @@ -284,25 +271,25 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { return null; })} {!this._isViewingPortal() && ( - <Link to={`${WebsitePaths.Portal}`} className="text-decoration-none"> + <Link to={WebsitePaths.Portal}> <MenuItem className="py2"> {this.props.translate.get(Key.PortalDApp, Deco.CapWords)} </MenuItem> </Link> )} - <a className="text-decoration-none" target="_blank" href={`${WebsitePaths.Whitepaper}`}> + <Link to={WebsitePaths.Whitepaper} shouldOpenInNewTab={true}> <MenuItem className="py2">{this.props.translate.get(Key.Whitepaper, Deco.Cap)}</MenuItem> - </a> - <Link to={`${WebsitePaths.About}`} className="text-decoration-none"> + </Link> + <Link to={WebsitePaths.About}> <MenuItem className="py2">{this.props.translate.get(Key.About, Deco.Cap)}</MenuItem> </Link> - <Link to={`${WebsitePaths.Careers}`} className="text-decoration-none"> + <Link to={WebsitePaths.Careers}> <MenuItem className="py2">{this.props.translate.get(Key.Careers, Deco.Cap)}</MenuItem> </Link> - <a className="text-decoration-none" target="_blank" href={constants.URL_BLOG}> + <Link to={constants.URL_BLOG} shouldOpenInNewTab={true}> <MenuItem className="py2">{this.props.translate.get(Key.Blog, Deco.Cap)}</MenuItem> - </a> - <Link to={`${WebsitePaths.FAQ}`} className="text-decoration-none"> + </Link> + <Link to={WebsitePaths.FAQ}> <MenuItem className="py2" onClick={this._onMenuButtonClick.bind(this)}> {this.props.translate.get(Key.Faq, Deco.Cap)} </MenuItem> @@ -319,14 +306,14 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { // because the sidebar renders `react-scroll` links which depend on the scroll container already // being rendered. const documentationContainer = document.getElementById(sharedConstants.SCROLL_CONTAINER_ID); - if (!isViewingDocsPage || _.isUndefined(this.props.menu) || _.isNull(documentationContainer)) { + if (!isViewingDocsPage || _.isUndefined(this.props.sectionNameToLinks) || _.isNull(documentationContainer)) { return undefined; } return ( <div className="lg-hide md-hide"> <NestedSidebarMenu - topLevelMenu={this.props.menu} - menuSubsectionsBySection={this.props.menuSubsectionsBySection} + sectionNameToLinks={this.props.sectionNameToLinks} + subsectionNameToLinks={this.props.subsectionNameToLinks} sidebarHeader={this.props.sidebarHeader} shouldDisplaySectionHeaders={false} onMenuItemClick={this._onMenuButtonClick.bind(this)} @@ -345,8 +332,8 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> { return ( <div className="lg-hide md-hide"> <NestedSidebarMenu - topLevelMenu={this.props.menuSubsectionsBySection} - menuSubsectionsBySection={this.props.menuSubsectionsBySection} + sectionNameToLinks={this.props.sectionNameToLinks} + subsectionNameToLinks={this.props.subsectionNameToLinks} sidebarHeader={this.props.sidebarHeader} shouldDisplaySectionHeaders={false} onMenuItemClick={this._onMenuButtonClick.bind(this)} diff --git a/packages/website/ts/components/top_bar/top_bar_menu_item.tsx b/packages/website/ts/components/top_bar/top_bar_menu_item.tsx index 25fab2868..eff5ba66d 100644 --- a/packages/website/ts/components/top_bar/top_bar_menu_item.tsx +++ b/packages/website/ts/components/top_bar/top_bar_menu_item.tsx @@ -1,7 +1,6 @@ -import { colors } from '@0xproject/react-shared'; +import { colors, Link } from '@0xproject/react-shared'; import * as _ from 'lodash'; import * as React from 'react'; -import { Link } from 'react-router-dom'; import { CallToAction } from 'ts/components/ui/button'; @@ -13,7 +12,7 @@ interface TopBarMenuItemProps { title: string; path?: string; isPrimary?: boolean; - isExternal: boolean; + shouldOpenInNewTab?: boolean; style?: React.CSSProperties; className?: string; isNightVersion?: boolean; @@ -26,6 +25,7 @@ export class TopBarMenuItem extends React.Component<TopBarMenuItemProps, TopBarM isPrimary: false, style: DEFAULT_STYLE, className: '', + shouldOpenInNewTab: false, isNightVersion: false, }; public render(): React.ReactNode { @@ -38,20 +38,9 @@ export class TopBarMenuItem extends React.Component<TopBarMenuItemProps, TopBarM ); return ( <div className={`center ${this.props.className}`} style={{ ...this.props.style, color: menuItemColor }}> - {this.props.isExternal ? ( - <a - className="text-decoration-none" - style={{ color: linkColor }} - target="_blank" - href={this.props.path} - > - {itemContent} - </a> - ) : ( - <Link to={this.props.path} className="text-decoration-none" style={{ color: linkColor }}> - {itemContent} - </Link> - )} + <Link to={this.props.path} shouldOpenInNewTab={this.props.shouldOpenInNewTab} fontColor={linkColor}> + {itemContent} + </Link> </div> ); } diff --git a/packages/website/ts/components/ui/container.tsx b/packages/website/ts/components/ui/container.tsx index f2ae68b70..ece077563 100644 --- a/packages/website/ts/components/ui/container.tsx +++ b/packages/website/ts/components/ui/container.tsx @@ -15,7 +15,11 @@ export interface ContainerProps { paddingRight?: StringOrNum; paddingLeft?: StringOrNum; backgroundColor?: string; + background?: string; borderRadius?: StringOrNum; + borderBottomLeftRadius?: StringOrNum; + borderBottomRightRadius?: StringOrNum; + borderBottom?: StringOrNum; maxWidth?: StringOrNum; maxHeight?: StringOrNum; width?: StringOrNum; diff --git a/packages/website/ts/components/ui/menu_item.tsx b/packages/website/ts/components/ui/custom_menu_item.tsx index 0cb4b387c..c25da6be6 100644 --- a/packages/website/ts/components/ui/menu_item.tsx +++ b/packages/website/ts/components/ui/custom_menu_item.tsx @@ -1,24 +1,23 @@ +import { Link } from '@0xproject/react-shared'; import * as _ from 'lodash'; import * as React from 'react'; -import { Link } from 'react-router-dom'; -interface MenuItemProps { +interface CustomMenuItemProps { to: string; - style?: React.CSSProperties; onClick?: () => void; className?: string; } -interface MenuItemState { +interface CustomMenuItemState { isHovering: boolean; } -export class MenuItem extends React.Component<MenuItemProps, MenuItemState> { - public static defaultProps: Partial<MenuItemProps> = { +export class CustomMenuItem extends React.Component<CustomMenuItemProps, CustomMenuItemState> { + public static defaultProps: Partial<CustomMenuItemProps> = { onClick: _.noop.bind(_), className: '', }; - public constructor(props: MenuItemProps) { + public constructor(props: CustomMenuItemProps) { super(props); this.state = { isHovering: false, @@ -30,7 +29,7 @@ export class MenuItem extends React.Component<MenuItemProps, MenuItemState> { opacity: this.state.isHovering ? 0.5 : 1, }; return ( - <Link to={this.props.to} style={{ textDecoration: 'none', ...this.props.style }}> + <Link to={this.props.to}> <div onClick={this.props.onClick.bind(this)} className={`mx-auto ${this.props.className}`} diff --git a/packages/website/ts/components/ui/simple_menu.tsx b/packages/website/ts/components/ui/simple_menu.tsx index 8a9349c6d..bdaf0701e 100644 --- a/packages/website/ts/components/ui/simple_menu.tsx +++ b/packages/website/ts/components/ui/simple_menu.tsx @@ -1,7 +1,7 @@ +import { Link } from '@0xproject/react-shared'; import * as _ from 'lodash'; import * as React from 'react'; import * as CopyToClipboard from 'react-copy-to-clipboard'; -import { Link } from 'react-router-dom'; import { Container } from 'ts/components/ui/container'; import { Text } from 'ts/components/ui/text'; @@ -72,7 +72,7 @@ export const GoToAccountManagementSimpleMenuItem: React.StatelessComponent< GoToAccountManagementSimpleMenuItemProps > = ({ onClick }) => { return ( - <Link to={`${WebsitePaths.Portal}/account`} style={{ textDecoration: 'none' }}> + <Link to={`${WebsitePaths.Portal}/account`}> <SimpleMenuItem displayText="Manage Account..." onClick={onClick} /> </Link> ); diff --git a/packages/website/ts/components/ui/text.tsx b/packages/website/ts/components/ui/text.tsx index cd8f290e3..4415962b1 100644 --- a/packages/website/ts/components/ui/text.tsx +++ b/packages/website/ts/components/ui/text.tsx @@ -19,7 +19,9 @@ export interface TextProps { textDecorationLine?: string; onClick?: (event: React.MouseEvent<HTMLElement>) => void; hoverColor?: string; + letterSpacing?: string | number; noWrap?: boolean; + textAlign?: string; display?: string; } @@ -34,6 +36,8 @@ export const Text = styled(PlainText)` font-style: ${props => props.fontStyle}; font-weight: ${props => props.fontWeight}; font-size: ${props => props.fontSize}; + text-align: ${props => props.textAlign}; + letter-spacing: ${props => props.letterSpacing}; text-decoration-line: ${props => props.textDecorationLine}; ${props => (props.lineHeight ? `line-height: ${props.lineHeight}` : '')}; ${props => (props.center ? 'text-align: center' : '')}; |