aboutsummaryrefslogtreecommitdiffstats
path: root/packages/website
diff options
context:
space:
mode:
authorFred Carlsen <fred@sjelfull.no>2018-12-10 18:19:20 +0800
committerFred Carlsen <fred@sjelfull.no>2018-12-10 18:19:20 +0800
commitc99558606347682c6c5c9bb20d37aa4fbe8ab6be (patch)
tree3b6927cac22415c7139dc9a2463664aa1dada1a3 /packages/website
parent8dd738629ad3bc6e07de7499272e3528a26091a3 (diff)
downloaddexon-sol-tools-c99558606347682c6c5c9bb20d37aa4fbe8ab6be.tar
dexon-sol-tools-c99558606347682c6c5c9bb20d37aa4fbe8ab6be.tar.gz
dexon-sol-tools-c99558606347682c6c5c9bb20d37aa4fbe8ab6be.tar.bz2
dexon-sol-tools-c99558606347682c6c5c9bb20d37aa4fbe8ab6be.tar.lz
dexon-sol-tools-c99558606347682c6c5c9bb20d37aa4fbe8ab6be.tar.xz
dexon-sol-tools-c99558606347682c6c5c9bb20d37aa4fbe8ab6be.tar.zst
dexon-sol-tools-c99558606347682c6c5c9bb20d37aa4fbe8ab6be.zip
WIP mobile header + developer dropdown
Diffstat (limited to 'packages/website')
-rw-r--r--packages/website/ts/@next/components/dropdowns/developers_drop_down.tsx159
-rw-r--r--packages/website/ts/@next/components/hamburger.tsx68
-rw-r--r--packages/website/ts/@next/components/header.tsx222
3 files changed, 417 insertions, 32 deletions
diff --git a/packages/website/ts/@next/components/dropdowns/developers_drop_down.tsx b/packages/website/ts/@next/components/dropdowns/developers_drop_down.tsx
new file mode 100644
index 000000000..bf75c3b92
--- /dev/null
+++ b/packages/website/ts/@next/components/dropdowns/developers_drop_down.tsx
@@ -0,0 +1,159 @@
+import { ALink, Link } from '@0x/react-shared';
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { colors } from 'ts/style/colors';
+import { Container } from 'ts/components/ui/container';
+import { DropDown } from 'ts/components/ui/drop_down';
+import { Heading, Paragraph } from 'ts/@next/components/text';
+import { Deco, Key, WebsitePaths } from 'ts/types';
+import { constants } from 'ts/utils/constants';
+import { Translate } from 'ts/utils/translate';
+
+const gettingStartedKeyToLinkInfo1: ALink[] = [
+ {
+ title: Key.BuildARelayer,
+ to: `${WebsitePaths.Wiki}#Build-A-Relayer`,
+ },
+ {
+ title: Key.OrderBasics,
+ to: `${WebsitePaths.Wiki}#Create,-Validate,-Fill-Order`,
+ },
+];
+const gettingStartedKeyToLinkInfo2: ALink[] = [
+ {
+ title: Key.DevelopOnEthereum,
+ to: `${WebsitePaths.Wiki}#Ethereum-Development`,
+ },
+ {
+ title: Key.UseNetworkedLiquidity,
+ to: `${WebsitePaths.Wiki}#Find,-Submit,-Fill-Order-From-Relayer`,
+ },
+];
+const popularDocsToLinkInfos: ALink[] = [
+ {
+ title: Key.ZeroExJs,
+ to: WebsitePaths.ZeroExJs,
+ },
+ {
+ title: Key.Connect,
+ to: WebsitePaths.Connect,
+ },
+ {
+ title: Key.SmartContract,
+ to: WebsitePaths.SmartContracts,
+ },
+];
+const usefulLinksToLinkInfo: ALink[] = [
+ {
+ title: Key.Wiki,
+ to: WebsitePaths.Wiki,
+ },
+ {
+ title: Key.Github,
+ to: constants.URL_GITHUB_ORG,
+ shouldOpenInNewTab: true,
+ },
+ {
+ title: Key.Whitepaper,
+ to: WebsitePaths.Whitepaper,
+ shouldOpenInNewTab: true,
+ },
+];
+
+interface DevelopersDropDownProps {
+ location: Location;
+}
+
+interface DevelopersDropDownState {}
+
+export class DevelopersDropDown extends React.Component<DevelopersDropDownProps, DevelopersDropDownState> {
+ public render(): React.ReactNode {
+ const activeNode = (
+ <Paragraph isNoMargin={true}>
+ Developers
+ </Paragraph>
+ );
+ return (
+ <DropDown
+ activeNode={activeNode}
+ popoverContent={this._renderDropdownMenu()}
+ anchorOrigin={{ horizontal: 'left', vertical: 'bottom' }}
+ targetOrigin={{ horizontal: 'left', vertical: 'top' }}
+ popoverStyle={{ borderRadius: 0, width: 420, height: 377, marginTop: 0 }}
+ />
+ );
+ }
+ private _renderDropdownMenu(): React.ReactNode {
+ const sectionPadding = '26px';
+ const dropdownMenu = (
+ <Container>
+ <Container className="flex" padding={sectionPadding}>
+ <Container paddingRight="45px">
+ {this._renderLinkSection(gettingStartedKeyToLinkInfo1, 'Getting started')}
+ </Container>
+ <Container>{this._renderLinkSection(gettingStartedKeyToLinkInfo2)}</Container>
+ </Container>
+ <Container width="100%" height="1px" backgroundColor={colors.grey300} />
+ <Container className="flex" padding={sectionPadding}>
+ <Container paddingRight="62px">
+ <Container>{this._renderLinkSection(popularDocsToLinkInfos, 'Popular docs')}</Container>
+ </Container>
+ <Container>
+ <Container>{this._renderLinkSection(usefulLinksToLinkInfo, 'Useful links')}</Container>
+ </Container>
+ </Container>
+ <Link to={WebsitePaths.Docs} fontColor={colors.brandLight}>
+ <Container
+ padding="0.9rem"
+ backgroundColor={colors.white}
+ borderBottomLeftRadius={4}
+ borderBottomRightRadius={4}
+ >
+ <Paragraph color={colors.brandLight} isCentered={true} isNoMargin={true}>
+ View all documentation
+ </Paragraph>
+ </Container>
+ </Link>
+ </Container>
+ );
+ return dropdownMenu;
+ }
+ private _renderLinkSection(links: ALink[], title: string = ''): React.ReactNode {
+ const numLinks = links.length;
+ let i = 0;
+ 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(link.title as Key, Deco.Cap);
+ const linkText = link.title;
+ return (
+ <Container className={`pr1 pt1 ${!isLast && 'pb1'}`} key={`dev-dropdown-link-${link.title}`}>
+ <Link to={to} shouldOpenInNewTab={!!link.shouldOpenInNewTab}>
+ <Paragraph size="small" color={colors.brandDark} isNoMargin={true}>
+ {linkText}
+ </Paragraph>
+ </Link>
+ </Container>
+ );
+ });
+ return (
+ <Container>
+ <Container height="33px">
+ {!_.isEmpty(title) && (
+ <Heading asElement="h3" size="small">
+ {title}
+ </Heading>
+ )}
+ </Container>
+ {renderLinks}
+ </Container>
+ );
+ }
+}
diff --git a/packages/website/ts/@next/components/hamburger.tsx b/packages/website/ts/@next/components/hamburger.tsx
new file mode 100644
index 000000000..0eac4a53f
--- /dev/null
+++ b/packages/website/ts/@next/components/hamburger.tsx
@@ -0,0 +1,68 @@
+import * as React from 'react';
+import styled from 'styled-components';
+
+interface Props {
+ isOpen: boolean;
+ onClick?: () => void;
+}
+
+export const Hamburger: React.FunctionComponent<Props> = (props: Props) => {
+ return (
+ <StyledHamburger isOpen={props.isOpen} onClick={props.onClick}>
+ <span />
+ <span />
+ <span />
+ </StyledHamburger>
+ );
+};
+
+const StyledHamburger = styled.button<Props>`
+ background: none;
+ border: 0;
+ width: 22px;
+ height: 16px;
+ position: relative;
+ z-index: 2;
+ padding: 0;
+ outline: none;
+ user-select: none;
+
+ @media (min-width: 768px) {
+ display: none;
+ }
+
+ span {
+ display: block;
+ background-color: #fff;
+ width: 100%;
+ height: 2px;
+ margin-bottom: 5px;
+ transform-origin: 4px 0px;
+ transition: transform 0.5s cubic-bezier(0.77,0.2,0.05,1.0),
+ background-color 0.5s cubic-bezier(0.77,0.2,0.05,1.0),
+ opacity 0.55s ease;
+
+ &:first-child {
+ //transform-origin: 0% 0%;
+ }
+
+ &:last-child {
+ //transform-origin: 0% 100%;
+ }
+
+ ${props => props.isOpen && `
+ opacity: 1;
+ transform: rotate(45deg) translate(0, 1px);
+ background-color: #fff;
+
+ &:nth-child(2) {
+ opacity: 0;
+ transform: rotate(0deg) scale(0.2, 0.2);
+ }
+
+ &:last-child {
+ transform: rotate(-45deg) translate(1px, -4px);
+ }
+ `}
+ }
+`;
diff --git a/packages/website/ts/@next/components/header.tsx b/packages/website/ts/@next/components/header.tsx
index a6bbe4d65..e4add9ecf 100644
--- a/packages/website/ts/@next/components/header.tsx
+++ b/packages/website/ts/@next/components/header.tsx
@@ -3,48 +3,206 @@ import * as React from 'react';
import { Link as ReactRouterLink } from 'react-router-dom';
import styled from 'styled-components';
+import { colors } from 'ts/style/colors';
+
import { Button, ButtonWrap, Link } from 'ts/@next/components/button';
+import { DevelopersDropDown } from 'ts/@next/components/dropdowns/developers_drop_down';
+import { Hamburger } from 'ts/@next/components/hamburger';
import { Section, Wrap } from 'ts/@next/components/layout';
import { Logo } from 'ts/@next/components/logo';
+import { Paragraph } from 'ts/@next/components/text';
interface HeaderProps {
+ isOpen: boolean;
+ location?: Location;
+}
+
+interface HeaderState {
+ isOpen: boolean;
+}
+
+interface HeaderState {
+ isOpen: boolean;
+}
+
+interface NavItem {
+ url?: string;
+ id?: string;
+ text?: string;
}
-const links = [
- { url: '/next/why', text: 'Why 0x' },
- { url: '/next/0x-instant', text: 'Products' },
- { url: '#', text: 'Developers' },
- { url: '/next/about/mission', text: 'About' },
- { url: '#', text: 'Blog' },
+const mobileProductLinks = [
+ { url: '/next/0x-instant', text: '0x Instant' },
+ { url: '/next/launch-kit', text: '0x Launch Kit' },
+];
+
+const navItems: NavItem[] = [
+ { id: 'why', url: '/next/why', text: 'Why 0x' },
+ { id: 'products', url: '/next/0x-instant', text: 'Products' },
+ { id: 'developers', url: '#', text: 'Developers' },
+ { id: 'about', url: '/next/about/mission', text: 'About' },
+ { id: 'blog', url: '#', text: 'Blog' },
];
-export const Header: React.StatelessComponent<HeaderProps> = ({}) => (
- <StyledHeader>
- <HeaderWrap>
- <ReactRouterLink to="/next">
- <Logo/>
- </ReactRouterLink>
-
- <ButtonWrap>
- {_.map(links, (link, index) => (
- <Link
- key={`hb-${index}`}
- href={link.url}
- isTransparent={true}
- isNoBorder={true}
- >
- {link.text}
- </Link>
- ))}
- </ButtonWrap>
-
- <Button href="#">Trade on 0x</Button>
- </HeaderWrap>
- </StyledHeader>
-);
-
-const StyledHeader = Section.withComponent('header');
+export class Header extends React.Component<HeaderProps, HeaderState> {
+ constructor(props: HeaderProps) {
+ super(props);
+ this.state = {
+ isOpen: false,
+ };
+ }
+ public render(): React.ReactNode {
+ return (
+ <StyledHeader isOpen={this.state.isOpen}>
+ <HeaderWrap>
+ <ReactRouterLink to="/next">
+ <Logo/>
+ </ReactRouterLink>
+ <Hamburger isOpen={this.state.isOpen} onClick={this._onMenuButtonClick.bind(this)}/>
+ <Nav>
+ <MobileProductLinksWrap>
+ <Paragraph isNoMargin={true} isMuted={0.5} size="small">Products</Paragraph>
+ {_.map(mobileProductLinks, (link, index) => (
+ <StyledLink
+ key={`productlink-${index}`}
+ href={link.url}
+ isTransparent={true}
+ isNoBorder={true}
+ >
+ {link.text}
+ </StyledLink>
+ ))}
+ </MobileProductLinksWrap>
+ <StyledButtonWrap>
+ {_.map(navItems, (link, index) => this._getNavItem(link, index))}
+ </StyledButtonWrap>
+ </Nav>
+ <TradeButton href="#">Trade on 0x</TradeButton>
+ </HeaderWrap>
+ </StyledHeader>
+ );
+ }
+ private _onMenuButtonClick(): void {
+ this.setState({
+ isOpen: !this.state.isOpen,
+ });
+ }
+ private _getNavItem(link: NavItem, index: number): React.ReactNode {
+ if (link.id === 'developers') {
+ return (
+ <DevelopersDropDown
+ location={window.location}
+ />
+ );
+ }
+
+ return (
+ <StyledLink
+ key={`header-nav-item-${index}`}
+ href={link.url}
+ isTransparent={true}
+ isNoBorder={true}
+ >
+ {link.text}
+ </StyledLink>
+ )
+ }
+}
+
+const StyledHeader = styled(Section.withComponent('header'))<HeaderProps>`
+ @media (max-width: 768px) {
+ overflow: hidden;
+ min-height: ${props => props.isOpen ? '385px' : '70px'};
+ position: relative;
+ transition: min-height 0.25s ease-in-out;
+ :root & {
+ padding: 20px 20px 0 !important;
+ }
+ }
+`;
+
const HeaderWrap = styled(Wrap)`
justify-content: space-between;
align-items: center;
+
+ @media (max-width: 768px) {
+ padding-top: 0;
+ display: flex;
+ padding-bottom: 0;
+ }
+`;
+
+const StyledButtonWrap = styled(ButtonWrap)`
+ display: flex;
+ @media (max-width: 768px) {
+ background-color: #022924;
+ display: flex;
+ flex-wrap: wrap;
+ padding: 20px 20px;
+
+ a {
+ text-align: left;
+ padding-left: 0;
+ }
+ }
+
+ button + button,
+ a + a,
+ a + button,
+ button + a {
+ margin-left: 0;
+
+ @media (min-width: 768px) {
+ margin-left: 10px;
+ }
+ }
+`;
+
+const MobileProductLinksWrap = styled(StyledButtonWrap)`
+ display: none;
+
+ @media (max-width: 768px) {
+ display: block;
+ background-color: transparent;
+ flex-direction: column;
+
+ a {
+ display: block;
+ width: 100%;
+ }
+ }
+`;
+
+const StyledLink = styled(Link)`
+ width: 50%;
+ text-align: left;
+ @media (max-width: 768px) {
+ }
+
+ @media (min-width: 768px) {
+ width: auto;
+ text-align: center;
+ }
+`;
+
+const Nav = styled.div`
+ @media (max-width: 768px) {
+ background-color: ${colors.brandDark};
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ padding-top: 65px;
+ }
+
+ @media (min-width: 768px) {
+ width: auto;
+ text-align: center;
+ }
+`;
+
+const TradeButton = styled(Button)`
+ @media (max-width: 768px) {
+ display: none;
+ }
`;