-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathindex.tsx
382 lines (375 loc) · 17.5 KB
/
index.tsx
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
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
import { useState, useEffect } from 'react';
import classNames from 'classnames';
import type { NextPage } from 'next';
import Head from 'next/head';
import { Layout, Button, Icon, CodeBlock, CodeBlockHeader, Accordion } from '@/components';
import { ChartMotion, StateSharingMotion, ServerMotion, MainBannerMotion } from '@/components/motions';
import UserGroupSVG from '@/public/assets/icons/icon_service_main_users_group.svg';
import CollaboProfileSVG from '@/public/assets/icons/icon_collaborate_profile.svg';
import CollaboCursorSVG from '@/public/assets/icons/icon_collaborate_cursor.svg';
import CollaboSelectionSVG from '@/public/assets/icons/icon_collaborate_selection.svg';
import CollaboEditingSVG from '@/public/assets/icons/icon_collaborate_editing.svg';
import { FEATURES_CODE } from '@/codes/features';
type FeatureType = keyof typeof FEATURES_CODE;
const Home: NextPage = () => {
const [bannerActive, setBannerActive] = useState(false);
const [activeFeatureCard, setActiveFeatureCard] = useState<FeatureType>('profile');
const [activeFeatureCode, setActiveFeatureCode] = useState({ type: 'js', info: FEATURES_CODE.profile.js });
useEffect(() => {
const handleVisualSize = () => {
const $visual = document.querySelector('.kv_bg svg') as HTMLElement;
if (!$visual) return;
const SVG_ASPECT_RATIO = 1512 / 868;
const HEADER_HEIGHT = 64;
const scale = window.innerWidth / ((window.innerHeight - HEADER_HEIGHT) * SVG_ASPECT_RATIO);
$visual.style.setProperty('--scale', scale < 1 ? '1' : `${scale}`);
};
window.addEventListener('resize', handleVisualSize);
handleVisualSize();
return () => {
window.removeEventListener('resize', handleVisualSize);
};
}, []);
// TODO(hackerwins): Remove examples condition when examples are ready.
return (
<Layout className="main_page">
<Head>
<title>Yorkie</title>
</Head>
<div className="content">
<section className="key_visual">
<div className="kv_bg">
<MainBannerMotion bannerActive={bannerActive} />
</div>
<div className="inner">
<h2 className="title">
<span className="text">Bring</span>
<span className={classNames('point', { is_hover: bannerActive })}>
collaboration
<span className="bg"></span>
</span>
<span className="text">to your app</span>
</h2>
<Button.Box>
<a
href={`${process.env.NEXT_PUBLIC_DASHBOARD_PATH}`}
className="btn orange_0 btn_start"
onPointerOver={() => setBannerActive(true)}
onPointerOut={() => setBannerActive(false)}
>
<span className="bg"></span>
<Icon type="star" />
<span className="text">Start for free</span>
</a>
</Button.Box>
<p className="desc">
Unlock the full potential of real-time collaboration with open-source SDKs and API package.
</p>
</div>
</section>
<section className="section section_app">
<div className="align_box">
<div className="app_header">
<h2 className="tag_name">Extend Your App with Yorkie</h2>
<span className="icon">
<UserGroupSVG />
</span>
</div>
<div className="app_body">
<strong className="section_title">
Make your product
<br />
<span className="point">collaborative</span> in a flash!
</strong>
<p className="section_desc">
Easily add collaboration to your apps with our API-based services. <br /> Sign up now and start building
powerful, high-performance collaborative features in no time.
</p>
<Button.Box>
<Button as="link" href="/docs/getting-started" className="orange_0" icon={<Icon type="book" />}>
Getting Started
</Button>
<Button as="link" href="/docs" outline icon={<Icon type="book" />}>
Read documentation
</Button>
</Button.Box>
</div>
</div>
</section>
<section className="section">
<h2 className="section_title">
Variety of <br className="br_mo" /> collaboration features <br /> for your app
</h2>
<p className="section_desc">
Easily add stable and diverse collaborative features <br className="br_mo" />
to your product with Yorkie. <br />
Transform your local-based product into a <br className="br_mo" /> collaborative online experience with our
powerful tools. <br />
Sign up now and start providing your users <br className="br_mo" /> with a completely new real-time
experience.
</p>
<div className="section_content">
<ul
className="service_card_list"
onClick={(e) => {
const target = (e.target as Element).closest('.service_card_menu');
if (!target) return;
const featureType = target.getAttribute('data-item') as FeatureType;
const codeType = FEATURES_CODE[featureType].tabOrder[0];
setActiveFeatureCard(featureType);
setActiveFeatureCode({
type: codeType,
info: (FEATURES_CODE[featureType] as any)[codeType],
});
}}
>
<li className={classNames('service_card_item', { is_active: activeFeatureCard === 'profile' })}>
<button type="button" className="service_card_menu" data-item="profile">
<span className="img_box">
<CollaboProfileSVG />
</span>
<strong className="service_card_title">Profile Stack</strong>
<span className="service_card_desc">
The Profile Stack feature shows the profile of the current users in real-time to announce that
multiple users are connected at the same time.
</span>
</button>
</li>
<li className={classNames('service_card_item', { is_active: activeFeatureCard === 'cursor' })}>
<button type="button" className="service_card_menu" data-item="cursor">
<span className="img_box">
<CollaboCursorSVG />
</span>
<strong className="service_card_title">Multi-Cursor</strong>
<span className="service_card_desc">
The Multi-Cursor shows the location of the cursor of the users who accessed the same canvas in
real-time. Each cursor shows the user's nickname and role as needed.
</span>
</button>
</li>
{process.env.NODE_ENV === 'development' && (
<>
<li className={classNames('service_card_item', { is_active: activeFeatureCard === 'selection' })}>
<button type="button" className="service_card_menu" data-item="selection">
<span className="img_box">
<CollaboSelectionSVG />
</span>
<strong className="service_card_title">Live Selection</strong>
<span className="service_card_desc">
Live Selection displays the object selected by each user who accesses the same canvas. Users can
see what each other is doing in real-time.
</span>
</button>
</li>
<li className={classNames('service_card_item', { is_active: activeFeatureCard === 'editing' })}>
<button type="button" className="service_card_menu" data-item="editing">
<span className="img_box">
<CollaboEditingSVG />
</span>
<strong className="service_card_title">Multiplayer Editing</strong>
<span className="service_card_desc">
Interact in real-time with the presence of others and edit material together. Any real-time
interaction, such as texting, drawing, commenting, or expressing emotion, could be shared with
Yorkie.
</span>
</button>
</li>
</>
)}
</ul>
<CodeBlock.Wrapper>
<CodeBlockHeader>
<CodeBlockHeader.LeftBox>
{FEATURES_CODE[activeFeatureCard].tabOrder.map((codeType) => (
<button
type="button"
key={codeType}
className={classNames('btn_item', { is_active: activeFeatureCode.type === codeType })}
onClick={() =>
setActiveFeatureCode({
type: codeType,
info: (FEATURES_CODE[activeFeatureCard] as any)[codeType],
})
}
>
{(FEATURES_CODE[activeFeatureCard] as any)[codeType].title}
</button>
))}
</CodeBlockHeader.LeftBox>
<CodeBlockHeader.RightBox>
<CodeBlockHeader.CopyButton value={activeFeatureCode.info.code} />
</CodeBlockHeader.RightBox>
</CodeBlockHeader>
<CodeBlock
code={activeFeatureCode.info.code}
language={activeFeatureCode.info.language as any}
withLineNumbers
/>
</CodeBlock.Wrapper>
</div>
</section>
{process.env.NODE_ENV === 'development' && (
<section className="section">
<h2 className="section_title">
What experiences <br />
can you create
<br className="br_mo_xs" /> with Yorkie?
</h2>
<p className="section_desc">Test our examples to add diverse collaborative features to your product.</p>
<div className="section_content draw">
<div className="draw_box"></div>
<div className="draw_box"></div>
</div>
<Button.Box>
<Button as="link" href="/examples" className="orange_0" icon={<Icon type="bulb" />}>
View all examples
</Button>
</Button.Box>
</section>
)}
<section className="section">
<h2 className="section_title">
Stable.
<br />
Reliable.
<br />
Manageable.
</h2>
<div className="section_content">
<ul className="horizon_list">
<li className="horizon_item">
<div className="img_box">
<StateSharingMotion />
</div>
<div className="text_box">
<strong className="title">Document and Presence</strong>
<p className="desc">
Document is stored using conflict-free replicated data types(CRDTs), which ensures that multiple
users can edit the same data concurrently without encountering conflicts. Presence represents a
peer's awareness of the data being edited. It is used to track which users are currently
editing the document.
</p>
<Button
as="link"
href="/products#document-and-presence"
className="gray800"
icon={<Icon type="book" />}
>
Learn more about Document and Presence
</Button>
</div>
</li>
<li className="horizon_item">
<div className="img_box">
<ChartMotion />
</div>
<div className="text_box">
<strong className="title">Data Warehouse with Dashboard</strong>
<p className="desc">
Dashboard allows users to easily browse stored documents and monitor the data warehouse in
real-time. With Dashboard, users can quickly and easily supervise the data warehouse and ensure that
it is functioning properly.
</p>
<Button as="link" href="/products#dashboard" className="gray800" icon={<Icon type="book" />}>
Learn more about Dashboard
</Button>
</div>
</li>
<li className="horizon_item">
<div className="img_box">
<ServerMotion />
</div>
<div className="text_box">
<strong className="title">Cloud or Self-Hosted Server</strong>
<p className="desc">
Yorkie offers flexible deployment options, allowing user to use a cloud or host the server on your
own premises. Whether you want the convenience of cloud or the control of a self-hosted server,
Yorkie has you covered.
</p>
<Button as="link" href="/products#self-hosted-server" className="gray800" icon={<Icon type="book" />}>
Learn more about Self-Hosted Server
</Button>
</div>
</li>
</ul>
</div>
</section>
<section className="section section_faq">
<h2 className="section_title">FAQ</h2>
<div className="section_content">
<Accordion defaultValue={[]} multiple icon={null}>
<Accordion.Item value="faq1">
<Accordion.Control>
<Icon type="messageSquare" />
Can we use the Yorkie for free?
</Accordion.Control>
<Accordion.Panel>
Yes, Yorkie is free to use. <br />
<br />
You can access it at no cost. Please note that the availability of the service and any associated
features may be subject to change without notice. It is always a good idea to check the latest
information on the service's website to ensure that it is still available and meets your needs.
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item value="faq2">
<Accordion.Control>
<Icon type="messageSquare" />
Is the Yorkie production ready?
</Accordion.Control>
<Accordion.Panel>
Yes, Yorkie is ready to use in production. <br />
<br />
Yorkie has achieved production-ready status and is currently operating as a stable and reliable
service. Its robustness has been thoroughly validated through extensive testing at NAVER, establishing
it as a dependable solution for production environments. But it is not a guarantee that there will be
no issues or bugs when using the service. If you encounter any problems while using Yorkie, please
report them to the Yorkie community so that they can be addressed as quickly as possible.
</Accordion.Panel>
</Accordion.Item>
<Accordion.Item value="faq3">
<Accordion.Control>
<Icon type="messageSquare" />
How can I contribute to the Yorkie project?
</Accordion.Control>
<Accordion.Panel>
Yorkie is an open source project, so there are many ways to contribute to its development. <br />
<br />
One way to contribute is by reporting any bugs you encounter while using the service. You can also
submit pull requests with improvements or new features that you have developed. If you plan to use
Yorkie in your company, you can also consider donating to the Yorkie community to support its
continued development. You can learn more about how to contribute to the Yorkie project on its website
or by visiting our{' '}
<u>
<a href="https://discord.com/invite/MVEAwz9sBy">Discord</a>
</u>
.
</Accordion.Panel>
</Accordion.Item>
</Accordion>
</div>
<Button.Box>
<Button
as="a"
href="https://discord.gg/MVEAwz9sBy"
outline
icon={<Icon type="smile" />}
target="_blank"
rel="noreferrer"
>
Contact
</Button>
<Button
as="a"
href={`${process.env.NEXT_PUBLIC_DASHBOARD_PATH}`}
className="orange_0 btn_start"
icon={<Icon type="twinkle" />}
>
Start for free
</Button>
</Button.Box>
</section>
</div>
</Layout>
);
};
export default Home;