aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/website/package.json1
-rw-r--r--packages/website/ts/@next/components/blockIconLink.tsx36
-rw-r--r--packages/website/ts/@next/components/button.tsx4
-rw-r--r--packages/website/ts/@next/components/modals/input.tsx65
-rw-r--r--packages/website/ts/@next/components/modals/modal_contact.tsx198
-rw-r--r--packages/website/ts/@next/components/sections/landing/cta.tsx8
-rw-r--r--packages/website/ts/@next/pages/landing.tsx38
-rw-r--r--yarn.lock76
8 files changed, 402 insertions, 24 deletions
diff --git a/packages/website/package.json b/packages/website/package.json
index 629cbffc2..fc98a1a1b 100644
--- a/packages/website/package.json
+++ b/packages/website/package.json
@@ -32,6 +32,7 @@
"@0x/typescript-typings": "^3.0.4",
"@0x/utils": "^2.0.6",
"@0x/web3-wrapper": "^3.1.6",
+ "@reach/dialog": "^0.1.2",
"@types/react-lazyload": "^2.3.1",
"@types/react-loadable": "^5.4.2",
"@types/react-syntax-highlighter": "^0.0.8",
diff --git a/packages/website/ts/@next/components/blockIconLink.tsx b/packages/website/ts/@next/components/blockIconLink.tsx
index cc3e88280..42b260731 100644
--- a/packages/website/ts/@next/components/blockIconLink.tsx
+++ b/packages/website/ts/@next/components/blockIconLink.tsx
@@ -1,14 +1,15 @@
import * as React from 'react';
import styled from 'styled-components';
-import {Link} from 'ts/@next/components/button';
+import {Button, Link} from 'ts/@next/components/button';
import {Icon} from 'ts/@next/components/icon';
interface Props {
icon: string;
title: string;
linkLabel: string;
- linkUrl: string;
+ linkUrl?: string;
+ onClick?: () => void;
}
export const BlockIconLink = (props: Props) => (
@@ -24,14 +25,29 @@ export const BlockIconLink = (props: Props) => (
{props.title}
</Title>
- <Link
- isWithArrow={true}
- isTransparent={true}
- isNoBorder={true}
- href={props.linkUrl}
- >
- {props.linkLabel}
- </Link>
+ {props.linkUrl &&
+ <Link
+ isWithArrow={true}
+ isTransparent={true}
+ isNoBorder={true}
+ href={props.linkUrl}
+ onClick={props.onClick}
+ >
+ {props.linkLabel}
+ </Link>
+ }
+
+ {props.onClick &&
+ <Button
+ isWithArrow={true}
+ isTransparent={true}
+ isNoBorder={true}
+ href={props.linkUrl}
+ onClick={props.onClick}
+ >
+ {props.linkLabel}
+ </Button>
+ }
</div>
</Wrap>
);
diff --git a/packages/website/ts/@next/components/button.tsx b/packages/website/ts/@next/components/button.tsx
index 3f14b59bd..5d44f1ce5 100644
--- a/packages/website/ts/@next/components/button.tsx
+++ b/packages/website/ts/@next/components/button.tsx
@@ -16,6 +16,8 @@ interface ButtonInterface {
isWithArrow?: boolean;
isAccentColor?: boolean;
hasIcon?: boolean | string;
+ isInline?: boolean;
+ type?: string;
href?: string;
onClick?: () => any;
theme?: {
@@ -57,7 +59,7 @@ export const Button = styled.button<ButtonInterface>`
}
`;
-export const Link = (props: ButtonInterface) => {
+export const Link: React.ReactNode = (props: ButtonInterface) => {
const {
children,
href,
diff --git a/packages/website/ts/@next/components/modals/input.tsx b/packages/website/ts/@next/components/modals/input.tsx
new file mode 100644
index 000000000..eee2d4102
--- /dev/null
+++ b/packages/website/ts/@next/components/modals/input.tsx
@@ -0,0 +1,65 @@
+import * as React from 'react';
+import styled from 'styled-components';
+
+import { colors } from 'ts/style/colors';
+
+export enum InputWidth {
+ Half,
+ Full,
+}
+
+interface InputProps {
+ name: string;
+ width: InputWidth;
+ label: string;
+ type?: string;
+}
+
+interface LabelProps {
+ string: boolean;
+}
+
+export const Input = React.forwardRef((props: InputProps, ref) => {
+ const { name, label, type } = props;
+ const id = `input-${name}`;
+
+ return (
+ <InputWrapper {...props}>
+ <Label htmlFor={id}>{label}</Label>
+ <StyledInput ref={ref} id={id} placeholder={label} {...props} />
+ </InputWrapper>
+ );
+});
+
+Input.defaultProps = {
+ width: InputWidth.Full,
+};
+
+const StyledInput = styled.input`
+ appearance: none;
+ background-color: #fff;
+ border: 1px solid #D5D5D5;
+ color: #000;
+ font-size: 1.294117647rem;
+ padding: 16px 15px;
+ outline: none;
+ width: 100%;
+
+ &::placeholder {
+ color: #9D9D9D;
+ }
+`;
+
+const InputWrapper = styled.div<InputProps>`
+ position: relative;
+ flex-grow: ${props => props.width === InputWidth.Full && 1};
+ width: ${props => props.width === InputWidth.Half && `calc(50% - 15px)`};
+`;
+
+const Label = styled.label`
+ color: #000;
+ font-size: 1.111111111rem;
+ line-height: 1.4em;
+ margin-bottom: 10px;
+ display: inline-block;
+`;
diff --git a/packages/website/ts/@next/components/modals/modal_contact.tsx b/packages/website/ts/@next/components/modals/modal_contact.tsx
new file mode 100644
index 000000000..cd6335103
--- /dev/null
+++ b/packages/website/ts/@next/components/modals/modal_contact.tsx
@@ -0,0 +1,198 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+import {Link as RouterLink} from 'react-router-dom';
+import styled, {withTheme} from 'styled-components';
+
+import { colors } from 'ts/style/colors';
+
+import {
+ Dialog,
+ DialogOverlay,
+ DialogContent
+ } from "@reach/dialog";
+import "@reach/dialog/styles.css";
+
+import {Button} from 'ts/@next/components/button';
+import {Column, Wrap, WrapGrid} from 'ts/@next/components/layout';
+import { Icon } from 'ts/@next/components/icon';
+import {Input, InputWidth} from 'ts/@next/components/modals/input';
+import {Heading, Paragraph} from 'ts/@next/components/text';
+import {GlobalStyle} from 'ts/@next/constants/globalStyle';
+
+interface Props {
+ theme?: GlobalStyle;
+ isOpen?: boolean;
+ onDismiss?: () => void;
+}
+
+interface FormProps {
+ isSuccessful?: boolean;
+ isSubmitting?: boolean;
+}
+
+export class ModalContact extends React.Component<Props> {
+ public state = {
+ isSubmitting: false,
+ isSuccessful: false,
+ };
+ public constructor(props: Props) {
+ super(props);
+ }
+ public render(): React.ReactNode {
+ const {isOpen, onDismiss} = this.props;
+ const {isSuccessful} = this.state;
+
+ return (
+ <>
+ <DialogOverlay
+ style={{ background: 'rgba(0, 0, 0, 0.75)' }}
+ isOpen={isOpen}
+ >
+ <StyledDialogContent>
+ <Form onSubmit={this._onSubmit.bind(this)} isSuccessful={isSuccessful}>
+ <Heading color={colors.textDarkPrimary} size={34} asElement="h2">Contact the 0x Core Team</Heading>
+ <Paragraph isMuted={true} color={colors.textDarkPrimary}>If you're considering building on 0x, we're happy to answer your questions. Fill out the form so we can connect you with the right person to help you get started.</Paragraph>
+ <InputRow>
+ <Input
+ name="name"
+ label="Your name"
+ type="text"
+ width={InputWidth.Half}
+ />
+ <Input
+ name="email"
+ label="Your email"
+ type="email"
+ width={InputWidth.Half}
+ />
+ </InputRow>
+ <InputRow>
+ <Input
+ name="companyOrProject"
+ label="Name of your project / company"
+ type="text"
+ />
+ </InputRow>
+ <InputRow>
+ <Input
+ name="link"
+ label="Do you have any documentation or a website?"
+ type="text"
+ />
+ </InputRow>
+ <InputRow>
+ <Input
+ name="comments"
+ label="Anything else?"
+ type="text"
+ />
+ </InputRow>
+ <InputRow>
+ <Button
+ color="#5C5C5C"
+ isNoBorder={true}
+ isTransparent={true}
+ type="button"
+ onClick={this.props.onDismiss}
+ >
+ Back
+ </Button>
+ <Button>Submit</Button>
+ </InputRow>
+ </Form>
+ <Confirmation isSuccessful={isSuccessful}>
+ <Icon name="checkmark" size="large" />
+ <Heading color={colors.textDarkPrimary} size={34} asElement="h2">Thanks for contacting us.</Heading>
+ <Paragraph isMuted={true} color={colors.textDarkPrimary}>We'll get back to you soon. If you need quick support in the meantime, reach out to the 0x team on Discord.</Paragraph>
+ <Button onClick={this.props.onDismiss}>Done</Button>
+ </Confirmation>
+ </StyledDialogContent>
+ </DialogOverlay>
+ </>
+ );
+ }
+ private async _onSubmit(e): void {
+ e.preventDefault();
+
+ // const email = this.emailInput.current.value;
+ const email = 'fred@sjelfull.no';
+
+ this.setState({ ...this.state, isSubmitting: true });
+
+ try {
+ const response = await fetch('/email', {
+ method: 'post',
+ headers: {
+ 'content-type': 'application/json; charset=utf-8',
+ },
+ body: JSON.stringify({ email }),
+ });
+ const json = await response.json();
+
+ console.log(response.json());
+ } catch (e) {
+ console.log(e);
+ }
+
+ this.setState({ ...this.state, isSuccessful: true });
+ }
+ private async _onDone(e): void {
+ e.preventDefault();
+
+ this.props.onDismiss();
+ }
+};
+
+const StyledWrap = styled(Wrap)`
+ padding-top: 20px;
+ margin-top: 30px;
+ position: relative;
+
+ &:before {
+ content: '';
+ width: 100%;
+ height: 1px;
+ background-color: ${props => props.theme.dropdownColor};
+ opacity: 0.15;
+ position: absolute;
+ top: 0;
+ left:0;
+ }
+`;
+
+const InputRow = styled.div`
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 30px;
+ width: 100%;
+ flex: 0 0 auto;
+`;
+
+const StyledDialogContent = styled(DialogContent)`
+ position: relative;
+ max-width: 800px;
+ background-color: #F6F6F6 !important;
+ padding: 60px 60px !important;
+`;
+
+const Form = styled.form<FormProps>`
+ position: relative;
+ transition: opacity 0.30s ease-in-out, visibility 0.30s ease-in-out;
+
+ opacity: ${props => props.isSuccessful && `0`};
+ visibility: ${props => props.isSuccessful && `hidden`};
+`;
+
+const Confirmation = styled.div<FormProps>`
+ position: absolute;
+ top: 50%;
+ text-align: center;
+ width: 100%;
+ left: 0;
+ transition: opacity 0.30s ease-in-out, visibility 0.30s ease-in-out;
+ transition-delay: 0.40s;
+ padding: 60px 60px;
+ transform: translateY(-50%);
+ opacity: ${props => props.isSuccessful ? `1` : `0`};
+ visibility: ${props => props.isSuccessful ? 'visible' : `hidden`};
+`;
diff --git a/packages/website/ts/@next/components/sections/landing/cta.tsx b/packages/website/ts/@next/components/sections/landing/cta.tsx
index 4c06982e4..b90b4070e 100644
--- a/packages/website/ts/@next/components/sections/landing/cta.tsx
+++ b/packages/website/ts/@next/components/sections/landing/cta.tsx
@@ -8,7 +8,11 @@ import {Column, Section} from 'ts/@next/components/newLayout';
import {BlockIconLink} from 'ts/@next/components/blockIconLink';
-export const SectionLandingCta = () => (
+interface Props {
+ onContactClick?: () => void;
+}
+
+export const SectionLandingCta = (props: Props) => (
<Section
isPadded={false}
isFullWidth={true}
@@ -25,7 +29,7 @@ export const SectionLandingCta = () => (
icon="coin"
title="Wat help from the 0x team?"
linkLabel="Get in Touch"
- linkUrl="#"
+ onClick={props.onContactClick}
/>
</Section>
);
diff --git a/packages/website/ts/@next/pages/landing.tsx b/packages/website/ts/@next/pages/landing.tsx
index fab5e62b6..5ead1b6b5 100644
--- a/packages/website/ts/@next/pages/landing.tsx
+++ b/packages/website/ts/@next/pages/landing.tsx
@@ -7,9 +7,7 @@ import {SectionLandingClients} from 'ts/@next/components/sections/landing/client
import {SectionLandingCta} from 'ts/@next/components/sections/landing/cta';
import {SectionLandingHero} from 'ts/@next/components/sections/landing/hero';
-import {Button} from 'ts/@next/components/button';
-import {Hero} from 'ts/@next/components/hero';
-import {LandingAnimation} from 'ts/@next/components/heroImage';
+import { ModalContact } from 'ts/@next/components/modals/modal_contact';
import LogoOutlined from 'ts/@next/icons/illustrations/logo-outlined.svg';
@@ -21,11 +19,29 @@ interface Props {
};
}
-export const NextLanding: React.StatelessComponent<{}> = (props: Props) => (
- <SiteWrap theme="dark">
- <SectionLandingHero />
- <SectionLandingAbout />
- <SectionLandingClients />
- <SectionLandingCta />
- </SiteWrap>
-);
+export class NextLanding extends React.Component<Props> {
+ public state = {
+ isContactModalOpen: false,
+ };
+ public render(): React.ReactNode {
+ return (
+ <SiteWrap theme="dark">
+ <SectionLandingHero />
+ <SectionLandingAbout />
+ <SectionLandingClients />
+ <SectionLandingCta onContactClick={this._onOpenContactModal.bind(this)} />
+ <ModalContact isOpen={this.state.isContactModalOpen} onDismiss={this._onDismissContactModal.bind(this)} />
+ </SiteWrap>
+ );
+ }
+
+ private _onOpenContactModal(e): void {
+ e.preventDefault();
+
+ this.setState({ isContactModalOpen: true });
+ }
+
+ private _onDismissContactModal(): void {
+ this.setState({ isContactModalOpen: false });
+ }
+}
diff --git a/yarn.lock b/yarn.lock
index cfaaf9e9f..7d5f0dc1b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1203,6 +1203,33 @@
call-me-maybe "^1.0.1"
glob-to-regexp "^0.3.0"
+"@reach/component-component@^0.1.1":
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/@reach/component-component/-/component-component-0.1.1.tgz#62ea2ec290da32f5e3a9872fb51f9a3ae4370cc4"
+ integrity sha512-4HxyyOLo/nDg0LlgYvzgqpTGaxqKmrZB8/y5wWhtyvGzgKAb1DJzSnYRaFsgGGgkQAQmhwPXKZ0H/rOAkxXJ8Q==
+
+"@reach/dialog@^0.1.2":
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/@reach/dialog/-/dialog-0.1.2.tgz#46a3639c01928e125110fd5ccb753281172e844d"
+ integrity sha512-aaBS2a4ZNKGpqsjCdZukYhjf1x75sZ1lQrYg9mJq21Nfz9kk0Yx6zn4LR7ZYxgqkGj5/CQOSciGuUPF+Z8k9nA==
+ dependencies:
+ "@reach/component-component" "^0.1.1"
+ "@reach/portal" "^0.1.1"
+ "@reach/utils" "^0.1.2"
+ focus-trap "^3.0.0"
+
+"@reach/portal@^0.1.1":
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/@reach/portal/-/portal-0.1.1.tgz#94f3f9b999c5a0dfb819309912ec23e36807e70b"
+ integrity sha512-AWsOH2TLfetlUzw3wbpy6n8trnuFI7N/HB2jYjrBRP5IbG/PmgrVQiL/HFP/OsCbbOo0rK7AsKnG7qyOf0r4Tg==
+ dependencies:
+ "@reach/component-component" "^0.1.1"
+
+"@reach/utils@^0.1.2":
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.1.2.tgz#72f547b5c9b0401a56de303d9e508abf6d3fa56a"
+ integrity sha512-HpDR5BeCApr3HufQtpg0P5b9sl0S66zikZSMtC/2jZBvrDzjVaT9O8PbKTQqW0PdkMNrnBkX1UtlrrM1TN3/Og==
+
"@samverschueren/stream-to-observable@^0.3.0":
version "0.3.0"
resolved "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f"
@@ -1236,6 +1263,11 @@
version "0.4.1"
resolved "https://registry.yarnpkg.com/@types/accounting/-/accounting-0.4.1.tgz#865d9f5694fd7c438fba34eb4bc82eec6f34cdd5"
+"@types/anymatch@*":
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.0.tgz#d1d55958d1fccc5527d4aba29fc9c4b942f563ff"
+ integrity sha512-7WcbyctkE8GTzogDb0ulRAEw7v8oIS54ft9mQTU7PfM0hp5e+8kpa+HeQ7IQrFbKtJXBKcZ4bh+Em9dTw5L6AQ==
+
"@types/axios@^0.14.0":
version "0.14.0"
resolved "https://registry.yarnpkg.com/@types/axios/-/axios-0.14.0.tgz#ec2300fbe7d7dddd7eb9d3abf87999964cafce46"
@@ -1597,6 +1629,14 @@
dependencies:
"@types/react" "*"
+"@types/react-loadable@^5.4.2":
+ version "5.4.2"
+ resolved "https://registry.yarnpkg.com/@types/react-loadable/-/react-loadable-5.4.2.tgz#087ead218ee0494c44e41fbdec7477b0ea4b7c86"
+ integrity sha512-F9hv1ErL1zRch8u6VNuxqXSvSr/WdlfpLhU1UcipHRWg1NXZ8pq2Dh7Uqkp+11ex9wocu/F26Edw4Hn318k6cA==
+ dependencies:
+ "@types/react" "*"
+ "@types/webpack" "*"
+
"@types/react-redux@^4.4.37":
version "4.4.47"
resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-4.4.47.tgz#12af1677116e08d413fe2620d0a85560c8a0536e"
@@ -1740,10 +1780,22 @@
"@types/react" "*"
csstype "^2.2.0"
+"@types/tapable@*":
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.4.tgz#b4ffc7dc97b498c969b360a41eee247f82616370"
+ integrity sha512-78AdXtlhpCHT0K3EytMpn4JNxaf5tbqbLcbIRoQIHzpTIyjpxLQKRoxU55ujBXAtg3Nl2h/XWvfDa9dsMOd0pQ==
+
"@types/tmp@^0.0.33":
version "0.0.33"
resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d"
+"@types/uglify-js@*":
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.0.4.tgz#96beae23df6f561862a830b4288a49e86baac082"
+ integrity sha512-SudIN9TRJ+v8g5pTG8RRCqfqTMNqgWCKKd3vtynhGzkIIjxaicNAMuY5TRadJ6tzDu3Dotf3ngaMILtmOdmWEQ==
+ dependencies:
+ source-map "^0.6.1"
+
"@types/uuid@^3.4.2", "@types/uuid@^3.4.3":
version "3.4.3"
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.3.tgz#121ace265f5569ce40f4f6d0ff78a338c732a754"
@@ -1760,6 +1812,17 @@
dependencies:
"@types/ethereum-protocol" "*"
+"@types/webpack@*":
+ version "4.4.21"
+ resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.4.21.tgz#1a80de6d3e465f35067dd2f4533bf6e04c2e7187"
+ integrity sha512-QJfA6GeLSlnx8yyrEQ7fNLYj1MYKzqHlo89skOwnKG4nblpwAyXe9Gcm/eTz/BpX0vBEtiehrSv9b/W9TMkhKg==
+ dependencies:
+ "@types/anymatch" "*"
+ "@types/node" "*"
+ "@types/tapable" "*"
+ "@types/uglify-js" "*"
+ source-map "^0.6.0"
+
"@types/websocket@^0.0.39":
version "0.0.39"
resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-0.0.39.tgz#aa971e24f9c1455fe2a57ee3e69c7d395016b12a"
@@ -6995,6 +7058,14 @@ flush-write-stream@^1.0.0, flush-write-stream@^1.0.2:
inherits "^2.0.1"
readable-stream "^2.0.4"
+focus-trap@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-3.0.0.tgz#4d2ee044ae66bf7eb6ebc6c93bd7a1039481d7dc"
+ integrity sha512-jTFblf0tLWbleGjj2JZsAKbgtZTdL1uC48L8FcmSDl4c2vDoU4NycN1kgV5vJhuq1mxNFkw7uWZ1JAGlINWvyw==
+ dependencies:
+ tabbable "^3.1.0"
+ xtend "^4.0.1"
+
follow-redirects@^1.3.0:
version "1.5.8"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.8.tgz#1dbfe13e45ad969f813e86c00e5296f525c885a1"
@@ -15452,6 +15523,11 @@ symbol-tree@^3.2.2:
version "3.2.2"
resolved "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6"
+tabbable@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-3.1.1.tgz#db7512f28a9a1ed16e4275bd190131be9d5ad8e9"
+ integrity sha512-583MHIOwictf7+zbxqO/L5fBqMN6Li4SJ1XTKQA9WzHRA7c2BB+D+Ny7Y6kGqU2u+rHK59+oRzrBvMU53aZz+A==
+
table@4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36"