diff options
Diffstat (limited to 'packages/website/ts/components/top_bar.tsx')
-rw-r--r-- | packages/website/ts/components/top_bar.tsx | 370 |
1 files changed, 370 insertions, 0 deletions
diff --git a/packages/website/ts/components/top_bar.tsx b/packages/website/ts/components/top_bar.tsx new file mode 100644 index 000000000..6248095b3 --- /dev/null +++ b/packages/website/ts/components/top_bar.tsx @@ -0,0 +1,370 @@ +import * as _ from 'lodash'; +import * as React from 'react'; +import { + Link as ScrollLink, + animateScroll, +} from 'react-scroll'; +import {Link} from 'react-router-dom'; +import {HashLink} from 'react-router-hash-link'; +import AppBar from 'material-ui/AppBar'; +import Drawer from 'material-ui/Drawer'; +import MenuItem from 'material-ui/MenuItem'; +import {colors} from 'material-ui/styles'; +import ReactTooltip = require('react-tooltip'); +import {configs} from 'ts/utils/configs'; +import {constants} from 'ts/utils/constants'; +import {Identicon} from 'ts/components/ui/identicon'; +import {NestedSidebarMenu} from 'ts/pages/shared/nested_sidebar_menu'; +import {typeDocUtils} from 'ts/utils/typedoc_utils'; +import {PortalMenu} from 'ts/components/portal_menu'; +import {Styles, TypeDocNode, MenuSubsectionsBySection, WebsitePaths, Docs} from 'ts/types'; +import {TopBarMenuItem} from 'ts/components/top_bar_menu_item'; +import {DropDownMenuItem} from 'ts/components/ui/drop_down_menu_item'; + +const CUSTOM_DARK_GRAY = '#231F20'; +const SECTION_HEADER_COLOR = 'rgb(234, 234, 234)'; + +interface TopBarProps { + userAddress?: string; + blockchainIsLoaded: boolean; + location: Location; + docsVersion?: string; + availableDocVersions?: string[]; + menuSubsectionsBySection?: MenuSubsectionsBySection; + shouldFullWidth?: boolean; + doc?: Docs; + style?: React.CSSProperties; + isNightVersion?: boolean; +} + +interface TopBarState { + isDrawerOpen: boolean; +} + +const styles: Styles = { + address: { + marginRight: 12, + overflow: 'hidden', + paddingTop: 4, + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + width: 70, + }, + addressPopover: { + backgroundColor: colors.blueGrey500, + color: 'white', + padding: 3, + }, + topBar: { + backgroundColor: 'white', + height: 59, + width: '100%', + position: 'fixed', + top: 0, + zIndex: 1100, + paddingBottom: 1, + }, + bottomBar: { + boxShadow: 'rgba(0, 0, 0, 0.187647) 0px 1px 3px', + }, + menuItem: { + fontSize: 14, + color: CUSTOM_DARK_GRAY, + paddingTop: 6, + paddingBottom: 6, + marginTop: 17, + cursor: 'pointer', + fontWeight: 400, + }, +}; + +export class TopBar extends React.Component<TopBarProps, TopBarState> { + public static defaultProps: Partial<TopBarProps> = { + shouldFullWidth: false, + style: {}, + isNightVersion: false, + }; + constructor(props: TopBarProps) { + super(props); + this.state = { + isDrawerOpen: false, + }; + } + public render() { + const isNightVersion = this.props.isNightVersion; + const isFullWidthPage = this.props.shouldFullWidth; + const parentClassNames = `flex mx-auto ${isFullWidthPage ? 'pl2' : 'max-width-4'}`; + const developerSectionMenuItems = [ + <Link + key="subMenuItem-zeroEx" + to={WebsitePaths.ZeroExJs} + className="text-decoration-none" + > + <MenuItem style={{fontSize: styles.menuItem.fontSize}} primaryText="0x.js" /> + </Link>, + <Link + key="subMenuItem-smartContracts" + to={WebsitePaths.SmartContracts} + className="text-decoration-none" + > + <MenuItem style={{fontSize: styles.menuItem.fontSize}} primaryText="Smart Contracts" /> + </Link>, + <a + key="subMenuItem-standard-relayer-api" + target="_blank" + className="text-decoration-none" + href={constants.STANDARD_RELAYER_API_GITHUB} + > + <MenuItem style={{fontSize: styles.menuItem.fontSize}} primaryText="Standard Relayer API" /> + </a>, + <a + key="subMenuItem-github" + target="_blank" + className="text-decoration-none" + href={constants.GITHUB_URL} + > + <MenuItem style={{ fontSize: styles.menuItem.fontSize }} primaryText="GitHub" /> + </a>, + <a + key="subMenuItem-whitePaper" + target="_blank" + className="text-decoration-none" + href={`${WebsitePaths.Whitepaper}`} + > + <MenuItem style={{fontSize: styles.menuItem.fontSize}} primaryText="Whitepaper" /> + </a>, + ]; + const bottomBorderStyle = this.shouldDisplayBottomBar() ? styles.bottomBar : {}; + const fullWithClassNames = isFullWidthPage ? 'pr4' : ''; + const logoUrl = isNightVersion ? '/images/protocol_logo_white.png' : '/images/protocol_logo_black.png'; + return ( + <div style={{...styles.topBar, ...bottomBorderStyle, ...this.props.style}} className="pb1"> + <div className={parentClassNames}> + <div className="col col-2 sm-pl2 md-pl2 lg-pl0" style={{paddingTop: 15}}> + <Link to={`${WebsitePaths.Home}`} className="text-decoration-none"> + <img src={logoUrl} height="30" /> + </Link> + </div> + <div className={`col col-${isFullWidthPage ? '8' : '9'} lg-hide md-hide`} /> + <div className={`col col-${isFullWidthPage ? '6' : '5'} sm-hide xs-hide`} /> + {!this.isViewingPortal() && + <div className={`col col-${isFullWidthPage ? '4' : '5'} ${fullWithClassNames} lg-pr0 md-pr2 sm-hide xs-hide`}> + <div className="flex justify-between"> + <DropDownMenuItem + title="Developers" + subMenuItems={developerSectionMenuItems} + style={styles.menuItem} + isNightVersion={isNightVersion} + /> + <TopBarMenuItem + title="Wiki" + path={`${WebsitePaths.Wiki}`} + style={styles.menuItem} + isNightVersion={isNightVersion} + /> + <TopBarMenuItem + title="About" + path={`${WebsitePaths.About}`} + style={styles.menuItem} + isNightVersion={isNightVersion} + /> + <TopBarMenuItem + title="Portal DApp" + path={`${WebsitePaths.Portal}`} + isPrimary={true} + style={styles.menuItem} + className={`${isFullWidthPage && 'md-hide'}`} + isNightVersion={isNightVersion} + /> + </div> + </div> + } + {this.props.blockchainIsLoaded && !_.isEmpty(this.props.userAddress) && + <div className="col col-5"> + {this.renderUser()} + </div> + } + {!this.isViewingPortal() && + <div + className={`col ${isFullWidthPage ? 'col-2 pl2' : 'col-1'} md-hide lg-hide`} + > + <div + style={{fontSize: 25, color: isNightVersion ? 'white' : 'black', cursor: 'pointer', paddingTop: 16}} + > + <i + className="zmdi zmdi-menu" + onClick={this.onMenuButtonClick.bind(this)} + /> + </div> + </div> + } + </div> + {this.renderDrawer()} + </div> + ); + } + private renderDrawer() { + return ( + <Drawer + open={this.state.isDrawerOpen} + docked={false} + openSecondary={true} + onRequestChange={this.onMenuButtonClick.bind(this)} + > + {this.renderPortalMenu()} + {this.renderDocsMenu()} + {this.renderWiki()} + <div className="pl1 py1 mt3" style={{backgroundColor: SECTION_HEADER_COLOR}}>Website</div> + <Link to={WebsitePaths.Home} className="text-decoration-none"> + <MenuItem className="py2">Home</MenuItem> + </Link> + <Link to={`${WebsitePaths.Wiki}`} className="text-decoration-none"> + <MenuItem className="py2">Wiki</MenuItem> + </Link> + {!this.isViewing0xjsDocs() && + <Link to={WebsitePaths.ZeroExJs} className="text-decoration-none"> + <MenuItem className="py2">0x.js Docs</MenuItem> + </Link> + } + {!this.isViewingSmartContractsDocs() && + <Link to={WebsitePaths.SmartContracts} className="text-decoration-none"> + <MenuItem className="py2">Smart Contract Docs</MenuItem> + </Link> + } + {!this.isViewingPortal() && + <Link to={`${WebsitePaths.Portal}`} className="text-decoration-none"> + <MenuItem className="py2">Portal DApp</MenuItem> + </Link> + } + <a + className="text-decoration-none" + target="_blank" + href={`${WebsitePaths.Whitepaper}`} + > + <MenuItem className="py2">Whitepaper</MenuItem> + </a> + <Link to={`${WebsitePaths.About}`} className="text-decoration-none"> + <MenuItem className="py2">About</MenuItem> + </Link> + <a + className="text-decoration-none" + target="_blank" + href={constants.BLOG_URL} + > + <MenuItem className="py2">Blog</MenuItem> + </a> + <Link to={`${WebsitePaths.FAQ}`} className="text-decoration-none"> + <MenuItem + className="py2" + onTouchTap={this.onMenuButtonClick.bind(this)} + > + FAQ + </MenuItem> + </Link> + </Drawer> + ); + } + private renderDocsMenu() { + if (!this.isViewing0xjsDocs() && !this.isViewingSmartContractsDocs()) { + return; + } + + const topLevelMenu = this.isViewing0xjsDocs() ? + typeDocUtils.getFinal0xjsMenu(this.props.docsVersion) : + constants.menuSmartContracts; + + const sectionTitle = this.isViewing0xjsDocs() ? '0x.js Docs' : 'Smart contract Docs'; + return ( + <div className="lg-hide md-hide"> + <div className="pl1 py1" style={{backgroundColor: SECTION_HEADER_COLOR}}>{sectionTitle}</div> + <NestedSidebarMenu + topLevelMenu={topLevelMenu} + menuSubsectionsBySection={this.props.menuSubsectionsBySection} + shouldDisplaySectionHeaders={false} + onMenuItemClick={this.onMenuButtonClick.bind(this)} + selectedVersion={this.props.docsVersion} + doc={this.props.doc} + versions={this.props.availableDocVersions} + /> + </div> + ); + } + private renderWiki() { + if (!this.isViewingWiki()) { + return; + } + + return ( + <div className="lg-hide md-hide"> + <div className="pl1 py1" style={{backgroundColor: SECTION_HEADER_COLOR}}>0x Protocol Wiki</div> + <NestedSidebarMenu + topLevelMenu={this.props.menuSubsectionsBySection} + menuSubsectionsBySection={this.props.menuSubsectionsBySection} + shouldDisplaySectionHeaders={false} + onMenuItemClick={this.onMenuButtonClick.bind(this)} + /> + </div> + ); + } + private renderPortalMenu() { + if (!this.isViewingPortal()) { + return; + } + + return ( + <div className="lg-hide md-hide"> + <div className="pl1 py1" style={{backgroundColor: SECTION_HEADER_COLOR}}>Portal DApp</div> + <PortalMenu + menuItemStyle={{color: 'black'}} + onClick={this.onMenuButtonClick.bind(this)} + /> + </div> + ); + } + private renderUser() { + const userAddress = this.props.userAddress; + const identiconDiameter = 26; + return ( + <div + className="flex right lg-pr0 md-pr2 sm-pr2" + style={{paddingTop: 16}} + > + <div + style={styles.address} + data-tip={true} + data-for="userAddressTooltip" + > + {!_.isEmpty(userAddress) ? userAddress : ''} + </div> + <ReactTooltip id="userAddressTooltip">{userAddress}</ReactTooltip> + <div> + <Identicon address={userAddress} diameter={identiconDiameter} /> + </div> + </div> + ); + } + private onMenuButtonClick() { + this.setState({ + isDrawerOpen: !this.state.isDrawerOpen, + }); + } + private isViewingPortal() { + return _.includes(this.props.location.pathname, WebsitePaths.Portal); + } + private isViewingFAQ() { + return _.includes(this.props.location.pathname, WebsitePaths.FAQ); + } + private isViewing0xjsDocs() { + return _.includes(this.props.location.pathname, WebsitePaths.ZeroExJs); + } + private isViewingSmartContractsDocs() { + return _.includes(this.props.location.pathname, WebsitePaths.SmartContracts); + } + private isViewingWiki() { + return _.includes(this.props.location.pathname, WebsitePaths.Wiki); + } + private shouldDisplayBottomBar() { + return this.isViewingWiki() || this.isViewing0xjsDocs() || this.isViewingFAQ() || + this.isViewingSmartContractsDocs(); + } +} |