aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/website/ts/@next/components/animatedChatIcon.tsx51
-rw-r--r--packages/website/ts/@next/components/animatedCompassIcon.tsx49
-rw-r--r--packages/website/ts/@next/components/blockIconLink.tsx87
-rw-r--r--packages/website/ts/@next/components/icon.tsx33
-rw-r--r--packages/website/ts/@next/components/sections/landing/cta.tsx7
-rw-r--r--packages/website/ts/@next/pages/landing.tsx9
6 files changed, 194 insertions, 42 deletions
diff --git a/packages/website/ts/@next/components/animatedChatIcon.tsx b/packages/website/ts/@next/components/animatedChatIcon.tsx
new file mode 100644
index 000000000..ea97daf48
--- /dev/null
+++ b/packages/website/ts/@next/components/animatedChatIcon.tsx
@@ -0,0 +1,51 @@
+import * as React from 'react';
+import styled, { keyframes } from 'styled-components';
+
+export const AnimatedChatIcon = () => (
+ <svg width="150" height="150" viewBox="0 0 150 150" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <circle cx="75" cy="75" r="73" stroke="#00AE99" stroke-width="3"/>
+ <path d="M76 37H137.5" stroke="#00AE99" stroke-width="3"/>
+ <path d="M37 73.5L37 12M113 137.5L113 75" stroke="#00AE99" stroke-width="3"/>
+ <path d="M13 113H71.5" stroke="#00AE99" stroke-width="3"/>
+ <path d="M49.087 47.5264L92.574 4.03932" stroke="#00AE99" stroke-width="3"/>
+ <path d="M47.3192 100.913L3.8321 57.4259M146.314 92.4277L102.12 48.2335" stroke="#00AE99" stroke-width="3"/>
+ <path d="M58.2793 145.814L101.766 102.327" stroke="#00AE99" stroke-width="3"/>
+ <Bubble>
+ <path vector-effect="non-scaling-stroke" d="M113 75C113 85.3064 108.897 94.6546 102.235 101.5C98.4048 105.436 71 132.5 71 132.5V112.792C51.8933 110.793 37 94.6359 37 75C37 54.0132 54.0132 37 75 37C95.9868 37 113 54.0132 113 75Z" stroke="#00AE99" strokeWidth="3"/>
+ <Dot delay={0} vector-effect="non-scaling-stroke" cx="75" cy="75" r="4" stroke="#00AE99" strokeWidth="3"/>
+ <Dot delay={5.6} vector-effect="non-scaling-stroke" cx="91" cy="75" r="4" stroke="#00AE99" strokeWidth="3"/>
+ <Dot delay={-5.8} vector-effect="non-scaling-stroke" cx="59" cy="75" r="4" stroke="#00AE99" strokeWidth="3"/>
+ </Bubble>
+ </svg>
+);
+
+const scale = keyframes`
+ 0% { transform: scale(1.2) }
+ 20% { transform: scale(1) }
+ 80% { transform: scale(1) }
+ 100% { transform: scale(1.2) }
+`;
+
+const fadeInOut = keyframes`
+ 0%, 50%, 54%, 100% {
+ transform: initial;
+ }
+
+ 25% {
+ transform: translateY(-5px);
+ }
+`;
+
+const Bubble = styled.g`
+ animation: ${scale} 5s infinite cubic-bezier(0.175, 0.885, 0.32, 1.275);
+ transform-origin: 50% 50%;
+
+ path,
+ circle {
+ fill: ${props => props.theme.lightBgColor};
+ }
+`;
+
+const Dot = styled.circle<{ delay: number }>`
+ animation: ${fadeInOut} 5s ${props => `${props.delay}s`} infinite;
+`;
diff --git a/packages/website/ts/@next/components/animatedCompassIcon.tsx b/packages/website/ts/@next/components/animatedCompassIcon.tsx
new file mode 100644
index 000000000..aa0cfd099
--- /dev/null
+++ b/packages/website/ts/@next/components/animatedCompassIcon.tsx
@@ -0,0 +1,49 @@
+import * as React from 'react';
+import styled, { keyframes } from 'styled-components';
+
+export const AnimatedCompassIcon = () => (
+ <svg width="150" height="150" viewBox="0 0 150 150" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <g>
+ <circle cx="75" cy="75" r="73" stroke="#00AE99" stroke-width="3"/>
+ <circle cx="75" cy="75" r="58" stroke="#00AE99" stroke-width="3"/>
+ <Needle d="M62.9792 62.9792L36.6447 113.355L87.0208 87.0208M62.9792 62.9792L113.355 36.6447L87.0208 87.0208M62.9792 62.9792L87.0208 87.0208" stroke="#00AE99" strokeWidth="3"/>
+
+ <Dial>
+ <path d="M75 2V17M75 133V148" stroke="#00AE99" stroke-width="3"/>
+ <path d="M2 75L17 75M133 75L148 75" stroke="#00AE99" stroke-width="3"/>
+ <path d="M11.7801 38.5L24.7705 46M125.229 104L138.22 111.5" stroke="#00AE99" stroke-width="3"/>
+ <path d="M38.5001 11.7801L46.0001 24.7705M104 125.229L111.5 138.22" stroke="#00AE99" stroke-width="3"/>
+ <path d="M111.5 11.7801L104 24.7705M46 125.229L38.5 138.22" stroke="#00AE99" stroke-width="3"/>
+ <path d="M138.22 38.5L125.229 46M24.7705 104L11.7801 111.5" stroke="#00AE99" stroke-width="3"/>
+ </Dial>
+ </g>
+ </svg>
+);
+
+const point = keyframes`
+ 0% { transform: rotate(0deg) }
+ 20% { transform: rotate(10deg) }
+ 30% { transform: rotate(30deg) }
+ 60% { transform: rotate(-20deg) }
+ 80% { transform: rotate(-20deg) }
+ 100% { transform: rotate(0deg) }
+`;
+
+const rotate = keyframes`
+ 0% { transform: rotate(0deg) }
+ 20% { transform: rotate(-10deg) }
+ 30% { transform: rotate(-30deg) }
+ 60% { transform: rotate(20deg) }
+ 80% { transform: rotate(20deg) }
+ 100% { transform: rotate(0deg) }
+`;
+
+const Needle = styled.path`
+ animation: ${point} 5s infinite;
+ transform-origin: 50% 50%;
+`;
+
+const Dial = styled.g`
+ animation: ${rotate} 5s infinite;
+ transform-origin: 50% 50%;
+`;
diff --git a/packages/website/ts/@next/components/blockIconLink.tsx b/packages/website/ts/@next/components/blockIconLink.tsx
index 0e97aed1a..648b5a485 100644
--- a/packages/website/ts/@next/components/blockIconLink.tsx
+++ b/packages/website/ts/@next/components/blockIconLink.tsx
@@ -1,41 +1,72 @@
import * as React from 'react';
+import {withRouter} from 'react-router-dom';
import styled from 'styled-components';
import {Button} from 'ts/@next/components/button';
import {Icon} from 'ts/@next/components/icon';
interface Props {
- icon: string;
+ icon?: string;
+ iconComponent?: React.ReactNode;
title: string;
linkLabel: string;
linkUrl?: string;
linkAction?: () => void;
}
-export const BlockIconLink = (props: Props) => (
- <Wrap>
- <div>
- <Icon
- name={props.icon}
- size="large"
- margin={[0, 0, 'default', 0]}
- />
-
- <Title>
- {props.title}
- </Title>
-
- <Button
- isWithArrow={true}
- isTransparent={true}
- href={props.linkUrl}
- onClick={props.linkAction}
- >
- {props.linkLabel}
- </Button>
- </div>
- </Wrap>
-);
+class BaseComponent extends React.PureComponent<Props> {
+ public onClick = (): void => {
+ const {
+ linkAction,
+ linkUrl,
+ } = this.props;
+
+ if (linkAction) {
+ linkAction();
+ } else {
+ this.props.history.push(linkUrl);
+ }
+ }
+
+ public render(): React.ReactNode {
+ const {
+ icon,
+ iconComponent,
+ linkUrl,
+ linkAction,
+ title,
+ linkLabel,
+ } = this.props;
+
+ return (
+ <Wrap onClick={this.onClick}>
+ <div>
+ <Icon
+ name={icon}
+ component={iconComponent}
+ size="large"
+ margin={[0, 0, 'default', 0]}
+ />
+
+ <Title>
+ {title}
+ </Title>
+
+ <Button
+ isWithArrow={true}
+ isTransparent={true}
+ href={linkUrl}
+ onClick={linkAction}
+ >
+ {linkLabel}
+ </Button>
+ </div>
+ </Wrap>
+ );
+ }
+}
+
+export const BlockIconLink = withRouter(BaseComponent);
const Wrap = styled.div`
width: calc(50% - 15px);
@@ -46,6 +77,12 @@ const Wrap = styled.div`
align-items: center;
text-align: center;
background-color: ${props => props.theme.lightBgColor};
+ cursor: pointer;
+
+ a,
+ button {
+ pointer-events: none;
+ }
@media (max-width: 900px) {
width: 100%;
diff --git a/packages/website/ts/@next/components/icon.tsx b/packages/website/ts/@next/components/icon.tsx
index 84d9f4cb4..e3ad83c94 100644
--- a/packages/website/ts/@next/components/icon.tsx
+++ b/packages/website/ts/@next/components/icon.tsx
@@ -5,20 +5,33 @@ import {getCSSPadding, PaddingInterface} from 'ts/@next/constants/utilities';
interface IconProps extends PaddingInterface {
name: string;
+ component?: React.ReactNode;
size?: 'small' | 'medium' | 'large' | 'hero' | number;
}
export const Icon: React.FunctionComponent<IconProps> = (props: IconProps) => {
- const IconSVG = Loadable({
- loader: () => import(/* webpackChunkName: "icon" */`ts/@next/icons/illustrations/${props.name}.svg`),
- loading: () => 'Loading',
- });
-
- return (
- <StyledIcon {...props}>
- <IconSVG />
- </StyledIcon>
- );
+ if (props.name && !props.component) {
+ const IconSVG = Loadable({
+ loader: () => import(/* webpackChunkName: "icon" */`ts/@next/icons/illustrations/${props.name}.svg`),
+ loading: () => 'Loading',
+ });
+
+ return (
+ <StyledIcon {...props}>
+ <IconSVG />
+ </StyledIcon>
+ );
+ }
+
+ if (props.component) {
+ return (
+ <StyledIcon {...props}>
+ {props.component}
+ </StyledIcon>
+ );
+ }
+
+ return null;
};
export const InlineIconWrap = styled.div<IconProps>`
diff --git a/packages/website/ts/@next/components/sections/landing/cta.tsx b/packages/website/ts/@next/components/sections/landing/cta.tsx
index 49fc48c1c..1a959a6e9 100644
--- a/packages/website/ts/@next/components/sections/landing/cta.tsx
+++ b/packages/website/ts/@next/components/sections/landing/cta.tsx
@@ -3,6 +3,9 @@ import * as React from 'react';
import {BlockIconLink} from 'ts/@next/components/blockIconLink';
import {Section} from 'ts/@next/components/newLayout';
+import {AnimatedChatIcon} from 'ts/@next/components/animatedChatIcon';
+import {AnimatedCompassIcon} from 'ts/@next/components/animatedCompassIcon';
+
interface Props {
onContactClick?: () => void;
}
@@ -16,13 +19,13 @@ export const SectionLandingCta = (props: Props) => (
flexBreakpoint="900px"
>
<BlockIconLink
- icon="getStarted"
+ iconComponent={<AnimatedCompassIcon />}
title="Ready to build on 0x?"
linkLabel="Get Started"
linkUrl="https://0xproject.com/docs"
/>
<BlockIconLink
- icon="getInTouch"
+ iconComponent={<AnimatedChatIcon />}
title="Want help from the 0x team?"
linkLabel="Get in Touch"
linkAction={props.onContactClick}
diff --git a/packages/website/ts/@next/pages/landing.tsx b/packages/website/ts/@next/pages/landing.tsx
index aa3e829b5..6788e08be 100644
--- a/packages/website/ts/@next/pages/landing.tsx
+++ b/packages/website/ts/@next/pages/landing.tsx
@@ -29,18 +29,17 @@ export class NextLanding extends React.Component<Props> {
<SectionLandingHero />
<SectionLandingAbout />
<SectionLandingClients />
- <SectionLandingCta onContactClick={this._onOpenContactModal.bind(this)} />
- <ModalContact isOpen={this.state.isContactModalOpen} onDismiss={this._onDismissContactModal.bind(this)} />
+ <SectionLandingCta onContactClick={this._onOpenContactModal} />
+ <ModalContact isOpen={this.state.isContactModalOpen} onDismiss={this._onDismissContactModal} />
</SiteWrap>
);
}
- private _onOpenContactModal(e: Event): void {
- e.preventDefault();
+ private _onOpenContactModal = (): void => {
this.setState({ isContactModalOpen: true });
}
- private _onDismissContactModal(): void {
+ private _onDismissContactModal = (): void => {
this.setState({ isContactModalOpen: false });
}
}