aboutsummaryrefslogtreecommitdiffstats
path: root/packages/website/ts
diff options
context:
space:
mode:
authorFrancesco Agosti <francesco.agosti93@gmail.com>2018-12-04 06:51:27 +0800
committerGitHub <noreply@github.com>2018-12-04 06:51:27 +0800
commite9fe7dcf54183416e114655595be4e565811d4ed (patch)
tree748372f2f919571a7221874f627124f61f606235 /packages/website/ts
parent50df67e7511460f051f91785bb4384485077ef60 (diff)
parent0f01e31cc3826df7000e0ddc35354aa9af515966 (diff)
downloaddexon-0x-contracts-e9fe7dcf54183416e114655595be4e565811d4ed.tar.gz
dexon-0x-contracts-e9fe7dcf54183416e114655595be4e565811d4ed.tar.zst
dexon-0x-contracts-e9fe7dcf54183416e114655595be4e565811d4ed.zip
Merge pull request #1353 from 0xProject/feature/website/instant-marketing
[website] instant marketing page shell
Diffstat (limited to 'packages/website/ts')
-rw-r--r--packages/website/ts/components/ui/image.tsx2
-rw-r--r--packages/website/ts/components/ui/text.tsx2
-rw-r--r--packages/website/ts/containers/instant.ts30
-rw-r--r--packages/website/ts/index.tsx2
-rw-r--r--packages/website/ts/pages/instant/configurator.tsx12
-rw-r--r--packages/website/ts/pages/instant/features.tsx146
-rw-r--r--packages/website/ts/pages/instant/instant.tsx87
-rw-r--r--packages/website/ts/pages/instant/introducing_0x_instant.tsx57
-rw-r--r--packages/website/ts/pages/instant/need_more.tsx62
-rw-r--r--packages/website/ts/pages/instant/screenshots.tsx35
-rw-r--r--packages/website/ts/style/colors.ts3
-rw-r--r--packages/website/ts/types.ts1
12 files changed, 438 insertions, 1 deletions
diff --git a/packages/website/ts/components/ui/image.tsx b/packages/website/ts/components/ui/image.tsx
index c8d39352b..d698ddaa0 100644
--- a/packages/website/ts/components/ui/image.tsx
+++ b/packages/website/ts/components/ui/image.tsx
@@ -10,6 +10,7 @@ export interface ImageProps {
height?: string | number;
maxWidth?: string | number;
maxHeight?: string | number;
+ additionalStyle?: React.CSSProperties;
}
interface ImageState {
imageLoadFailed: boolean;
@@ -30,6 +31,7 @@ export class Image extends React.Component<ImageProps, ImageState> {
onError={this._onError.bind(this)}
src={src}
style={{
+ ...this.props.additionalStyle,
borderRadius: this.props.borderRadius,
maxWidth: this.props.maxWidth,
maxHeight: this.props.maxHeight,
diff --git a/packages/website/ts/components/ui/text.tsx b/packages/website/ts/components/ui/text.tsx
index c13e21913..87239a021 100644
--- a/packages/website/ts/components/ui/text.tsx
+++ b/packages/website/ts/components/ui/text.tsx
@@ -3,7 +3,7 @@ import { darken } from 'polished';
import * as React from 'react';
import { styled } from 'ts/style/theme';
-export type TextTag = 'p' | 'div' | 'span' | 'label' | 'h1' | 'h2' | 'h3' | 'h4' | 'i';
+export type TextTag = 'p' | 'div' | 'span' | 'label' | 'h1' | 'h2' | 'h3' | 'h4' | 'i' | 'span';
export interface TextProps {
className?: string;
diff --git a/packages/website/ts/containers/instant.ts b/packages/website/ts/containers/instant.ts
new file mode 100644
index 000000000..12ae7454e
--- /dev/null
+++ b/packages/website/ts/containers/instant.ts
@@ -0,0 +1,30 @@
+import * as React from 'react';
+import { connect } from 'react-redux';
+import { Dispatch } from 'redux';
+import { Instant as InstantComponent, InstantProps } from 'ts/pages/instant/instant';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { State } from 'ts/redux/reducer';
+import { ScreenWidths } from 'ts/types';
+import { Translate } from 'ts/utils/translate';
+
+interface ConnectedState {
+ translate: Translate;
+ screenWidth: ScreenWidths;
+}
+
+interface ConnectedDispatch {
+ dispatcher: Dispatcher;
+}
+
+const mapStateToProps = (state: State, _ownProps: InstantProps): ConnectedState => ({
+ translate: state.translate,
+ screenWidth: state.screenWidth,
+});
+
+const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
+ dispatcher: new Dispatcher(dispatch),
+});
+
+export const Instant: React.ComponentClass<InstantProps> = connect(mapStateToProps, mapDispatchToProps)(
+ InstantComponent,
+);
diff --git a/packages/website/ts/index.tsx b/packages/website/ts/index.tsx
index faf7d8c87..050c201a3 100644
--- a/packages/website/ts/index.tsx
+++ b/packages/website/ts/index.tsx
@@ -7,6 +7,7 @@ import { MetaTags } from 'ts/components/meta_tags';
import { About } from 'ts/containers/about';
import { DocsHome } from 'ts/containers/docs_home';
import { FAQ } from 'ts/containers/faq';
+import { Instant } from 'ts/containers/instant';
import { Jobs } from 'ts/containers/jobs';
import { Landing } from 'ts/containers/landing';
import { LaunchKit } from 'ts/containers/launch_kit';
@@ -92,6 +93,7 @@ render(
<Route exact={true} path="/" component={Landing as any} />
<Redirect from="/otc" to={`${WebsitePaths.Portal}`} />
<Route path={WebsitePaths.LaunchKit} component={LaunchKit as any} />
+ <Route path={WebsitePaths.Instant} component={Instant as any} />
<Route path={WebsitePaths.Careers} component={Jobs as any} />
<Route path={WebsitePaths.Portal} component={LazyPortal} />
<Route path={WebsitePaths.FAQ} component={FAQ as any} />
diff --git a/packages/website/ts/pages/instant/configurator.tsx b/packages/website/ts/pages/instant/configurator.tsx
new file mode 100644
index 000000000..c836739bb
--- /dev/null
+++ b/packages/website/ts/pages/instant/configurator.tsx
@@ -0,0 +1,12 @@
+import * as React from 'react';
+
+import { Container } from 'ts/components/ui/container';
+import { colors } from 'ts/style/colors';
+
+export interface ConfiguratorProps {
+ hash: string;
+}
+
+export const Configurator = (props: ConfiguratorProps) => (
+ <Container id={props.hash} height="400px" backgroundColor={colors.instantTertiaryBackground} />
+);
diff --git a/packages/website/ts/pages/instant/features.tsx b/packages/website/ts/pages/instant/features.tsx
new file mode 100644
index 000000000..9c1668c1c
--- /dev/null
+++ b/packages/website/ts/pages/instant/features.tsx
@@ -0,0 +1,146 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { Container } from 'ts/components/ui/container';
+import { Image } from 'ts/components/ui/image';
+import { Text } from 'ts/components/ui/text';
+import { colors } from 'ts/style/colors';
+import { ScreenWidths } from 'ts/types';
+import { utils } from 'ts/utils/utils';
+
+export interface FeatureProps {
+ screenWidth: ScreenWidths;
+ onGetStartedClick: () => void;
+}
+
+export const Features = (props: FeatureProps) => {
+ const isSmallScreen = props.screenWidth === ScreenWidths.Sm;
+ const getStartedLinkInfo = {
+ displayText: 'Get started',
+ onClick: props.onGetStartedClick,
+ };
+ const exploreTheDocsLinkInfo = {
+ displayText: 'Explore the docs',
+ linkSrc: `${utils.getCurrentBaseUrl()}/wiki#Get-Started`,
+ };
+ const tokenLinkInfos = isSmallScreen ? [getStartedLinkInfo] : [getStartedLinkInfo, exploreTheDocsLinkInfo];
+ return (
+ <Container backgroundColor={colors.instantSecondaryBackground} className="py3 flex flex-column px3">
+ <FeatureItem
+ imgSrc="images/instant/feature_1.svg"
+ title="Support ERC-20 and ERC-721 tokens"
+ description="Seamlessly integrate token purchasing into your product experience by offering digital assets ranging from in-game items to stablecoins."
+ linkInfos={tokenLinkInfos}
+ screenWidth={props.screenWidth}
+ />
+ <FeatureItem
+ imgSrc="images/instant/feature_2.svg"
+ title="Generate revenue for your business"
+ description="With just a few lines of code, you can earn up to 5% in affiliate fees on every transaction from your crypto wallet or dApp."
+ linkInfos={[
+ {
+ displayText: 'Learn about affiliate fees',
+ linkSrc: `${utils.getCurrentBaseUrl()}/wiki#Learn-About-Affiliate-Fees`,
+ },
+ ]}
+ screenWidth={props.screenWidth}
+ />
+ <FeatureItem
+ imgSrc="images/instant/feature_3.svg"
+ title="Easy and Flexible Integration"
+ description="Use our out-of-the-box design or customize the user interface by integrating the AssetBuyer engine. You can also tap into 0x networked liquidity or choose your own liquidity pool."
+ linkInfos={[
+ {
+ displayText: 'Explore AssetBuyer',
+ linkSrc: `${utils.getCurrentBaseUrl()}/docs/asset-buyer`,
+ },
+ ]}
+ screenWidth={props.screenWidth}
+ />
+ </Container>
+ );
+};
+
+interface LinkInfo {
+ displayText: string;
+ linkSrc?: string;
+ onClick?: () => void;
+}
+
+interface FeatureItemProps {
+ imgSrc: string;
+ title: string;
+ description: string;
+ linkInfos: LinkInfo[];
+ screenWidth: ScreenWidths;
+}
+
+const FeatureItem = (props: FeatureItemProps) => {
+ const { imgSrc, title, description, linkInfos, screenWidth } = props;
+ const isLargeScreen = screenWidth === ScreenWidths.Lg;
+ const maxWidth = isLargeScreen ? '500px' : undefined;
+ const image = (
+ <Container className="center" minWidth="435px" maxHeight="225px">
+ <Image src={imgSrc} additionalStyle={{ filter: 'drop-shadow(0px 4px 4px rgba(0,0,0,.25))' }} />
+ </Container>
+ );
+ const info = (
+ <Container maxWidth={maxWidth}>
+ <Text fontSize="24px" lineHeight="34px" fontColor={colors.white} fontWeight={500}>
+ {title}
+ </Text>
+ <Container marginTop="28px">
+ <Text fontFamily="Roboto Mono" fontSize="14px" lineHeight="2em" fontColor={colors.grey500}>
+ {description}
+ </Text>
+ </Container>
+ <Container className="flex" marginTop="28px">
+ {_.map(linkInfos, linkInfo => {
+ const onClick = (event: React.MouseEvent<HTMLElement>) => {
+ if (!_.isUndefined(linkInfo.onClick)) {
+ linkInfo.onClick();
+ } else if (!_.isUndefined(linkInfo.linkSrc)) {
+ utils.openUrl(linkInfo.linkSrc);
+ }
+ };
+ return (
+ <Container
+ key={linkInfo.linkSrc}
+ className="flex items-center"
+ marginRight="32px"
+ onClick={onClick}
+ cursor="pointer"
+ >
+ <Container>
+ <Text fontSize="16px" fontColor={colors.white}>
+ {linkInfo.displayText}
+ </Text>
+ </Container>
+ <Container paddingTop="1px" paddingLeft="6px">
+ <i
+ className="zmdi zmdi-chevron-right bold"
+ style={{ fontSize: 16, color: colors.white }}
+ />
+ </Container>
+ </Container>
+ );
+ })}
+ </Container>
+ </Container>
+ );
+ return (
+ <Container className="flex flex-column items-center py4 px3">
+ {isLargeScreen ? (
+ <Container className="flex">
+ {image}
+ <Container marginLeft="115px">{info}</Container>
+ </Container>
+ ) : (
+ <Container className="flex flex-column items-center" width="100%">
+ {image}
+ <Container marginTop="48px">{info}</Container>
+ </Container>
+ )}
+ </Container>
+ );
+};
diff --git a/packages/website/ts/pages/instant/instant.tsx b/packages/website/ts/pages/instant/instant.tsx
new file mode 100644
index 000000000..fa6bd1c33
--- /dev/null
+++ b/packages/website/ts/pages/instant/instant.tsx
@@ -0,0 +1,87 @@
+import { utils as sharedUtils } from '@0x/react-shared';
+import * as _ from 'lodash';
+import * as React from 'react';
+import * as DocumentTitle from 'react-document-title';
+
+import { Footer } from 'ts/components/footer';
+import { MetaTags } from 'ts/components/meta_tags';
+import { TopBar } from 'ts/components/top_bar/top_bar';
+import { Container } from 'ts/components/ui/container';
+import { Configurator } from 'ts/pages/instant/configurator';
+import { Features } from 'ts/pages/instant/features';
+import { Introducing0xInstant } from 'ts/pages/instant/introducing_0x_instant';
+import { NeedMore } from 'ts/pages/instant/need_more';
+import { Screenshots } from 'ts/pages/instant/screenshots';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { colors } from 'ts/style/colors';
+import { ScreenWidths } from 'ts/types';
+import { Translate } from 'ts/utils/translate';
+import { utils } from 'ts/utils/utils';
+
+export interface InstantProps {
+ location: Location;
+ translate: Translate;
+ dispatcher: Dispatcher;
+ screenWidth: ScreenWidths;
+}
+
+export interface InstantState {}
+
+const CONFIGURATOR_HASH = 'configure';
+const THROTTLE_TIMEOUT = 100;
+const DOCUMENT_TITLE = '0x Instant';
+const DOCUMENT_DESCRIPTION = '0x Instant';
+
+export class Instant extends React.Component<InstantProps, InstantState> {
+ // TODO: consolidate this small screen scaffolding into one place (its being used in portal and docs as well)
+ private readonly _throttledScreenWidthUpdate: () => void;
+ public constructor(props: InstantProps) {
+ super(props);
+ this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
+ }
+ public componentDidMount(): void {
+ window.addEventListener('resize', this._throttledScreenWidthUpdate);
+ window.scrollTo(0, 0);
+ }
+ public render(): React.ReactNode {
+ return (
+ <Container overflowX="hidden">
+ <MetaTags title={DOCUMENT_TITLE} description={DOCUMENT_DESCRIPTION} />
+ <DocumentTitle title={DOCUMENT_TITLE} />
+ <TopBar
+ blockchainIsLoaded={false}
+ location={this.props.location}
+ style={{ backgroundColor: colors.instantPrimaryBackground, position: 'relative' }}
+ translate={this.props.translate}
+ isNightVersion={true}
+ />
+ <Container backgroundColor={colors.instantPrimaryBackground} />
+ <Introducing0xInstant screenWidth={this.props.screenWidth} onCTAClick={this._onGetStartedClick} />
+ <Screenshots screenWidth={this.props.screenWidth} />
+ <Features screenWidth={this.props.screenWidth} onGetStartedClick={this._onGetStartedClick} />
+ {!this._isSmallScreen() && <Configurator hash={CONFIGURATOR_HASH} />}
+ <NeedMore screenWidth={this.props.screenWidth} />
+ <Footer translate={this.props.translate} dispatcher={this.props.dispatcher} />
+ </Container>
+ );
+ }
+ private readonly _onGetStartedClick = () => {
+ if (this._isSmallScreen()) {
+ utils.openUrl(`${utils.getCurrentBaseUrl()}/wiki#Get-Started`);
+ } else {
+ this._scrollToConfigurator();
+ }
+ };
+ private _isSmallScreen(): boolean {
+ const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm;
+ return isSmallScreen;
+ }
+ private _scrollToConfigurator(): void {
+ sharedUtils.setUrlHash(CONFIGURATOR_HASH);
+ sharedUtils.scrollToHash(CONFIGURATOR_HASH, '');
+ }
+ private _updateScreenWidth(): void {
+ const newScreenWidth = utils.getScreenWidth();
+ this.props.dispatcher.updateScreenWidth(newScreenWidth);
+ }
+}
diff --git a/packages/website/ts/pages/instant/introducing_0x_instant.tsx b/packages/website/ts/pages/instant/introducing_0x_instant.tsx
new file mode 100644
index 000000000..da3f09faa
--- /dev/null
+++ b/packages/website/ts/pages/instant/introducing_0x_instant.tsx
@@ -0,0 +1,57 @@
+import * as React from 'react';
+
+import { Button } from 'ts/components/ui/button';
+import { Container } from 'ts/components/ui/container';
+import { Text } from 'ts/components/ui/text';
+import { colors } from 'ts/style/colors';
+import { ScreenWidths } from 'ts/types';
+
+export interface Introducing0xInstantProps {
+ screenWidth: ScreenWidths;
+ onCTAClick: () => void;
+}
+
+export const Introducing0xInstant = (props: Introducing0xInstantProps) => {
+ const isSmallScreen = props.screenWidth === ScreenWidths.Sm;
+ const zero = (
+ <Text fontColor={colors.white} fontSize="42px" fontWeight="600" fontFamily="Roboto Mono" Tag="span">
+ 0
+ </Text>
+ );
+ const title = isSmallScreen ? (
+ <div>
+ Introducing<br />
+ {zero}x Instant
+ </div>
+ ) : (
+ <div>Introducing {zero}x Instant</div>
+ );
+ return (
+ <div className="clearfix center lg-pt4 md-pt4" style={{ backgroundColor: colors.instantPrimaryBackground }}>
+ <div className="mx-auto inline-block align-middle py4" style={{ lineHeight: '44px', textAlign: 'center' }}>
+ <Container className="sm-center sm-pt3">
+ <Text fontColor={colors.white} fontSize="42px" lineHeight="52px" fontWeight="600">
+ {title}
+ </Text>
+ </Container>
+ <Container className="pb2 lg-pt2 md-pt2 sm-pt3 sm-px3 sm-center" maxWidth="600px">
+ <Text fontColor={colors.grey500} fontSize="20px" lineHeight="32px" fontFamily="Roboto Mono">
+ A free and flexible way to offer simple crypto
+ <br /> purchasing in any app or website.
+ </Text>
+ </Container>
+ <div className="py3">
+ <Button
+ type="button"
+ backgroundColor={colors.mediumBlue}
+ fontColor={colors.white}
+ fontSize="18px"
+ onClick={props.onCTAClick}
+ >
+ Get Started
+ </Button>
+ </div>
+ </div>
+ </div>
+ );
+};
diff --git a/packages/website/ts/pages/instant/need_more.tsx b/packages/website/ts/pages/instant/need_more.tsx
new file mode 100644
index 000000000..e6d5c3694
--- /dev/null
+++ b/packages/website/ts/pages/instant/need_more.tsx
@@ -0,0 +1,62 @@
+import * as React from 'react';
+
+import { Button } from 'ts/components/ui/button';
+import { Container } from 'ts/components/ui/container';
+import { Text } from 'ts/components/ui/text';
+import { colors } from 'ts/style/colors';
+import { ScreenWidths } from 'ts/types';
+import { constants } from 'ts/utils/constants';
+import { utils } from 'ts/utils/utils';
+
+export interface NeedMoreProps {
+ screenWidth: ScreenWidths;
+}
+export const NeedMore = (props: NeedMoreProps) => {
+ const isSmallScreen = props.screenWidth === ScreenWidths.Sm;
+ const backgroundColor = isSmallScreen ? colors.instantTertiaryBackground : colors.instantSecondaryBackground;
+ const className = isSmallScreen ? 'flex flex-column items-center' : 'flex';
+ const marginRight = isSmallScreen ? undefined : '200px';
+ return (
+ <Container className="flex flex-column items-center py4 px3" backgroundColor={backgroundColor}>
+ <Container className={className}>
+ <Container className="sm-center" marginRight={marginRight}>
+ <Text fontColor={colors.white} fontSize="32px" lineHeight="45px">
+ Need more flexibility?
+ </Text>
+ <Text fontColor={colors.grey500} fontSize="18px" lineHeight="27px">
+ View our full documentation or reach out if you have any questions.
+ </Text>
+ </Container>
+ <Container className="py3 flex">
+ <Container marginRight="20px">
+ <Button
+ type="button"
+ backgroundColor={colors.white}
+ fontColor={backgroundColor}
+ fontSize="18px"
+ onClick={onGetInTouchClick}
+ >
+ Get in Touch
+ </Button>
+ </Container>
+ <Button
+ type="button"
+ backgroundColor={colors.mediumBlue}
+ fontColor={colors.white}
+ fontSize="18px"
+ onClick={onDocsClick}
+ >
+ Explore the Docs
+ </Button>
+ </Container>
+ </Container>
+ </Container>
+ );
+};
+
+const onGetInTouchClick = () => {
+ utils.openUrl(constants.URL_ZEROEX_CHAT);
+};
+const onDocsClick = () => {
+ utils.openUrl(`${utils.getCurrentBaseUrl()}/wiki#Get-Started`);
+};
diff --git a/packages/website/ts/pages/instant/screenshots.tsx b/packages/website/ts/pages/instant/screenshots.tsx
new file mode 100644
index 000000000..7dcf17fd1
--- /dev/null
+++ b/packages/website/ts/pages/instant/screenshots.tsx
@@ -0,0 +1,35 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { Container } from 'ts/components/ui/container';
+import { colors } from 'ts/style/colors';
+import { ScreenWidths } from 'ts/types';
+
+export interface ScreenshotsProps {
+ screenWidth: ScreenWidths;
+}
+
+export const Screenshots = (props: ScreenshotsProps) => {
+ const isSmallScreen = props.screenWidth === ScreenWidths.Sm;
+ const images = isSmallScreen
+ ? [
+ 'images/instant/rep_screenshot.png',
+ 'images/instant/dai_screenshot.png',
+ 'images/instant/gods_screenshot.png',
+ ]
+ : [
+ 'images/instant/nmr_screenshot.png',
+ 'images/instant/kitty_screenshot.png',
+ 'images/instant/rep_screenshot.png',
+ 'images/instant/dai_screenshot.png',
+ 'images/instant/gods_screenshot.png',
+ 'images/instant/gnt_screenshot.png',
+ ];
+ return (
+ <Container backgroundColor={colors.instantPrimaryBackground} className="py3 flex justify-center">
+ {_.map(images, image => {
+ return <img className="px1 flex-none" width="300px" height="420px" src={image} key={image} />;
+ })}
+ </Container>
+ );
+};
diff --git a/packages/website/ts/style/colors.ts b/packages/website/ts/style/colors.ts
index 0620bae0f..f89dfc86e 100644
--- a/packages/website/ts/style/colors.ts
+++ b/packages/website/ts/style/colors.ts
@@ -13,6 +13,9 @@ const appColors = {
jobsPageOpenPositionRow: sharedColors.grey100,
metaMaskOrange: '#f68c24',
metaMaskTransparentOrange: 'rgba(255, 248, 242, 0.8)',
+ instantPrimaryBackground: '#222222',
+ instantSecondaryBackground: '#333333',
+ instantTertiaryBackground: '#444444',
};
export const colors = {
diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts
index 89c477085..9c4b8a018 100644
--- a/packages/website/ts/types.ts
+++ b/packages/website/ts/types.ts
@@ -353,6 +353,7 @@ export enum WebsitePaths {
FAQ = '/faq',
About = '/about',
LaunchKit = '/launch-kit',
+ Instant = '/instant',
Whitepaper = '/pdfs/0x_white_paper.pdf',
SmartContracts = '/docs/contracts',
Connect = '/docs/connect',