feat: move all @next files to non @next directory
@@ -1,168 +0,0 @@
|
||||
import { Link as SmartLink } from '@0x/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
import MediaQuery from 'react-responsive';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { Logo } from 'ts/@next/components/logo';
|
||||
import { Column, FlexWrap, WrapGrid } from 'ts/@next/components/newLayout';
|
||||
import { NewsletterForm } from 'ts/@next/components/newsletter_form';
|
||||
import { WebsitePaths } from 'ts/types';
|
||||
import { constants } from 'ts/utils/constants';
|
||||
|
||||
interface LinkInterface {
|
||||
text: string;
|
||||
url: string;
|
||||
shouldOpenInNewTab?: boolean;
|
||||
}
|
||||
|
||||
interface LinkRows {
|
||||
heading: string;
|
||||
isOnMobile?: boolean;
|
||||
links: LinkInterface[];
|
||||
}
|
||||
|
||||
interface LinkListProps {
|
||||
links: LinkInterface[];
|
||||
}
|
||||
|
||||
const linkRows: LinkRows[] = [
|
||||
{
|
||||
heading: 'Products',
|
||||
isOnMobile: true,
|
||||
links: [
|
||||
{ url: WebsitePaths.Instant, text: '0x Instant' },
|
||||
{ url: WebsitePaths.LaunchKit, text: '0x Launch Kit' },
|
||||
],
|
||||
},
|
||||
{
|
||||
heading: 'Developers',
|
||||
links: [
|
||||
{ url: WebsitePaths.Docs, text: 'Documentation' },
|
||||
{ url: constants.URL_GITHUB_ORG, text: 'GitHub', shouldOpenInNewTab: true },
|
||||
{ url: constants.URL_PROTOCOL_SPECIFICATION, text: 'Protocol Spec', shouldOpenInNewTab: true },
|
||||
],
|
||||
},
|
||||
{
|
||||
heading: 'About',
|
||||
isOnMobile: true,
|
||||
links: [
|
||||
{ url: WebsitePaths.AboutMission, text: 'Mission' },
|
||||
{ url: WebsitePaths.AboutTeam, text: 'Team' },
|
||||
{ url: WebsitePaths.AboutJobs, text: 'Jobs' },
|
||||
{ url: WebsitePaths.AboutPress, text: 'Press' },
|
||||
{ url: WebsitePaths.Ecosystem, text: 'Grant Program' },
|
||||
],
|
||||
},
|
||||
{
|
||||
heading: 'Community',
|
||||
isOnMobile: true,
|
||||
links: [
|
||||
{ url: constants.URL_TWITTER, text: 'Twitter', shouldOpenInNewTab: true },
|
||||
{ url: constants.URL_ZEROEX_CHAT, text: 'Discord Chat', shouldOpenInNewTab: true },
|
||||
{ url: constants.URL_FACEBOOK, text: 'Facebook', shouldOpenInNewTab: true },
|
||||
{ url: constants.URL_REDDIT, text: 'Reddit', shouldOpenInNewTab: true },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const Footer: React.StatelessComponent = () => (
|
||||
<FooterWrap>
|
||||
<FlexWrap>
|
||||
<FooterColumn width="35%">
|
||||
<Logo />
|
||||
<NewsletterForm />
|
||||
</FooterColumn>
|
||||
|
||||
<FooterColumn width="55%">
|
||||
<WrapGrid isCentered={false} isWrapped={true}>
|
||||
{_.map(linkRows, (row: LinkRows, index) => (
|
||||
<MediaQuery minWidth={row.isOnMobile ? 0 : 768} key={`fc-${index}`}>
|
||||
<FooterSectionWrap>
|
||||
<RowHeading>{row.heading}</RowHeading>
|
||||
|
||||
<LinkList links={row.links} />
|
||||
</FooterSectionWrap>
|
||||
</MediaQuery>
|
||||
))}
|
||||
</WrapGrid>
|
||||
</FooterColumn>
|
||||
</FlexWrap>
|
||||
</FooterWrap>
|
||||
);
|
||||
|
||||
const LinkList = (props: LinkListProps) => (
|
||||
<List>
|
||||
{_.map(props.links, (link, index) => (
|
||||
<li key={`fl-${index}`}>
|
||||
<Link to={link.url} shouldOpenInNewTab={link.shouldOpenInNewTab}>
|
||||
{link.text}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</List>
|
||||
);
|
||||
|
||||
const FooterWrap = styled.footer`
|
||||
padding: 40px 30px 30px 30px;
|
||||
margin-top: 30px;
|
||||
background-color: ${props => props.theme.footerBg};
|
||||
color: ${props => props.theme.footerColor};
|
||||
|
||||
path {
|
||||
fill: ${props => props.theme.footerColor};
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
height: 350px;
|
||||
}
|
||||
`;
|
||||
|
||||
const FooterColumn = styled(Column)`
|
||||
@media (min-width: 768px) {
|
||||
width: ${props => props.width};
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
text-align: left;
|
||||
}
|
||||
`;
|
||||
|
||||
const FooterSectionWrap = styled(FooterColumn)`
|
||||
@media (max-width: 768px) {
|
||||
width: 50%;
|
||||
|
||||
& + & {
|
||||
margin-top: 0;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const RowHeading = styled.h3`
|
||||
color: inherit;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
margin-bottom: 1.25em;
|
||||
opacity: 0.75;
|
||||
`;
|
||||
|
||||
const List = styled.ul`
|
||||
li + li {
|
||||
margin-top: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
const Link = styled(SmartLink)`
|
||||
color: inherit;
|
||||
opacity: 0.5;
|
||||
display: block;
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
transition: opacity 0.25s;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
`;
|
||||
@@ -1,183 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import * as CopyToClipboard from 'react-copy-to-clipboard';
|
||||
import SyntaxHighlighter from 'react-syntax-highlighter';
|
||||
|
||||
import { Button } from 'ts/@next/components/button';
|
||||
import { Container } from 'ts/components/ui/container';
|
||||
import { styled } from 'ts/style/theme';
|
||||
import { zIndex } from 'ts/style/z_index';
|
||||
|
||||
const CustomPre = styled.pre`
|
||||
margin: 0px;
|
||||
line-height: 24px;
|
||||
overflow: scroll;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: 800px;
|
||||
border-radius: 4px;
|
||||
code {
|
||||
background-color: inherit !important;
|
||||
border-radius: 0px;
|
||||
font-family: 'Roboto Mono', sans-serif;
|
||||
border: none;
|
||||
}
|
||||
code:first-of-type {
|
||||
background-color: #060d0d !important;
|
||||
color: #999;
|
||||
min-height: 100%;
|
||||
text-align: center;
|
||||
margin-right: 15px;
|
||||
line-height: 25px;
|
||||
padding: 10px 7px !important;
|
||||
}
|
||||
code:last-of-type {
|
||||
position: relative;
|
||||
top: 10px;
|
||||
top: 0;
|
||||
padding-top: 11px;
|
||||
display: inline-block;
|
||||
line-height: 25px;
|
||||
}
|
||||
`;
|
||||
|
||||
const customStyle = {
|
||||
'hljs-comment': {
|
||||
color: '#7e7887',
|
||||
},
|
||||
'hljs-quote': {
|
||||
color: '#7e7887',
|
||||
},
|
||||
'hljs-variable': {
|
||||
color: '#be4678',
|
||||
},
|
||||
'hljs-template-variable': {
|
||||
color: '#be4678',
|
||||
},
|
||||
'hljs-attribute': {
|
||||
color: '#be4678',
|
||||
},
|
||||
'hljs-regexp': {
|
||||
color: '#be4678',
|
||||
},
|
||||
'hljs-link': {
|
||||
color: '#be4678',
|
||||
},
|
||||
'hljs-tag': {
|
||||
color: '#61f5ff',
|
||||
},
|
||||
'hljs-name': {
|
||||
color: '#61f5ff',
|
||||
},
|
||||
'hljs-selector-id': {
|
||||
color: '#be4678',
|
||||
},
|
||||
'hljs-selector-class': {
|
||||
color: '#be4678',
|
||||
},
|
||||
'hljs-number': {
|
||||
color: '#c994ff',
|
||||
},
|
||||
'hljs-meta': {
|
||||
color: '#61f5ff',
|
||||
},
|
||||
'hljs-built_in': {
|
||||
color: '#aa573c',
|
||||
},
|
||||
'hljs-builtin-name': {
|
||||
color: '#aa573c',
|
||||
},
|
||||
'hljs-literal': {
|
||||
color: '#aa573c',
|
||||
},
|
||||
'hljs-type': {
|
||||
color: '#aa573c',
|
||||
},
|
||||
'hljs-params': {
|
||||
color: '#aa573c',
|
||||
},
|
||||
'hljs-string': {
|
||||
color: '#bcff88',
|
||||
},
|
||||
'hljs-symbol': {
|
||||
color: '#2a9292',
|
||||
},
|
||||
'hljs-bullet': {
|
||||
color: '#2a9292',
|
||||
},
|
||||
'hljs-title': {
|
||||
color: '#576ddb',
|
||||
},
|
||||
'hljs-section': {
|
||||
color: '#576ddb',
|
||||
},
|
||||
'hljs-keyword': {
|
||||
color: '#955ae7',
|
||||
},
|
||||
'hljs-selector-tag': {
|
||||
color: '#955ae7',
|
||||
},
|
||||
'hljs-deletion': {
|
||||
color: '#19171c',
|
||||
display: 'inline-block',
|
||||
width: '100%',
|
||||
backgroundColor: '#be4678',
|
||||
},
|
||||
'hljs-addition': {
|
||||
color: '#19171c',
|
||||
display: 'inline-block',
|
||||
width: '100%',
|
||||
backgroundColor: '#2a9292',
|
||||
},
|
||||
hljs: {
|
||||
display: 'block',
|
||||
overflowX: 'hidden',
|
||||
background: '#1B2625',
|
||||
color: 'white',
|
||||
fontSize: '12px',
|
||||
},
|
||||
'hljs-emphasis': {
|
||||
fontStyle: 'italic',
|
||||
},
|
||||
'hljs-strong': {
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
};
|
||||
|
||||
export interface CodeDemoProps {
|
||||
children: string;
|
||||
}
|
||||
|
||||
export interface CodeDemoState {
|
||||
didCopyCode: boolean;
|
||||
}
|
||||
|
||||
export class CodeDemo extends React.Component<CodeDemoProps, CodeDemoState> {
|
||||
public state: CodeDemoState = {
|
||||
didCopyCode: false,
|
||||
};
|
||||
public render(): React.ReactNode {
|
||||
const copyButtonText = this.state.didCopyCode ? 'Copied!' : 'Copy';
|
||||
return (
|
||||
<Container position="relative" height="100%">
|
||||
<Container position="absolute" top="10px" right="10px" zIndex={zIndex.overlay - 1}>
|
||||
<CopyToClipboard text={this.props.children} onCopy={this._handleCopyClick}>
|
||||
<StyledButton>{copyButtonText}</StyledButton>
|
||||
</CopyToClipboard>
|
||||
</Container>
|
||||
<SyntaxHighlighter language="html" style={customStyle} showLineNumbers={true} PreTag={CustomPre}>
|
||||
{this.props.children}
|
||||
</SyntaxHighlighter>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
private readonly _handleCopyClick = () => {
|
||||
this.setState({ didCopyCode: true });
|
||||
};
|
||||
}
|
||||
|
||||
const StyledButton = styled(Button)`
|
||||
border-radius: 4px;
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
padding: 9px 21px 7px;
|
||||
`;
|
||||
@@ -1,84 +0,0 @@
|
||||
import { addressUtils } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
import * as React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { colors } from 'ts/style/colors';
|
||||
|
||||
import { Container } from 'ts/components/ui/container';
|
||||
|
||||
import { Paragraph } from 'ts/@next/components/text';
|
||||
|
||||
export interface ConfigGeneratorAddressInputProps {
|
||||
value?: string;
|
||||
onChange?: (address: string, isValid: boolean) => void;
|
||||
}
|
||||
|
||||
export interface ConfigGeneratorAddressInputState {
|
||||
errMsg: string;
|
||||
}
|
||||
|
||||
export interface InputProps {
|
||||
className?: string;
|
||||
value?: string;
|
||||
width?: string;
|
||||
fontSize?: string;
|
||||
fontColor?: string;
|
||||
padding?: string;
|
||||
placeholderColor?: string;
|
||||
placeholder?: string;
|
||||
backgroundColor?: string;
|
||||
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
}
|
||||
|
||||
export class ConfigGeneratorAddressInput extends React.Component<
|
||||
ConfigGeneratorAddressInputProps,
|
||||
ConfigGeneratorAddressInputState
|
||||
> {
|
||||
public state = {
|
||||
errMsg: '',
|
||||
};
|
||||
public render(): React.ReactNode {
|
||||
const { errMsg } = this.state;
|
||||
const hasError = !_.isEmpty(errMsg);
|
||||
return (
|
||||
<Container height="80px">
|
||||
<Input value={this.props.value} onChange={this._handleChange} placeholder="0xe99...aa8da4" />
|
||||
<Container marginTop="5px" isHidden={!hasError} height="25px">
|
||||
<Paragraph size="small" isNoMargin={true}>
|
||||
{errMsg}
|
||||
</Paragraph>
|
||||
</Container>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
private readonly _handleChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
const address = event.target.value;
|
||||
const isValidAddress = addressUtils.isAddress(address.toLowerCase()) || address === '';
|
||||
const errMsg = isValidAddress ? '' : 'Please enter a valid Ethereum address';
|
||||
this.setState({
|
||||
errMsg,
|
||||
});
|
||||
this.props.onChange(address, isValidAddress);
|
||||
};
|
||||
}
|
||||
|
||||
const PlainInput: React.StatelessComponent<InputProps> = ({ value, className, placeholder, onChange }) => (
|
||||
<input className={className} value={value} onChange={onChange} placeholder={placeholder} />
|
||||
);
|
||||
|
||||
export const Input = styled(PlainInput)`
|
||||
background-color: ${colors.white};
|
||||
color: ${colors.textDarkSecondary};
|
||||
font-size: 1rem;
|
||||
width: 100%;
|
||||
padding: 16px 20px 18px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid transparent;
|
||||
outline: none;
|
||||
&::placeholder {
|
||||
color: #333333;
|
||||
opacity: 0.5;
|
||||
}
|
||||
`;
|
||||
@@ -1,228 +1,168 @@
|
||||
import { ALink, colors, Link } from '@0x/react-shared';
|
||||
import { ObjectMap } from '@0x/types';
|
||||
import { Link as SmartLink } from '@0x/react-shared';
|
||||
import * as _ from 'lodash';
|
||||
import DropDownMenu from 'material-ui/DropDownMenu';
|
||||
import MenuItem from 'material-ui/MenuItem';
|
||||
import * as React from 'react';
|
||||
import MediaQuery from 'react-responsive';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { Dispatcher } from 'ts/redux/dispatcher';
|
||||
import { Deco, Key, Language, WebsitePaths } from 'ts/types';
|
||||
import { Logo } from 'ts/@next/components/logo';
|
||||
import { Column, FlexWrap, WrapGrid } from 'ts/@next/components/newLayout';
|
||||
import { NewsletterForm } from 'ts/@next/components/newsletter_form';
|
||||
import { WebsitePaths } from 'ts/types';
|
||||
import { constants } from 'ts/utils/constants';
|
||||
import { Translate } from 'ts/utils/translate';
|
||||
|
||||
const ICON_DIMENSION = 16;
|
||||
|
||||
const languageToMenuTitle = {
|
||||
[Language.English]: 'English',
|
||||
[Language.Russian]: 'Русский',
|
||||
[Language.Spanish]: 'Español',
|
||||
[Language.Korean]: '한국어',
|
||||
[Language.Chinese]: '中文',
|
||||
};
|
||||
|
||||
export interface FooterProps {
|
||||
translate: Translate;
|
||||
dispatcher: Dispatcher;
|
||||
backgroundColor?: string;
|
||||
interface LinkInterface {
|
||||
text: string;
|
||||
url: string;
|
||||
shouldOpenInNewTab?: boolean;
|
||||
}
|
||||
|
||||
interface FooterState {
|
||||
selectedLanguage: Language;
|
||||
interface LinkRows {
|
||||
heading: string;
|
||||
isOnMobile?: boolean;
|
||||
links: LinkInterface[];
|
||||
}
|
||||
|
||||
export class Footer extends React.Component<FooterProps, FooterState> {
|
||||
public static defaultProps = {
|
||||
backgroundColor: colors.darkerGrey,
|
||||
};
|
||||
constructor(props: FooterProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
selectedLanguage: props.translate.getLanguage(),
|
||||
};
|
||||
}
|
||||
public render(): React.ReactNode {
|
||||
const sectionNameToLinks: ObjectMap<ALink[]> = {
|
||||
[Key.Documentation]: [
|
||||
{
|
||||
title: 'Developer Home',
|
||||
to: WebsitePaths.Docs,
|
||||
},
|
||||
{
|
||||
title: '0x.js',
|
||||
to: WebsitePaths.ZeroExJs,
|
||||
},
|
||||
{
|
||||
title: this.props.translate.get(Key.SmartContracts, Deco.Cap),
|
||||
to: WebsitePaths.SmartContracts,
|
||||
},
|
||||
{
|
||||
title: this.props.translate.get(Key.Connect, Deco.Cap),
|
||||
to: WebsitePaths.Connect,
|
||||
},
|
||||
{
|
||||
title: this.props.translate.get(Key.Whitepaper, Deco.Cap),
|
||||
to: WebsitePaths.Whitepaper,
|
||||
shouldOpenInNewTab: true,
|
||||
},
|
||||
{
|
||||
title: this.props.translate.get(Key.Wiki, Deco.Cap),
|
||||
to: WebsitePaths.Wiki,
|
||||
},
|
||||
],
|
||||
[Key.Community]: [
|
||||
{
|
||||
title: this.props.translate.get(Key.Discord, Deco.Cap),
|
||||
to: constants.URL_ZEROEX_CHAT,
|
||||
shouldOpenInNewTab: true,
|
||||
},
|
||||
{
|
||||
title: this.props.translate.get(Key.Blog, Deco.Cap),
|
||||
to: constants.URL_BLOG,
|
||||
shouldOpenInNewTab: true,
|
||||
},
|
||||
{
|
||||
title: 'Twitter',
|
||||
to: constants.URL_TWITTER,
|
||||
shouldOpenInNewTab: true,
|
||||
},
|
||||
{
|
||||
title: 'Reddit',
|
||||
to: constants.URL_REDDIT,
|
||||
shouldOpenInNewTab: true,
|
||||
},
|
||||
{
|
||||
title: this.props.translate.get(Key.Forum, Deco.Cap),
|
||||
to: constants.URL_DISCOURSE_FORUM,
|
||||
shouldOpenInNewTab: true,
|
||||
},
|
||||
],
|
||||
[Key.Organization]: [
|
||||
{
|
||||
title: this.props.translate.get(Key.About, Deco.Cap),
|
||||
to: WebsitePaths.About,
|
||||
},
|
||||
{
|
||||
title: this.props.translate.get(Key.Careers, Deco.Cap),
|
||||
to: WebsitePaths.Careers,
|
||||
},
|
||||
{
|
||||
title: this.props.translate.get(Key.Contact, Deco.Cap),
|
||||
to: 'mailto:team@0x.org',
|
||||
shouldOpenInNewTab: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
const languageMenuItems = _.map(languageToMenuTitle, (menuTitle: string, language: Language) => {
|
||||
return <MenuItem key={menuTitle} value={language} primaryText={menuTitle} />;
|
||||
});
|
||||
return (
|
||||
<div className="relative pb4 pt2" style={{ backgroundColor: this.props.backgroundColor }}>
|
||||
<div className="mx-auto max-width-4 md-px2 lg-px0 py4 clearfix" style={{ color: colors.white }}>
|
||||
<div className="col lg-col-4 md-col-4 col-12 left">
|
||||
<div className="sm-mx-auto" style={{ width: 148 }}>
|
||||
<div>
|
||||
<img src="/images/protocol_logo_white.png" height="30" />
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
fontSize: 11,
|
||||
color: colors.grey,
|
||||
paddingLeft: 37,
|
||||
paddingTop: 2,
|
||||
}}
|
||||
>
|
||||
© ZeroEx, Intl.
|
||||
</div>
|
||||
<div className="pt4 center">
|
||||
<DropDownMenu
|
||||
labelStyle={{ color: colors.white }}
|
||||
value={this.state.selectedLanguage}
|
||||
onChange={this._updateLanguage.bind(this)}
|
||||
>
|
||||
{languageMenuItems}
|
||||
</DropDownMenu>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col lg-col-8 md-col-8 col-12 lg-pl4 md-pl4">
|
||||
<div className="col lg-col-4 md-col-4 col-12">
|
||||
<div className="lg-right md-right sm-center">
|
||||
{this._renderHeader(Key.Documentation)}
|
||||
{_.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(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(sectionNameToLinks[Key.Organization], this._renderMenuItem.bind(this))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderIcon(fileName: string): React.ReactNode {
|
||||
return (
|
||||
<div style={{ height: ICON_DIMENSION, width: ICON_DIMENSION }}>
|
||||
<img src={`/images/social/${fileName}`} style={{ width: ICON_DIMENSION }} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
private _renderMenuItem(link: ALink): React.ReactNode {
|
||||
const titleToIcon: { [title: string]: string } = {
|
||||
[this.props.translate.get(Key.Discord, Deco.Cap)]: 'discord.png',
|
||||
[this.props.translate.get(Key.Blog, Deco.Cap)]: 'medium.png',
|
||||
Twitter: 'twitter.png',
|
||||
Reddit: 'reddit.png',
|
||||
[this.props.translate.get(Key.Forum, Deco.Cap)]: 'discourse.png',
|
||||
};
|
||||
const iconIfExists = titleToIcon[link.title];
|
||||
return (
|
||||
<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">{link.title}</div>
|
||||
</div>
|
||||
) : (
|
||||
link.title
|
||||
)}
|
||||
</div>
|
||||
interface LinkListProps {
|
||||
links: LinkInterface[];
|
||||
}
|
||||
|
||||
const linkRows: LinkRows[] = [
|
||||
{
|
||||
heading: 'Products',
|
||||
isOnMobile: true,
|
||||
links: [
|
||||
{ url: WebsitePaths.Instant, text: '0x Instant' },
|
||||
{ url: WebsitePaths.LaunchKit, text: '0x Launch Kit' },
|
||||
],
|
||||
},
|
||||
{
|
||||
heading: 'Developers',
|
||||
links: [
|
||||
{ url: WebsitePaths.Docs, text: 'Documentation' },
|
||||
{ url: constants.URL_GITHUB_ORG, text: 'GitHub', shouldOpenInNewTab: true },
|
||||
{ url: constants.URL_PROTOCOL_SPECIFICATION, text: 'Protocol Spec', shouldOpenInNewTab: true },
|
||||
],
|
||||
},
|
||||
{
|
||||
heading: 'About',
|
||||
isOnMobile: true,
|
||||
links: [
|
||||
{ url: WebsitePaths.AboutMission, text: 'Mission' },
|
||||
{ url: WebsitePaths.AboutTeam, text: 'Team' },
|
||||
{ url: WebsitePaths.AboutJobs, text: 'Jobs' },
|
||||
{ url: WebsitePaths.AboutPress, text: 'Press' },
|
||||
{ url: WebsitePaths.Ecosystem, text: 'Grant Program' },
|
||||
],
|
||||
},
|
||||
{
|
||||
heading: 'Community',
|
||||
isOnMobile: true,
|
||||
links: [
|
||||
{ url: constants.URL_TWITTER, text: 'Twitter', shouldOpenInNewTab: true },
|
||||
{ url: constants.URL_ZEROEX_CHAT, text: 'Discord Chat', shouldOpenInNewTab: true },
|
||||
{ url: constants.URL_FACEBOOK, text: 'Facebook', shouldOpenInNewTab: true },
|
||||
{ url: constants.URL_REDDIT, text: 'Reddit', shouldOpenInNewTab: true },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const Footer: React.StatelessComponent = () => (
|
||||
<FooterWrap>
|
||||
<FlexWrap>
|
||||
<FooterColumn width="35%">
|
||||
<Logo />
|
||||
<NewsletterForm />
|
||||
</FooterColumn>
|
||||
|
||||
<FooterColumn width="55%">
|
||||
<WrapGrid isCentered={false} isWrapped={true}>
|
||||
{_.map(linkRows, (row: LinkRows, index) => (
|
||||
<MediaQuery minWidth={row.isOnMobile ? 0 : 768} key={`fc-${index}`}>
|
||||
<FooterSectionWrap>
|
||||
<RowHeading>{row.heading}</RowHeading>
|
||||
|
||||
<LinkList links={row.links} />
|
||||
</FooterSectionWrap>
|
||||
</MediaQuery>
|
||||
))}
|
||||
</WrapGrid>
|
||||
</FooterColumn>
|
||||
</FlexWrap>
|
||||
</FooterWrap>
|
||||
);
|
||||
|
||||
const LinkList = (props: LinkListProps) => (
|
||||
<List>
|
||||
{_.map(props.links, (link, index) => (
|
||||
<li key={`fl-${index}`}>
|
||||
<Link to={link.url} shouldOpenInNewTab={link.shouldOpenInNewTab}>
|
||||
{link.text}
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
</li>
|
||||
))}
|
||||
</List>
|
||||
);
|
||||
|
||||
const FooterWrap = styled.footer`
|
||||
padding: 40px 30px 30px 30px;
|
||||
margin-top: 30px;
|
||||
background-color: ${props => props.theme.footerBg};
|
||||
color: ${props => props.theme.footerColor};
|
||||
|
||||
path {
|
||||
fill: ${props => props.theme.footerColor};
|
||||
}
|
||||
private _renderHeader(key: Key): React.ReactNode {
|
||||
const headerStyle = {
|
||||
color: colors.grey400,
|
||||
letterSpacing: 2,
|
||||
fontFamily: 'Roboto Mono',
|
||||
fontSize: 13,
|
||||
};
|
||||
return (
|
||||
<div className="lg-pb2 md-pb2 sm-pt4" style={headerStyle}>
|
||||
{this.props.translate.get(key, Deco.Upper)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@media (min-width: 768px) {
|
||||
height: 350px;
|
||||
}
|
||||
private _updateLanguage(_event: any, _index: number, value: Language): void {
|
||||
this.setState({
|
||||
selectedLanguage: value,
|
||||
});
|
||||
this.props.dispatcher.updateSelectedLanguage(value);
|
||||
`;
|
||||
|
||||
const FooterColumn = styled(Column)`
|
||||
@media (min-width: 768px) {
|
||||
width: ${props => props.width};
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
text-align: left;
|
||||
}
|
||||
`;
|
||||
|
||||
const FooterSectionWrap = styled(FooterColumn)`
|
||||
@media (max-width: 768px) {
|
||||
width: 50%;
|
||||
|
||||
& + & {
|
||||
margin-top: 0;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const RowHeading = styled.h3`
|
||||
color: inherit;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
margin-bottom: 1.25em;
|
||||
opacity: 0.75;
|
||||
`;
|
||||
|
||||
const List = styled.ul`
|
||||
li + li {
|
||||
margin-top: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
const Link = styled(SmartLink)`
|
||||
color: inherit;
|
||||
opacity: 0.5;
|
||||
display: block;
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
transition: opacity 0.25s;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
`;
|
||||
|
||||
|
Before Width: | Height: | Size: 198 B After Width: | Height: | Size: 198 B |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 749 B After Width: | Height: | Size: 749 B |
|
Before Width: | Height: | Size: 826 B After Width: | Height: | Size: 826 B |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 493 B After Width: | Height: | Size: 493 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 786 B After Width: | Height: | Size: 786 B |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 955 B After Width: | Height: | Size: 955 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 921 B After Width: | Height: | Size: 921 B |
|
Before Width: | Height: | Size: 630 B After Width: | Height: | Size: 630 B |
|
Before Width: | Height: | Size: 1013 B After Width: | Height: | Size: 1013 B |
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 730 B After Width: | Height: | Size: 730 B |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 670 B After Width: | Height: | Size: 670 B |
|
Before Width: | Height: | Size: 615 B After Width: | Height: | Size: 615 B |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 684 B After Width: | Height: | Size: 684 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 554 B After Width: | Height: | Size: 554 B |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 545 B After Width: | Height: | Size: 545 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 470 B After Width: | Height: | Size: 470 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 650 B After Width: | Height: | Size: 650 B |
|
Before Width: | Height: | Size: 857 B After Width: | Height: | Size: 857 B |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |