create-swift-rust 0.4.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +74 -938
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
- package/templates/default/README.md +29 -0
- package/templates/default/_env.example +5 -0
- package/templates/default/_env.local +5 -0
- package/templates/default/_gitignore +14 -0
- package/templates/default/biome.json +12 -0
- package/templates/default/globals.d.ts +19 -0
- package/templates/default/package.json +30 -0
- package/templates/default/postcss.config.mjs +7 -0
- package/templates/default/public/blog/introducing-swift-rust.svg +12 -0
- package/templates/default/public/og-image.svg +25 -0
- package/templates/default/public/samples/axelborg-towers-modern-architecture.jpg +0 -0
- package/templates/default/public/samples/brown-high-skyscrapers.jpg +0 -0
- package/templates/default/public/samples/close-up-portrait-gorgeous-young-woman.jpg +0 -0
- package/templates/default/public/samples/full-shot-woman-taking-selfie.jpg +0 -0
- package/templates/default/public/samples/happy-black-parents-with-kids-making-video-call-smart-phone-home.jpg +0 -0
- package/templates/default/public/samples/metaverse-concept-collage-design.jpg +0 -0
- package/templates/default/src/app/about/layout.tsx +5 -0
- package/templates/default/src/app/about/page.tsx +74 -0
- package/templates/default/src/app/about/team/page.tsx +88 -0
- package/templates/default/src/app/api/contact/route.ts +15 -0
- package/templates/default/src/app/api/health/route.ts +7 -0
- package/templates/default/src/app/api/posts/[id]/route.ts +33 -0
- package/templates/default/src/app/api/posts/route.ts +29 -0
- package/templates/default/src/app/api/search/route.ts +15 -0
- package/templates/default/src/app/api/stats/route.ts +16 -0
- package/templates/default/src/app/blog/[slug]/page.tsx +116 -0
- package/templates/default/src/app/blog/page.tsx +101 -0
- package/templates/default/src/app/blog/tag/[tag]/page.tsx +82 -0
- package/templates/default/src/app/contact/page.tsx +131 -0
- package/templates/default/src/app/dashboard/analytics/page.tsx +103 -0
- package/templates/default/src/app/dashboard/layout.tsx +11 -0
- package/templates/default/src/app/dashboard/loading.tsx +18 -0
- package/templates/default/src/app/dashboard/page.tsx +181 -0
- package/templates/default/src/app/dashboard/posts/[id]/not-found.tsx +23 -0
- package/templates/default/src/app/dashboard/posts/[id]/page.tsx +87 -0
- package/templates/default/src/app/dashboard/posts/new/page.tsx +103 -0
- package/templates/default/src/app/dashboard/posts/page.tsx +81 -0
- package/templates/default/src/app/dashboard/settings/page.tsx +119 -0
- package/templates/default/src/app/error.tsx +42 -0
- package/templates/default/src/app/favicon.ico +0 -0
- package/templates/default/src/app/favicon.svg +8 -0
- package/templates/default/src/app/fonts/page.tsx +610 -0
- package/templates/default/src/app/globals.css +238 -0
- package/templates/default/src/app/images/page.tsx +56 -0
- package/templates/default/src/app/layout.tsx +44 -0
- package/templates/default/src/app/loading.tsx +13 -0
- package/templates/default/src/app/not-found.tsx +25 -0
- package/templates/default/src/app/page.tsx +410 -0
- package/templates/default/src/app/videos/page.tsx +182 -0
- package/templates/default/src/components/font-studio.tsx +378 -0
- package/templates/default/src/components/footer.tsx +75 -0
- package/templates/default/src/components/logo.tsx +26 -0
- package/templates/default/src/components/nav.tsx +102 -0
- package/templates/default/src/components/sidebar.tsx +109 -0
- package/templates/default/src/lib/blur.ts +5 -0
- package/templates/default/src/lib/format.ts +31 -0
- package/templates/default/src/lib/posts.ts +132 -0
- package/templates/default/src/lib/site.config.ts +39 -0
- package/templates/default/src/lib/stats.ts +25 -0
- package/templates/default/swift-rust.config.json +8 -0
- package/templates/default/tsconfig.json +29 -0
- package/templates/default/vercel.json +23 -0
|
@@ -0,0 +1,610 @@
|
|
|
1
|
+
import { FontStudio } from "@/components/font-studio";
|
|
2
|
+
import type { Metadata } from "swift-rust";
|
|
3
|
+
import { localFontCss } from "swift-rust/font";
|
|
4
|
+
import {
|
|
5
|
+
DxSlight,
|
|
6
|
+
DxSlightExtBdUltraSlant,
|
|
7
|
+
DxSlightMediumUltra,
|
|
8
|
+
Lausanne,
|
|
9
|
+
VarentGrotesk,
|
|
10
|
+
VarentGroteskBold,
|
|
11
|
+
VarentGroteskExtLtIta,
|
|
12
|
+
Zimula,
|
|
13
|
+
} from "swift-rust/font";
|
|
14
|
+
import {
|
|
15
|
+
BebasNeue,
|
|
16
|
+
BricolageGrotesque,
|
|
17
|
+
Caveat,
|
|
18
|
+
Cinzel,
|
|
19
|
+
DmSans,
|
|
20
|
+
DmSerifDisplay,
|
|
21
|
+
Figtree,
|
|
22
|
+
FiraCode,
|
|
23
|
+
Geist,
|
|
24
|
+
GeistMono,
|
|
25
|
+
IbmPlexMono,
|
|
26
|
+
IbmPlexSans,
|
|
27
|
+
IbmPlexSerif,
|
|
28
|
+
Inter,
|
|
29
|
+
JetbrainsMono,
|
|
30
|
+
Lora,
|
|
31
|
+
Manrope,
|
|
32
|
+
Outfit,
|
|
33
|
+
PlayfairDisplay,
|
|
34
|
+
PlusJakartaSans,
|
|
35
|
+
Poppins,
|
|
36
|
+
Roboto,
|
|
37
|
+
Sora,
|
|
38
|
+
SourceCodePro,
|
|
39
|
+
SpaceGrotesk,
|
|
40
|
+
} from "swift-rust/font/google";
|
|
41
|
+
|
|
42
|
+
export const metadata: Metadata = { title: "Fonts" };
|
|
43
|
+
|
|
44
|
+
type Factory = (opts?: { variable?: boolean }) => {
|
|
45
|
+
className: string;
|
|
46
|
+
style: Record<string, string>;
|
|
47
|
+
variable?: string;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
type FeaturedFont = {
|
|
51
|
+
name: string;
|
|
52
|
+
importName: string;
|
|
53
|
+
factory: Factory;
|
|
54
|
+
category: "Sans" | "Serif" | "Mono" | "Display" | "Script";
|
|
55
|
+
blurb: string;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const FEATURED: FeaturedFont[] = [
|
|
59
|
+
{
|
|
60
|
+
name: "Geist",
|
|
61
|
+
importName: "Geist",
|
|
62
|
+
factory: Geist as Factory,
|
|
63
|
+
category: "Sans",
|
|
64
|
+
blurb: "Default UI sans, by Vercel",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: "Geist Mono",
|
|
68
|
+
importName: "GeistMono",
|
|
69
|
+
factory: GeistMono as Factory,
|
|
70
|
+
category: "Mono",
|
|
71
|
+
blurb: "Default monospace, by Vercel",
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: "Inter",
|
|
75
|
+
importName: "Inter",
|
|
76
|
+
factory: Inter as Factory,
|
|
77
|
+
category: "Sans",
|
|
78
|
+
blurb: "Designed for screens",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: "Roboto",
|
|
82
|
+
importName: "Roboto",
|
|
83
|
+
factory: Roboto as Factory,
|
|
84
|
+
category: "Sans",
|
|
85
|
+
blurb: "Modern, friendly, versatile",
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: "Poppins",
|
|
89
|
+
importName: "Poppins",
|
|
90
|
+
factory: Poppins as Factory,
|
|
91
|
+
category: "Sans",
|
|
92
|
+
blurb: "Geometric, warm heart",
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: "Manrope",
|
|
96
|
+
importName: "Manrope",
|
|
97
|
+
factory: Manrope as Factory,
|
|
98
|
+
category: "Sans",
|
|
99
|
+
blurb: "Clean for editorial",
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: "IBM Plex Sans",
|
|
103
|
+
importName: "IbmPlexSans",
|
|
104
|
+
factory: IbmPlexSans as Factory,
|
|
105
|
+
category: "Sans",
|
|
106
|
+
blurb: "Corporate with character",
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "Space Grotesk",
|
|
110
|
+
importName: "SpaceGrotesk",
|
|
111
|
+
factory: SpaceGrotesk as Factory,
|
|
112
|
+
category: "Sans",
|
|
113
|
+
blurb: "Quirky display",
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: "Plus Jakarta Sans",
|
|
117
|
+
importName: "PlusJakartaSans",
|
|
118
|
+
factory: PlusJakartaSans as Factory,
|
|
119
|
+
category: "Sans",
|
|
120
|
+
blurb: "Elegant, modern",
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: "Outfit",
|
|
124
|
+
importName: "Outfit",
|
|
125
|
+
factory: Outfit as Factory,
|
|
126
|
+
category: "Sans",
|
|
127
|
+
blurb: "Geometric branding",
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: "Figtree",
|
|
131
|
+
importName: "Figtree",
|
|
132
|
+
factory: Figtree as Factory,
|
|
133
|
+
category: "Sans",
|
|
134
|
+
blurb: "Friendly, approachable",
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: "Sora",
|
|
138
|
+
importName: "Sora",
|
|
139
|
+
factory: Sora as Factory,
|
|
140
|
+
category: "Sans",
|
|
141
|
+
blurb: "Made for UI",
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
name: "DM Sans",
|
|
145
|
+
importName: "DmSans",
|
|
146
|
+
factory: DmSans as Factory,
|
|
147
|
+
category: "Sans",
|
|
148
|
+
blurb: "Low-contrast geometric",
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: "Playfair Display",
|
|
152
|
+
importName: "PlayfairDisplay",
|
|
153
|
+
factory: PlayfairDisplay as Factory,
|
|
154
|
+
category: "Serif",
|
|
155
|
+
blurb: "Editorial elegance",
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: "Lora",
|
|
159
|
+
importName: "Lora",
|
|
160
|
+
factory: Lora as Factory,
|
|
161
|
+
category: "Serif",
|
|
162
|
+
blurb: "Balanced for the screen",
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
name: "DM Serif Display",
|
|
166
|
+
importName: "DmSerifDisplay",
|
|
167
|
+
factory: DmSerifDisplay as Factory,
|
|
168
|
+
category: "Serif",
|
|
169
|
+
blurb: "Editorial display",
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: "IBM Plex Serif",
|
|
173
|
+
importName: "IbmPlexSerif",
|
|
174
|
+
factory: IbmPlexSerif as Factory,
|
|
175
|
+
category: "Serif",
|
|
176
|
+
blurb: "Corporate serif",
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
name: "JetBrains Mono",
|
|
180
|
+
importName: "JetbrainsMono",
|
|
181
|
+
factory: JetbrainsMono as Factory,
|
|
182
|
+
category: "Mono",
|
|
183
|
+
blurb: "Code editor default",
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
name: "Fira Code",
|
|
187
|
+
importName: "FiraCode",
|
|
188
|
+
factory: FiraCode as Factory,
|
|
189
|
+
category: "Mono",
|
|
190
|
+
blurb: "Monospace ligatures",
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
name: "Source Code Pro",
|
|
194
|
+
importName: "SourceCodePro",
|
|
195
|
+
factory: SourceCodePro as Factory,
|
|
196
|
+
category: "Mono",
|
|
197
|
+
blurb: "Adobe monospace",
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
name: "IBM Plex Mono",
|
|
201
|
+
importName: "IbmPlexMono",
|
|
202
|
+
factory: IbmPlexMono as Factory,
|
|
203
|
+
category: "Mono",
|
|
204
|
+
blurb: "Corporate mono",
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
name: "Bricolage Grotesque",
|
|
208
|
+
importName: "BricolageGrotesque",
|
|
209
|
+
factory: BricolageGrotesque as Factory,
|
|
210
|
+
category: "Display",
|
|
211
|
+
blurb: "Bold contemporary",
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
name: "Bebas Neue",
|
|
215
|
+
importName: "BebasNeue",
|
|
216
|
+
factory: BebasNeue as Factory,
|
|
217
|
+
category: "Display",
|
|
218
|
+
blurb: "All-caps display",
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
name: "Cinzel",
|
|
222
|
+
importName: "Cinzel",
|
|
223
|
+
factory: Cinzel as Factory,
|
|
224
|
+
category: "Display",
|
|
225
|
+
blurb: "Roman capitals",
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: "Caveat",
|
|
229
|
+
importName: "Caveat",
|
|
230
|
+
factory: Caveat as Factory,
|
|
231
|
+
category: "Script",
|
|
232
|
+
blurb: "Casual handwriting",
|
|
233
|
+
},
|
|
234
|
+
];
|
|
235
|
+
|
|
236
|
+
type LocalFont = {
|
|
237
|
+
name: string;
|
|
238
|
+
factory: Factory;
|
|
239
|
+
importName: string;
|
|
240
|
+
weights: string;
|
|
241
|
+
blurb: string;
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
const LOCAL: LocalFont[] = [
|
|
245
|
+
{
|
|
246
|
+
name: "Lausanne",
|
|
247
|
+
factory: Lausanne as Factory,
|
|
248
|
+
importName: "Lausanne",
|
|
249
|
+
weights: "400",
|
|
250
|
+
blurb: "A precise editorial display",
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: "DxSlight",
|
|
254
|
+
factory: DxSlight as Factory,
|
|
255
|
+
importName: "DxSlight",
|
|
256
|
+
weights: "500, 800 italic",
|
|
257
|
+
blurb: "Decorative medium + ultra",
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
name: "DxSlight Medium Ultra",
|
|
261
|
+
factory: DxSlightMediumUltra as Factory,
|
|
262
|
+
importName: "DxSlightMediumUltra",
|
|
263
|
+
weights: "500",
|
|
264
|
+
blurb: "Decorative medium",
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
name: "DxSlight ExtBd UltraSlant",
|
|
268
|
+
factory: DxSlightExtBdUltraSlant as Factory,
|
|
269
|
+
importName: "DxSlightExtBdUltraSlant",
|
|
270
|
+
weights: "800 italic",
|
|
271
|
+
blurb: "Heavy display slant",
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
name: "Varent Grotesk",
|
|
275
|
+
factory: VarentGrotesk as Factory,
|
|
276
|
+
importName: "VarentGrotesk",
|
|
277
|
+
weights: "700, 200 italic",
|
|
278
|
+
blurb: "Modern grotesk",
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
name: "Varent Grotesk Bold",
|
|
282
|
+
factory: VarentGroteskBold as Factory,
|
|
283
|
+
importName: "VarentGroteskBold",
|
|
284
|
+
weights: "700",
|
|
285
|
+
blurb: "Bold variant",
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
name: "Varent Grotesk ExtLtIta",
|
|
289
|
+
factory: VarentGroteskExtLtIta as Factory,
|
|
290
|
+
importName: "VarentGroteskExtLtIta",
|
|
291
|
+
weights: "200 italic",
|
|
292
|
+
blurb: "Extra-light italic",
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
name: "Zimula",
|
|
296
|
+
factory: Zimula as Factory,
|
|
297
|
+
importName: "Zimula",
|
|
298
|
+
weights: "100-900 + ink trap + ink spot",
|
|
299
|
+
blurb: "Full weight ladder",
|
|
300
|
+
},
|
|
301
|
+
];
|
|
302
|
+
|
|
303
|
+
const ZIMULA_WEIGHTS: ReadonlyArray<{
|
|
304
|
+
weight: number;
|
|
305
|
+
style: "normal" | "ink-trap" | "ink-spot";
|
|
306
|
+
label: string;
|
|
307
|
+
}> = [
|
|
308
|
+
{ weight: 100, style: "normal", label: "Thin" },
|
|
309
|
+
{ weight: 200, style: "normal", label: "ExtraLight" },
|
|
310
|
+
{ weight: 300, style: "normal", label: "Light" },
|
|
311
|
+
{ weight: 400, style: "normal", label: "Regular" },
|
|
312
|
+
{ weight: 500, style: "normal", label: "Medium" },
|
|
313
|
+
{ weight: 600, style: "normal", label: "SemiBold" },
|
|
314
|
+
{ weight: 700, style: "normal", label: "Bold" },
|
|
315
|
+
{ weight: 800, style: "normal", label: "ExtraBold" },
|
|
316
|
+
{ weight: 900, style: "normal", label: "Black" },
|
|
317
|
+
];
|
|
318
|
+
|
|
319
|
+
function ZIMULA_FAMILY(style: "normal" | "ink-trap" | "ink-spot"): string {
|
|
320
|
+
if (style === "ink-trap") return "'ZimulaInkTrap'";
|
|
321
|
+
if (style === "ink-spot") return "'ZimulaInkSpot'";
|
|
322
|
+
return "'Zimula'";
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function ZimulaLadder() {
|
|
326
|
+
return (
|
|
327
|
+
<div className="space-y-2.5">
|
|
328
|
+
{ZIMULA_WEIGHTS.map((w) => (
|
|
329
|
+
<div key={`${w.weight}-${w.style}`} className="flex items-baseline gap-4">
|
|
330
|
+
<span className="w-20 shrink-0 font-mono text-xs text-[var(--color-fg-subtle)]">
|
|
331
|
+
{w.weight} {w.label}
|
|
332
|
+
</span>
|
|
333
|
+
<span
|
|
334
|
+
className="truncate text-[var(--color-fg)]"
|
|
335
|
+
style={{
|
|
336
|
+
fontFamily: ZIMULA_FAMILY(w.style),
|
|
337
|
+
fontWeight: w.weight,
|
|
338
|
+
fontSize: "1.75rem",
|
|
339
|
+
lineHeight: 1.2,
|
|
340
|
+
}}
|
|
341
|
+
>
|
|
342
|
+
The quick brown fox jumps
|
|
343
|
+
</span>
|
|
344
|
+
</div>
|
|
345
|
+
))}
|
|
346
|
+
</div>
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const FEATURED_GROUPS: ReadonlyArray<{ name: string; fonts: FeaturedFont[] }> = [
|
|
351
|
+
{ name: "Sans-serif", fonts: FEATURED.filter((f) => f.category === "Sans") },
|
|
352
|
+
{ name: "Serif", fonts: FEATURED.filter((f) => f.category === "Serif") },
|
|
353
|
+
{ name: "Monospace", fonts: FEATURED.filter((f) => f.category === "Mono") },
|
|
354
|
+
{
|
|
355
|
+
name: "Display & script",
|
|
356
|
+
fonts: FEATURED.filter((f) => f.category === "Display" || f.category === "Script"),
|
|
357
|
+
},
|
|
358
|
+
];
|
|
359
|
+
|
|
360
|
+
export default function FontsPage() {
|
|
361
|
+
const localCss = localFontCss();
|
|
362
|
+
|
|
363
|
+
return (
|
|
364
|
+
<div className="container-page py-16 sm:py-20">
|
|
365
|
+
<header className="mx-auto max-w-3xl text-center">
|
|
366
|
+
<div className="badge badge-accent mb-5 inline-flex">
|
|
367
|
+
<span className="pulse-dot h-1.5 w-1.5 rounded-full bg-current" />
|
|
368
|
+
Typography
|
|
369
|
+
</div>
|
|
370
|
+
<h1 className="text-balance text-5xl font-semibold tracking-tight text-[var(--color-fg)] sm:text-6xl">
|
|
371
|
+
Every font, every weight,
|
|
372
|
+
<br />
|
|
373
|
+
live in your browser.
|
|
374
|
+
</h1>
|
|
375
|
+
<p className="mx-auto mt-6 max-w-2xl text-pretty text-lg leading-relaxed text-[var(--color-fg-muted)]">
|
|
376
|
+
2,071 Google fonts and 8 local font families, all available as on-demand imports. Pick a
|
|
377
|
+
font, see it in action, and copy the import statement into your project.
|
|
378
|
+
</p>
|
|
379
|
+
<dl className="mt-10 grid grid-cols-2 gap-4 sm:grid-cols-4">
|
|
380
|
+
{[
|
|
381
|
+
{ v: "2,071", l: "Google fonts" },
|
|
382
|
+
{ v: "8", l: "Local families" },
|
|
383
|
+
{ v: "27+", l: "Zimula weights" },
|
|
384
|
+
{ v: "auto", l: "Subsetting" },
|
|
385
|
+
].map((s) => (
|
|
386
|
+
<div
|
|
387
|
+
key={s.l}
|
|
388
|
+
className="rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-4"
|
|
389
|
+
>
|
|
390
|
+
<dt className="font-mono text-2xl font-semibold text-[var(--color-fg)]">{s.v}</dt>
|
|
391
|
+
<dd className="mt-1 text-xs uppercase tracking-wider text-[var(--color-fg-subtle)]">
|
|
392
|
+
{s.l}
|
|
393
|
+
</dd>
|
|
394
|
+
</div>
|
|
395
|
+
))}
|
|
396
|
+
</dl>
|
|
397
|
+
</header>
|
|
398
|
+
|
|
399
|
+
<section className="mt-20">
|
|
400
|
+
<div className="mb-6 flex items-baseline justify-between">
|
|
401
|
+
<h2 className="text-2xl font-semibold tracking-tight text-[var(--color-fg)]">
|
|
402
|
+
Live preview
|
|
403
|
+
</h2>
|
|
404
|
+
<span className="text-sm text-[var(--color-fg-muted)]">
|
|
405
|
+
Type a name to load any of the 2,071 Google fonts.
|
|
406
|
+
</span>
|
|
407
|
+
</div>
|
|
408
|
+
<FontStudio />
|
|
409
|
+
</section>
|
|
410
|
+
|
|
411
|
+
<section className="mt-24">
|
|
412
|
+
<div className="mb-2 flex items-baseline justify-between">
|
|
413
|
+
<h2 className="text-2xl font-semibold tracking-tight text-[var(--color-fg)]">
|
|
414
|
+
Featured Google fonts
|
|
415
|
+
</h2>
|
|
416
|
+
<span className="text-sm text-[var(--color-fg-muted)]">
|
|
417
|
+
25 of 2,071 — every one ships the same way.
|
|
418
|
+
</span>
|
|
419
|
+
</div>
|
|
420
|
+
<p className="mb-8 max-w-2xl text-[var(--color-fg-muted)]">
|
|
421
|
+
These are the fonts most teams reach for. Use the search above to preview any of the
|
|
422
|
+
remaining 2,046.
|
|
423
|
+
</p>
|
|
424
|
+
{FEATURED_GROUPS.map((group) => (
|
|
425
|
+
<div key={group.name} className="mb-10">
|
|
426
|
+
<h3 className="mb-3 text-xs font-semibold uppercase tracking-wider text-[var(--color-fg-subtle)]">
|
|
427
|
+
{group.name}
|
|
428
|
+
</h3>
|
|
429
|
+
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
|
|
430
|
+
{group.fonts.map((f) => {
|
|
431
|
+
const font = f.factory();
|
|
432
|
+
return (
|
|
433
|
+
<div
|
|
434
|
+
key={f.name}
|
|
435
|
+
className="group flex flex-col gap-2 rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-5 transition-colors hover:border-[var(--color-border-strong)]"
|
|
436
|
+
style={font.style}
|
|
437
|
+
>
|
|
438
|
+
<div className="flex items-baseline justify-between gap-2">
|
|
439
|
+
<h4 className="text-sm font-medium text-[var(--color-fg)]">{f.name}</h4>
|
|
440
|
+
<span className="text-xs text-[var(--color-fg-subtle)]">{f.blurb}</span>
|
|
441
|
+
</div>
|
|
442
|
+
<div className="truncate text-2xl text-[var(--color-fg)]">Beautiful type</div>
|
|
443
|
+
<code
|
|
444
|
+
className="mt-auto truncate font-mono text-[11px] text-[var(--color-fg-muted)]"
|
|
445
|
+
style={{ fontFamily: "ui-monospace, monospace" }}
|
|
446
|
+
>
|
|
447
|
+
import {"{ "}
|
|
448
|
+
{f.importName}
|
|
449
|
+
{" }"} from "swift-rust/font/google"
|
|
450
|
+
</code>
|
|
451
|
+
</div>
|
|
452
|
+
);
|
|
453
|
+
})}
|
|
454
|
+
</div>
|
|
455
|
+
</div>
|
|
456
|
+
))}
|
|
457
|
+
</section>
|
|
458
|
+
|
|
459
|
+
<section className="mt-24">
|
|
460
|
+
<div className="mb-2 flex items-baseline justify-between">
|
|
461
|
+
<h2 className="text-2xl font-semibold tracking-tight text-[var(--color-fg)]">
|
|
462
|
+
Local fonts
|
|
463
|
+
</h2>
|
|
464
|
+
<span className="text-sm text-[var(--color-fg-muted)]">
|
|
465
|
+
8 families bundled in the framework.
|
|
466
|
+
</span>
|
|
467
|
+
</div>
|
|
468
|
+
<p className="mb-8 max-w-2xl text-[var(--color-fg-muted)]">
|
|
469
|
+
Bundled in <code className="font-mono text-xs">packages/font/src/local/</code> and served
|
|
470
|
+
from <code className="font-mono text-xs">/_swift-rust/fonts/</code>. Use them when you
|
|
471
|
+
need exact control over weights or want to avoid a network round-trip.
|
|
472
|
+
</p>
|
|
473
|
+
<style dangerouslySetInnerHTML={{ __html: localCss }} />
|
|
474
|
+
|
|
475
|
+
<div className="mb-6 grid grid-cols-1 gap-3 sm:grid-cols-2">
|
|
476
|
+
{LOCAL.filter((f) => f.name !== "Zimula").map((f) => {
|
|
477
|
+
const font = f.factory();
|
|
478
|
+
return (
|
|
479
|
+
<div
|
|
480
|
+
key={f.name}
|
|
481
|
+
className="flex flex-col gap-2 rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-6"
|
|
482
|
+
style={font.style}
|
|
483
|
+
>
|
|
484
|
+
<div className="flex items-baseline justify-between gap-2">
|
|
485
|
+
<h4 className="text-sm font-medium text-[var(--color-fg)]">{f.name}</h4>
|
|
486
|
+
<span
|
|
487
|
+
className="font-mono text-[11px] text-[var(--color-fg-subtle)]"
|
|
488
|
+
style={{ fontFamily: "ui-monospace, monospace" }}
|
|
489
|
+
>
|
|
490
|
+
{f.weights}
|
|
491
|
+
</span>
|
|
492
|
+
</div>
|
|
493
|
+
<div className="text-3xl text-[var(--color-fg)]">Aa Bb Cc 123</div>
|
|
494
|
+
<p className="text-xs text-[var(--color-fg-muted)]">{f.blurb}</p>
|
|
495
|
+
<code
|
|
496
|
+
className="mt-auto truncate font-mono text-[11px] text-[var(--color-fg-muted)]"
|
|
497
|
+
style={{ fontFamily: "ui-monospace, monospace" }}
|
|
498
|
+
>
|
|
499
|
+
import {"{ "}
|
|
500
|
+
{f.importName}
|
|
501
|
+
{" }"} from "swift-rust/font"
|
|
502
|
+
</code>
|
|
503
|
+
</div>
|
|
504
|
+
);
|
|
505
|
+
})}
|
|
506
|
+
</div>
|
|
507
|
+
|
|
508
|
+
<div className="rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)] p-6">
|
|
509
|
+
<div className="mb-4 flex items-baseline justify-between gap-2">
|
|
510
|
+
<div>
|
|
511
|
+
<h4 className="text-sm font-medium text-[var(--color-fg)]">Zimula</h4>
|
|
512
|
+
<p className="mt-0.5 text-xs text-[var(--color-fg-muted)]">
|
|
513
|
+
Full weight ladder 100–900 in three styles (normal, ink-trap, ink-spot)
|
|
514
|
+
</p>
|
|
515
|
+
</div>
|
|
516
|
+
<span className="font-mono text-[11px] text-[var(--color-fg-subtle)]">27 weights</span>
|
|
517
|
+
</div>
|
|
518
|
+
<ZimulaLadder />
|
|
519
|
+
<code className="mt-6 block truncate font-mono text-[11px] text-[var(--color-fg-muted)]">
|
|
520
|
+
import {"{ "}Zimula{" }"} from "swift-rust/font"
|
|
521
|
+
</code>
|
|
522
|
+
</div>
|
|
523
|
+
</section>
|
|
524
|
+
|
|
525
|
+
<section className="mt-24">
|
|
526
|
+
<h2 className="mb-2 text-2xl font-semibold tracking-tight text-[var(--color-fg)]">
|
|
527
|
+
How to use
|
|
528
|
+
</h2>
|
|
529
|
+
<p className="mb-8 max-w-2xl text-[var(--color-fg-muted)]">
|
|
530
|
+
Three patterns cover almost every case. Drop them into your{" "}
|
|
531
|
+
<code className="font-mono text-xs">app/layout.tsx</code> and you're shipping.
|
|
532
|
+
</p>
|
|
533
|
+
<div className="space-y-6">
|
|
534
|
+
<CodeBlock
|
|
535
|
+
filename="app/layout.tsx"
|
|
536
|
+
caption="Google fonts · one import, one variable, the whole tree gets it"
|
|
537
|
+
code={`import { Geist, GeistMono } from "swift-rust/font/google";
|
|
538
|
+
|
|
539
|
+
const geist = Geist({ subsets: ["latin"], display: "swap", variable: true });
|
|
540
|
+
const geistMono = GeistMono({ subsets: ["latin"], display: "swap", variable: true });
|
|
541
|
+
|
|
542
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
543
|
+
return (
|
|
544
|
+
<html className={\`\${geist.variable} \${geistMono.variable}\`}>
|
|
545
|
+
<body className={geist.className}>{children}</body>
|
|
546
|
+
</html>
|
|
547
|
+
);
|
|
548
|
+
}`}
|
|
549
|
+
/>
|
|
550
|
+
<CodeBlock
|
|
551
|
+
filename="app/fonts.ts"
|
|
552
|
+
caption="Local fonts · point at a file, get a CSS class back"
|
|
553
|
+
code={`import { localFont } from "swift-rust/font/local";
|
|
554
|
+
|
|
555
|
+
const heading = localFont({
|
|
556
|
+
src: "./fonts/Heading-Bold.woff2",
|
|
557
|
+
weight: "700",
|
|
558
|
+
display: "swap",
|
|
559
|
+
variable: true,
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
export { heading };`}
|
|
563
|
+
/>
|
|
564
|
+
<CodeBlock
|
|
565
|
+
filename="app/layout.tsx"
|
|
566
|
+
caption="Local font CSS · inject @font-face declarations from the framework"
|
|
567
|
+
code={`import { localFontCss, Lausanne } from "swift-rust/font";
|
|
568
|
+
import { Lausanne as LausanneFont } from "swift-rust/font";
|
|
569
|
+
|
|
570
|
+
const css = localFontCss();
|
|
571
|
+
const lausanne = Lausanne({ variable: true });
|
|
572
|
+
|
|
573
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
574
|
+
return (
|
|
575
|
+
<html className={lausanne.variable}>
|
|
576
|
+
<head>
|
|
577
|
+
<style dangerouslySetInnerHTML={{ __html: css }} />
|
|
578
|
+
</head>
|
|
579
|
+
<body>{children}</body>
|
|
580
|
+
</html>
|
|
581
|
+
);
|
|
582
|
+
}`}
|
|
583
|
+
/>
|
|
584
|
+
</div>
|
|
585
|
+
</section>
|
|
586
|
+
</div>
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
function CodeBlock({
|
|
591
|
+
filename,
|
|
592
|
+
caption,
|
|
593
|
+
code,
|
|
594
|
+
}: {
|
|
595
|
+
filename: string;
|
|
596
|
+
caption: string;
|
|
597
|
+
code: string;
|
|
598
|
+
}) {
|
|
599
|
+
return (
|
|
600
|
+
<div className="overflow-hidden rounded-lg border border-[var(--color-border)] bg-[var(--color-surface)]">
|
|
601
|
+
<div className="flex items-center justify-between border-b border-[var(--color-border)] bg-[var(--color-surface-2)] px-4 py-2.5">
|
|
602
|
+
<span className="font-mono text-xs text-[var(--color-fg-muted)]">{filename}</span>
|
|
603
|
+
<span className="text-xs text-[var(--color-fg-subtle)]">{caption}</span>
|
|
604
|
+
</div>
|
|
605
|
+
<pre className="overflow-x-auto bg-[var(--color-bg)] p-5 font-mono text-xs leading-relaxed text-[var(--color-fg)]">
|
|
606
|
+
<code>{code}</code>
|
|
607
|
+
</pre>
|
|
608
|
+
</div>
|
|
609
|
+
);
|
|
610
|
+
}
|