Skip to content

Commit db3dd6f

Browse files
authored
docs: add homepage get started section (#486)
1 parent c4116d9 commit db3dd6f

6 files changed

Lines changed: 304 additions & 10 deletions

File tree

website/theme/components/Commands.module.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
2020
align-items: center;
2121
gap: clamp(2rem, 4vw, 3rem);
22-
padding: 5.5rem 0;
22+
padding: 7.5rem 0;
2323
border-top: 1px solid var(--command-border);
2424
}
2525

@@ -42,7 +42,7 @@
4242
flex-wrap: wrap;
4343
align-items: center;
4444
gap: 0.5rem 0.75rem;
45-
margin: 0 0 1.25rem;
45+
margin: 0 0 0.5rem;
4646
color: var(--command-text);
4747
font-family: var(--rp-font-family-mono);
4848
font-size: 0.8125rem;
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
.getStarted {
2+
--cta-title: #111214;
3+
--cta-text: #727272;
4+
--cta-border: #e8e8e8;
5+
--cta-primary-text: #fff;
6+
--cta-hover: #f5f5f5;
7+
8+
max-width: 72rem;
9+
margin: 0 auto;
10+
padding: 0 2rem;
11+
}
12+
13+
:global(.dark) .getStarted {
14+
--cta-title: #f5f5f5;
15+
--cta-text: #9a9a9a;
16+
--cta-border: #292929;
17+
--cta-primary-text: #111214;
18+
--cta-hover: #202020;
19+
}
20+
21+
.inner {
22+
display: flex;
23+
flex-direction: column;
24+
align-items: center;
25+
padding: 7.5rem 0;
26+
text-align: center;
27+
border-block: 1px solid var(--cta-border);
28+
29+
h2 {
30+
margin: 0;
31+
color: var(--cta-title);
32+
font-size: clamp(1.75rem, 3vw, 2.5rem);
33+
font-weight: 600;
34+
line-height: 1.25;
35+
letter-spacing: -0.04em;
36+
text-wrap: balance;
37+
}
38+
}
39+
40+
.description {
41+
max-width: 40rem;
42+
margin: 0.75rem 0 2rem;
43+
color: var(--cta-text);
44+
font-size: 0.925rem;
45+
line-height: 1.75;
46+
text-wrap: balance;
47+
}
48+
49+
.controls {
50+
position: relative;
51+
max-width: 100%;
52+
}
53+
54+
.command {
55+
display: flex;
56+
align-items: center;
57+
gap: 0.75rem;
58+
width: 22.5rem;
59+
min-height: 2.875rem;
60+
max-width: 100%;
61+
padding: 0.375rem 0.5rem 0.375rem 1rem;
62+
color: var(--cta-title);
63+
border: 1px solid var(--cta-border);
64+
border-radius: 0.5rem;
65+
66+
code {
67+
min-width: 0;
68+
overflow-wrap: anywhere;
69+
text-align: left;
70+
font-family: var(--rp-font-family-mono);
71+
font-size: 0.875rem;
72+
line-height: 1.6;
73+
}
74+
}
75+
76+
.prompt {
77+
color: var(--cta-text);
78+
font-family: var(--rp-font-family-mono);
79+
}
80+
81+
.copyButton {
82+
display: inline-flex;
83+
flex: 0 0 auto;
84+
align-items: center;
85+
justify-content: center;
86+
width: 2rem;
87+
height: 2rem;
88+
margin-left: auto;
89+
color: var(--cta-text);
90+
background: transparent;
91+
border: 0;
92+
cursor: pointer;
93+
border-radius: 0.375rem;
94+
95+
&:hover {
96+
color: var(--cta-title);
97+
background: var(--cta-hover);
98+
}
99+
}
100+
101+
.status {
102+
position: absolute;
103+
top: 100%;
104+
width: 100%;
105+
margin: 0.375rem 0 0;
106+
color: var(--cta-text);
107+
font-size: 0.8125rem;
108+
line-height: 1.25rem;
109+
}
110+
111+
.actions {
112+
display: flex;
113+
align-items: center;
114+
justify-content: center;
115+
gap: 0.75rem;
116+
117+
a {
118+
display: inline-flex;
119+
align-items: center;
120+
justify-content: center;
121+
gap: 0.625rem;
122+
min-width: 8rem;
123+
min-height: 2.875rem;
124+
padding: 0.5rem 1rem;
125+
font-size: 0.875rem;
126+
font-weight: 500;
127+
line-height: 1.25;
128+
text-decoration: none;
129+
border: 1px solid var(--cta-border);
130+
border-radius: 0.5rem;
131+
}
132+
}
133+
134+
.primary {
135+
color: var(--cta-primary-text);
136+
background: var(--cta-title);
137+
138+
&:hover {
139+
color: var(--cta-primary-text);
140+
opacity: 0.85;
141+
}
142+
}
143+
144+
.copyButton:focus-visible,
145+
.actions a:focus-visible {
146+
outline: 2px solid var(--rp-c-brand);
147+
outline-offset: 3px;
148+
}
149+
150+
@media (max-width: 640px) {
151+
.getStarted {
152+
padding-inline: 1.25rem;
153+
}
154+
155+
.inner {
156+
padding-block: 2.75rem;
157+
}
158+
159+
.description {
160+
font-size: 0.875rem;
161+
margin-bottom: 1.5rem;
162+
}
163+
164+
.actions {
165+
flex-direction: column;
166+
167+
a {
168+
width: 100%;
169+
}
170+
}
171+
172+
.command {
173+
gap: 0.5rem;
174+
padding-left: 0.875rem;
175+
176+
code {
177+
font-size: 0.8125rem;
178+
}
179+
}
180+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import { useLang } from '@rspress/core/runtime';
2+
import { Link } from '@rspress/core/theme-original';
3+
import { useEffect, useState } from 'react';
4+
import { useI18nUrl } from './utils';
5+
import styles from './GetStarted.module.scss';
6+
7+
const command = 'pnpm create rstack@latest';
8+
9+
export function GetStarted() {
10+
const isZh = useLang() === 'zh';
11+
const tUrl = useI18nUrl();
12+
const [copyStatus, setCopyStatus] = useState<'idle' | 'copied' | 'error'>(
13+
'idle',
14+
);
15+
16+
useEffect(() => {
17+
if (copyStatus === 'idle') return;
18+
const timeout = setTimeout(() => setCopyStatus('idle'), 2500);
19+
return () => clearTimeout(timeout);
20+
}, [copyStatus]);
21+
22+
async function copyCommand() {
23+
try {
24+
await navigator.clipboard.writeText(command);
25+
setCopyStatus('copied');
26+
} catch {
27+
setCopyStatus('error');
28+
}
29+
}
30+
31+
return (
32+
<section className={styles.getStarted} aria-labelledby="get-started-title">
33+
<div className={styles.inner}>
34+
<h2 id="get-started-title">
35+
{isZh
36+
? '用 Rstack CLI 开启下一个项目'
37+
: 'Build your next project with Rstack CLI'}
38+
</h2>
39+
<p className={styles.description}>
40+
{isZh
41+
? '让工具步调一致,将时间留给你想创造的事物'
42+
: 'Keep your tools in sync and make time for what you want to create.'}
43+
</p>
44+
<div className={styles.controls}>
45+
<div className={styles.actions}>
46+
<div className={styles.command}>
47+
<span className={styles.prompt} aria-hidden="true">
48+
$
49+
</span>
50+
<code>{command}</code>
51+
<button
52+
type="button"
53+
className={styles.copyButton}
54+
onClick={() => {
55+
void copyCommand();
56+
}}
57+
aria-label={isZh ? '复制创建命令' : 'Copy create command'}
58+
title={isZh ? '复制命令' : 'Copy command'}
59+
>
60+
<svg
61+
width="18"
62+
height="18"
63+
viewBox="0 0 24 24"
64+
fill="none"
65+
stroke="currentColor"
66+
strokeWidth="1.7"
67+
strokeLinecap="round"
68+
strokeLinejoin="round"
69+
aria-hidden="true"
70+
>
71+
{copyStatus === 'copied' ? (
72+
<path d="m5 12 4 4L19 6" />
73+
) : (
74+
<>
75+
<rect x="8" y="8" width="12" height="13" rx="2" />
76+
<path d="M16 4V3H4v13h1" />
77+
</>
78+
)}
79+
</svg>
80+
</button>
81+
</div>
82+
<Link className={styles.primary} href={tUrl('/guide/quick-start')}>
83+
{isZh ? '开始使用' : 'Get started'}
84+
<svg
85+
width="16"
86+
height="16"
87+
viewBox="0 0 24 24"
88+
fill="none"
89+
stroke="currentColor"
90+
strokeWidth="1.8"
91+
strokeLinecap="round"
92+
strokeLinejoin="round"
93+
aria-hidden="true"
94+
>
95+
<path d="M5 12h14m-6-6 6 6-6 6" />
96+
</svg>
97+
</Link>
98+
</div>
99+
<p className={styles.status} role="status" aria-live="polite">
100+
{copyStatus === 'copied'
101+
? isZh
102+
? '命令已复制'
103+
: 'Command copied'
104+
: copyStatus === 'error'
105+
? isZh
106+
? '复制失败,请手动复制命令'
107+
: 'Could not copy. Please copy the command manually.'
108+
: ''}
109+
</p>
110+
</div>
111+
</div>
112+
</section>
113+
);
114+
}

website/theme/components/HomeFooter.module.scss

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
display: none;
33
flex-direction: column;
44
align-items: center;
5-
margin-top: 6rem;
6-
border-top: 1px solid var(--rp-c-divider-light);
75

86
@media (min-width: 640px) {
97
display: flex;

website/theme/components/HomeFooter.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,22 +91,22 @@ function useFooterData() {
9191
title: 'GitHub',
9292
link: 'https://github.com/rstackjs/rstack-cli',
9393
},
94-
{
95-
title: 'npm',
96-
link: 'https://www.npmjs.com/package/rstack',
97-
},
9894
{
9995
title: 'Discord',
10096
link: 'https://discord.gg/XsaKEEk4mW',
10197
},
10298
{
103-
title: 'X',
104-
link: 'https://x.com/rspack_dev',
99+
title: 'Reddit',
100+
link: 'https://www.reddit.com/r/Rspack/',
105101
},
106102
{
107103
title: 'Bluesky',
108104
link: 'https://bsky.app/profile/rspack.dev',
109105
},
106+
{
107+
title: 'X',
108+
link: 'https://x.com/rspack_dev',
109+
},
110110
],
111111
},
112112
];

website/theme/pages/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Commands } from '../components/Commands';
22
import { CopyRight } from '../components/Copyright';
3+
import { GetStarted } from '../components/GetStarted';
34
import { Hero } from '../components/Hero';
45
import { HomeFooter } from '../components/HomeFooter';
56

@@ -8,6 +9,7 @@ export function HomeLayout() {
89
<>
910
<Hero />
1011
<Commands />
12+
<GetStarted />
1113
<HomeFooter />
1214
<CopyRight />
1315
</>

0 commit comments

Comments
 (0)