aboutsummaryrefslogtreecommitdiffstats
path: root/packages/website/ts/pages/instant.tsx
blob: 586665d5ba8e3b50749e01059af718927c9fa9aa (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
import { utils as sharedUtils } from '@0x/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
import DocumentTitle from 'react-document-title';
import styled, { keyframes } from 'styled-components';

import { Banner } from 'ts/components/banner';
import { Button } from 'ts/components/button';
import { Definition } from 'ts/components/definition';
import { Hero } from 'ts/components/hero';
import { Section, SectionProps } from 'ts/components/newLayout';
import { SiteWrap } from 'ts/components/siteWrap';
import { Heading, Paragraph } from 'ts/components/text';
import { Configurator } from 'ts/pages/instant/configurator';
import { colors } from 'ts/style/colors';
import { WebsitePaths } from 'ts/types';
import { utils } from 'ts/utils/utils';

import { ModalContact } from '../components/modals/modal_contact';

const CONFIGURATOR_MIN_WIDTH_PX = 1050;

export const getStartedClick = () => {
    if (window.innerWidth < CONFIGURATOR_MIN_WIDTH_PX) {
        utils.openUrl(`${WebsitePaths.Wiki}#Get-Started-With-Instant`);
    } else {
        sharedUtils.setUrlHash('configurator');
        sharedUtils.scrollToHash('configurator', '');
    }
};

const featuresData = [
    {
        title: 'Support ERC-20 and ERC-721 tokens',
        icon: 'supportForAllEthereumStandards-large',
        description:
            'Seamlessly integrate token purchasing into your product experience by offering digital assets ranging from in-game items to stablecoins.',
        links: [
            {
                label: 'Get Started',
                onClick: getStartedClick,
                shouldUseAnchorTag: true,
            },
            {
                label: 'Explore the Docs',
                url: `${WebsitePaths.Wiki}#Get-Started-With-Instant`,
            },
        ],
    },
    {
        title: 'Generate revenue for your business',
        icon: 'generateRevenueForYourBusiness-large',
        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.',
        links: [
            {
                label: 'Learn about affiliate fees',
                url: `${WebsitePaths.Wiki}#Learn-About-Affiliate-Fees`,
            },
        ],
    },
    {
        title: 'Easy and flexible integration',
        icon: 'flexibleIntegration0xInstant',
        description:
            'Use our out-of-the-box design or customize the user interface by integrating via the AssetBuyer engine.. You can also tap into 0x networked liquidity or choose your own liquidity pool.',
        links: [
            {
                label: 'Explore AssetBuyer',
                url: `${WebsitePaths.Docs}/asset-buyer`,
            },
        ],
    },
];

interface Props {
    theme: {
        bgColor: string;
        textColor: string;
        linkColor: string;
    };
}

export class Next0xInstant extends React.Component<Props> {
    public state = {
        isContactModalOpen: false,
    };
    public render(): React.ReactNode {
        return (
            <SiteWrap>
                <DocumentTitle title="0x Instant: Quick and secure crypto purchasing" />
                <Hero
                    title="Introducing 0x Instant"
                    description="A free and flexible way to offer simple crypto purchasing in any app or website"
                    actions={<Button onClick={getStartedClick}>Get Started</Button>}
                />

                <Section isFullWidth={true} isPadded={false} padding="30px 0">
                    <MarqueeWrap>
                        <div>
                            {[...Array(18)].map((item, index) => (
                                <Card key={`card-${index}`} index={index}>
                                    <img src={`/images/0x-instant/widget-${(index % 6) + 1}.png`} />
                                </Card>
                            ))}
                        </div>
                    </MarqueeWrap>
                </Section>

                <Section>
                    {_.map(featuresData, (item, index) => (
                        <Definition
                            key={`definition-${index}`}
                            icon={item.icon}
                            title={item.title}
                            description={item.description}
                            isInlineIcon={true}
                            iconSize={240}
                            actions={item.links}
                        />
                    ))}
                </Section>

                <ConfiguratorSection
                    id="configurator"
                    maxWidth="1386px"
                    padding="0 58px 70px"
                    bgColor={colors.backgroundDark}
                >
                    <Heading>0x Instant Configurator</Heading>
                    <Configurator />
                </ConfiguratorSection>

                <Banner
                    heading="Need more flexibility?"
                    subline="Dive into our docs, or contact us if needed"
                    mainCta={{ text: 'Explore the Docs', href: `${WebsitePaths.Wiki}#Get-Started-With-Instant` }}
                    secondaryCta={{ text: 'Get in Touch', onClick: this._onOpenContactModal.bind(this) }}
                />
                <ModalContact isOpen={this.state.isContactModalOpen} onDismiss={this._onDismissContactModal} />

                <Section maxWidth="1170px" isPadded={false} padding="60px 0">
                    <Paragraph size="small" isMuted={0.5}>
                        Disclaimer: The laws and regulations applicable to the use and exchange of digital assets and
                        blockchain-native tokens, including through any software developed using the licensed work
                        created by ZeroEx Intl. (the “Work”), vary by jurisdiction. As set forth in the Apache License,
                        Version 2.0 applicable to the Work, developers are “solely responsible for determining the
                        appropriateness of using or redistributing the Work,” which includes responsibility for ensuring
                        compliance with any such applicable laws and regulations.
                    </Paragraph>
                    <Paragraph size="small" isMuted={0.5}>
                        See the Apache License, Version 2.0 for the specific language governing all applicable
                        permissions and limitations.
                    </Paragraph>
                </Section>
            </SiteWrap>
        );
    }

    public _onOpenContactModal = (): void => {
        this.setState({ isContactModalOpen: true });
    };

    public _onDismissContactModal = (): void => {
        this.setState({ isContactModalOpen: false });
    };
}

// scroll animation calc is simply (imageWidth * totalRepetitions) / 2
// img width is 370px
const scroll = keyframes`
    0% { transform: translate3d(-2220px, 0, 0) }
    100% { transform: translate3d(-4440px, 0, 0) }
`;

const scrollMobile = keyframes`
    0% { transform: translate3d(0, 0, 0) }
    100% { transform: translate3d(-1800px, 0, 0) }
`;

const fadeUp = keyframes`
  0% {
    opacity: 0;
    transform: translateY(50px);
  }
  100% {
    opacity: 1;
    transform: translateY(0px);
  }
`;

const ConfiguratorSection = styled(Section)<SectionProps>`
    @media (max-width: ${CONFIGURATOR_MIN_WIDTH_PX}px) {
        display: none;
    }
`;

// width = 370 * 12
// mobile width = 300
const MarqueeWrap = styled.div`
    width: 100vw;
    height: 514px;
    padding-bottom: 60px;

    @media (max-width: 768px) {
        width: calc(100% + 60px);
        margin-left: -30px;
        overflow: hidden;
    }

    > div {
        height: auto;
        display: flex;
        will-change: transform;
        transform: translate3d(-2220px, 0, 0);
    }

    @media (min-width: 768px) {
        > div {
            width: 6660px;
            animation: ${scroll} 70s linear infinite;
        }
    }

    @media (max-width: 768px) {
        > div {
            width: 5400px;
            animation: ${scrollMobile} 70s linear infinite;
        }
    }
`;

const Card = styled.div<{ index: number }>`
    opacity: 0;
    flex-shrink: 0;
    transform: translateY(10px);
    will-change: opacity, transform;
    animation: ${fadeUp} 0.75s ${props => `${props.index * 0.05}s`} forwards;

    img {
        height: auto;
    }

    @media (min-width: 768px) {
        img {
            width: 370px;
        }
    }

    @media (max-width: 768px) {
        img {
            width: 300px;
        }
    }
`;