vite-plugin-capsize-radix 0.1.4 → 0.2.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/README.md CHANGED
@@ -56,6 +56,31 @@ export default defineConfig({
56
56
  })
57
57
  ```
58
58
 
59
+ ### Install Fonts via Fontsource
60
+
61
+ For open source fonts, use [@fontsource](https://fontsource.org/):
62
+
63
+ ```bash
64
+ pnpm add @fontsource/merriweather @fontsource/merriweather-sans @fontsource/source-code-pro
65
+ ```
66
+
67
+ ### Import CSS in Correct Order
68
+
69
+ In your entry file (e.g., `main.tsx`), the import order matters:
70
+
71
+ ```typescript
72
+ // 1. Radix base styles FIRST
73
+ import "@radix-ui/themes/styles.css"
74
+
75
+ // 2. Your font CSS from Fontsource
76
+ import "@fontsource/merriweather/latin.css"
77
+
78
+ // 3. Generated typography CSS LAST (overrides Radix variables)
79
+ import "/merriweather.css"
80
+ ```
81
+
82
+ **Critical**: The generated typography CSS must come AFTER `@radix-ui/themes/styles.css` to properly override the CSS variables.
83
+
59
84
  ### Using with Radix UI
60
85
 
61
86
  This plugin overrides all typography related CSS for Radix so you can simply
@@ -72,8 +97,25 @@ They all share a `size` prop from "1" to "10". This corresponds to the optional
72
97
  the array, etc. `<Text>` defaults to `size="2"` and `<Heading>` defaults to
73
98
  `size="6"`.
74
99
 
75
- As Capsize trims _all_ space around text, you'll find that `<Flex gap="[space]">` becomes
76
- your best friend for controlling spacing between elements e.g.
100
+ ### Spacing with Capsize
101
+
102
+ Because Capsize trims the invisible whitespace above and below text, **adjacent text elements will sit directly against each other** without any natural spacing. This is by design—it gives you precise control over layout.
103
+
104
+ You must explicitly add spacing between text elements using `<Flex gap>`:
105
+
106
+ ```tsx
107
+ // Without gap - heading and text will touch
108
+ <Flex direction="column">
109
+ <Heading>Title</Heading>
110
+ <Text>Body text...</Text>
111
+ </Flex>
112
+
113
+ // With gap - natural spacing between elements
114
+ <Flex direction="column" gap="2">
115
+ <Heading>Title</Heading>
116
+ <Text>Body text...</Text>
117
+ </Flex>
118
+ ```
77
119
 
78
120
  <img width="669" alt="Screenshot 2024-03-28 at 10 44 10 AM" src="https://github.com/KyleAMathews/vite-plugin-capsize-radix-ui/assets/71047/b8552d58-4e2d-42d6-9b7b-a595466c2725">
79
121
 
package/SKILL.md ADDED
@@ -0,0 +1,952 @@
1
+ ---
2
+ name: radix-typography
3
+ description: Set up pixel-perfect typography for Radix UI using vite-plugin-capsize-radix. Helps configure fonts, choose pairings, and integrate with your project.
4
+ ---
5
+
6
+ # Radix Typography with Capsize
7
+
8
+ This skill helps you set up bulletproof typography for Radix UI applications using `vite-plugin-capsize-radix`. It generates CSS that trims the invisible whitespace above and below text (caused by font metrics), enabling pixel-perfect alignment.
9
+
10
+ ## What This Plugin Does
11
+
12
+ Traditional CSS font rendering includes invisible space above and below text based on the font's ascender/descender metrics. This makes precise layouts difficult. Capsize calculates these metrics and applies CSS pseudo-elements to trim the excess, so your text sits exactly where you specify.
13
+
14
+ This plugin:
15
+ - Generates CSS that overrides Radix UI's typography variables
16
+ - Creates font stacks with metric-aware fallbacks
17
+ - Supports separate fonts for body text, headings, and code
18
+ - Handles responsive sizing (mobile vs desktop)
19
+
20
+ ## Important: Spacing with Capsize
21
+
22
+ Because Capsize trims the invisible whitespace above and below text, **adjacent text elements will sit directly against each other** without any natural spacing. This is by design - it gives you precise control over layout.
23
+
24
+ You must explicitly add spacing between text elements using:
25
+ - **Flex with gap** (recommended): `<Flex direction="column" gap="2">`
26
+ - **margin/padding**: Apply to individual elements
27
+ - **Radix spacing props**: `mt`, `mb`, `my`, etc.
28
+
29
+ ```tsx
30
+ // Without gap - heading and text will touch
31
+ <Flex direction="column">
32
+ <Heading>Recipes</Heading>
33
+ <Text>Define your chocolate recipes...</Text>
34
+ </Flex>
35
+
36
+ // With gap - natural spacing between elements
37
+ <Flex direction="column" gap="2">
38
+ <Heading>Recipes</Heading>
39
+ <Text>Define your chocolate recipes...</Text>
40
+ </Flex>
41
+ ```
42
+
43
+ This explicit spacing model is more predictable than relying on font metrics and gives you pixel-perfect control over your layouts.
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ pnpm add vite-plugin-capsize-radix @capsizecss/metrics
49
+ ```
50
+
51
+ ## Quick Start
52
+
53
+ ### 1. Configure the Plugin
54
+
55
+ In `vite.config.ts`:
56
+
57
+ ```typescript
58
+ import { defineConfig } from "vite"
59
+ import react from "@vitejs/plugin-react"
60
+ import { capsizeRadixPlugin } from "vite-plugin-capsize-radix"
61
+
62
+ // Import metrics for your chosen fonts
63
+ import inter from "@capsizecss/metrics/inter"
64
+ import arial from "@capsizecss/metrics/arial"
65
+
66
+ export default defineConfig({
67
+ plugins: [
68
+ react(),
69
+ capsizeRadixPlugin({
70
+ outputPath: `./public/typography.css`,
71
+ defaultFontStack: [inter, arial],
72
+ }),
73
+ ],
74
+ })
75
+ ```
76
+
77
+ ### 2. Install Fonts via Fontsource
78
+
79
+ For open source fonts, use [@fontsource](https://fontsource.org/):
80
+
81
+ ```bash
82
+ pnpm add @fontsource/inter
83
+ ```
84
+
85
+ ### 3. Import CSS in Correct Order
86
+
87
+ In your entry file (e.g., `main.tsx`), the import order matters:
88
+
89
+ ```typescript
90
+ // 1. Radix base styles FIRST
91
+ import "@radix-ui/themes/styles.css"
92
+
93
+ // 2. Your font CSS from Fontsource
94
+ import "@fontsource/inter/latin.css"
95
+
96
+ // 3. Generated typography CSS LAST (overrides Radix variables)
97
+ import "/typography.css"
98
+
99
+ // 4. Your app styles
100
+ import "./App.css"
101
+ ```
102
+
103
+ **Critical**: The generated typography CSS must come AFTER `@radix-ui/themes/styles.css` to properly override the CSS variables.
104
+
105
+ ## Using Fontsource Fonts
106
+
107
+ Fontsource provides npm packages for Google Fonts and other open source fonts. Each package includes the font files and CSS.
108
+
109
+ ### Installation Pattern
110
+
111
+ ```bash
112
+ # Install the font package
113
+ pnpm add @fontsource/[font-name]
114
+
115
+ # Install the metrics (usually same name, check @capsizecss/metrics)
116
+ # Metrics are included in @capsizecss/metrics
117
+ ```
118
+
119
+ ### Import Patterns
120
+
121
+ ```typescript
122
+ // Full font (all weights, styles, subsets)
123
+ import "@fontsource/inter"
124
+
125
+ // Specific subset (recommended for performance)
126
+ import "@fontsource/inter/latin.css"
127
+
128
+ // Specific weight
129
+ import "@fontsource/inter/400.css"
130
+ import "@fontsource/inter/700.css"
131
+
132
+ // Variable font (if available)
133
+ import "@fontsource-variable/inter"
134
+ ```
135
+
136
+ ### Common Fontsource Packages
137
+
138
+ | Font | Package | Metrics Import |
139
+ |------|---------|----------------|
140
+ | Albert Sans | `@fontsource/albert-sans` | `@capsizecss/metrics/albertSans` |
141
+ | Alegreya | `@fontsource/alegreya` | `@capsizecss/metrics/alegreya` |
142
+ | Alegreya Sans | `@fontsource/alegreya-sans` | `@capsizecss/metrics/alegreyaSans` |
143
+ | Archivo | `@fontsource/archivo` | `@capsizecss/metrics/archivo` |
144
+ | Arvo | `@fontsource/arvo` | `@capsizecss/metrics/arvo` |
145
+ | Atkinson Hyperlegible | `@fontsource/atkinson-hyperlegible` | `@capsizecss/metrics/atkinsonHyperlegible` |
146
+ | Be Vietnam Pro | `@fontsource/be-vietnam-pro` | `@capsizecss/metrics/beVietnamPro` |
147
+ | Bodoni Moda | `@fontsource/bodoni-moda` | `@capsizecss/metrics/bodoniModa` |
148
+ | Bricolage Grotesque | `@fontsource/bricolage-grotesque` | `@capsizecss/metrics/bricolageGrotesque` |
149
+ | Cabin | `@fontsource/cabin` | `@capsizecss/metrics/cabin` |
150
+ | Cabin Condensed | `@fontsource/cabin-condensed` | `@capsizecss/metrics/cabinCondensed` |
151
+ | Commissioner | `@fontsource/commissioner` | `@capsizecss/metrics/commissioner` |
152
+ | Crimson Text | `@fontsource/crimson-text` | `@capsizecss/metrics/crimsonText` |
153
+ | DM Sans | `@fontsource/dm-sans` | `@capsizecss/metrics/dmSans` |
154
+ | DM Serif Display | `@fontsource/dm-serif-display` | `@capsizecss/metrics/dmSerifDisplay` |
155
+ | DM Serif Text | `@fontsource/dm-serif-text` | `@capsizecss/metrics/dmSerifText` |
156
+ | Domine | `@fontsource/domine` | `@capsizecss/metrics/domine` |
157
+ | Epilogue | `@fontsource/epilogue` | `@capsizecss/metrics/epilogue` |
158
+ | Exo | `@fontsource/exo` | `@capsizecss/metrics/exo` |
159
+ | Figtree | `@fontsource/figtree` | `@capsizecss/metrics/figtree` |
160
+ | Fira Sans | `@fontsource/fira-sans` | `@capsizecss/metrics/firaSans` |
161
+ | Fraunces | `@fontsource/fraunces` | `@capsizecss/metrics/fraunces` |
162
+ | Geist | `@fontsource/geist-sans` | `@capsizecss/metrics/geist` |
163
+ | Instrument Sans | `@fontsource/instrument-sans` | `@capsizecss/metrics/instrumentSans` |
164
+ | Instrument Serif | `@fontsource/instrument-serif` | `@capsizecss/metrics/instrumentSerif` |
165
+ | Inter | `@fontsource/inter` | `@capsizecss/metrics/inter` |
166
+ | Josefin Sans | `@fontsource/josefin-sans` | `@capsizecss/metrics/josefinSans` |
167
+ | Lato | `@fontsource/lato` | `@capsizecss/metrics/lato` |
168
+ | Lexend | `@fontsource/lexend` | `@capsizecss/metrics/lexend` |
169
+ | Libre Baskerville | `@fontsource/libre-baskerville` | `@capsizecss/metrics/libreBaskerville` |
170
+ | Literata | `@fontsource/literata` | `@capsizecss/metrics/literata` |
171
+ | Lora | `@fontsource/lora` | `@capsizecss/metrics/lora` |
172
+ | Manrope | `@fontsource/manrope` | `@capsizecss/metrics/manrope` |
173
+ | Merriweather | `@fontsource/merriweather` | `@capsizecss/metrics/merriweather` |
174
+ | Merriweather Sans | `@fontsource/merriweather-sans` | `@capsizecss/metrics/merriweatherSans` |
175
+ | Montserrat | `@fontsource/montserrat` | `@capsizecss/metrics/montserrat` |
176
+ | Neuton | `@fontsource/neuton` | `@capsizecss/metrics/neuton` |
177
+ | Newsreader | `@fontsource/newsreader` | `@capsizecss/metrics/newsreader` |
178
+ | Open Sans | `@fontsource/open-sans` | `@capsizecss/metrics/openSans` |
179
+ | Oswald | `@fontsource/oswald` | `@capsizecss/metrics/oswald` |
180
+ | Outfit | `@fontsource/outfit` | `@capsizecss/metrics/outfit` |
181
+ | Patua One | `@fontsource/patua-one` | `@capsizecss/metrics/patuaOne` |
182
+ | Playfair Display | `@fontsource/playfair-display` | `@capsizecss/metrics/playfairDisplay` |
183
+ | Plus Jakarta Sans | `@fontsource/plus-jakarta-sans` | `@capsizecss/metrics/plusJakartaSans` |
184
+ | PT Sans | `@fontsource/pt-sans` | `@capsizecss/metrics/pTSans` |
185
+ | Quattrocento Sans | `@fontsource/quattrocento-sans` | `@capsizecss/metrics/quattrocentoSans` |
186
+ | Raleway | `@fontsource/raleway` | `@capsizecss/metrics/raleway` |
187
+ | Roboto | `@fontsource/roboto` | `@capsizecss/metrics/roboto` |
188
+ | Roboto Condensed | `@fontsource/roboto-condensed` | `@capsizecss/metrics/robotoCondensed` |
189
+ | Roboto Slab | `@fontsource/roboto-slab` | `@capsizecss/metrics/robotoSlab` |
190
+ | Rosario | `@fontsource/rosario` | `@capsizecss/metrics/rosario` |
191
+ | Sora | `@fontsource/sora` | `@capsizecss/metrics/sora` |
192
+ | Source Sans 3 | `@fontsource/source-sans-3` | `@capsizecss/metrics/sourceSans3` |
193
+ | Source Serif 4 | `@fontsource/source-serif-4` | `@capsizecss/metrics/sourceSerif4` |
194
+ | Space Grotesk | `@fontsource/space-grotesk` | `@capsizecss/metrics/spaceGrotesk` |
195
+ | Varela Round | `@fontsource/varela-round` | `@capsizecss/metrics/varelaRound` |
196
+ | Vollkorn | `@fontsource/vollkorn` | `@capsizecss/metrics/vollkorn` |
197
+ | Work Sans | `@fontsource/work-sans` | `@capsizecss/metrics/workSans` |
198
+ | Yrsa | `@fontsource/yrsa` | `@capsizecss/metrics/yrsa` |
199
+
200
+ ## Plugin Configuration Options
201
+
202
+ ```typescript
203
+ capsizeRadixPlugin({
204
+ // Required: where to write the generated CSS
205
+ outputPath: `./public/typography.css`,
206
+
207
+ // Body text font stack (first font = primary, rest = fallbacks)
208
+ defaultFontStack: [inter, arial],
209
+
210
+ // Heading font stack (defaults to defaultFontStack if not specified)
211
+ headingFontStack: [playfairDisplay, arial],
212
+
213
+ // Code/monospace font stack
214
+ codingFontStack: [sourceCodePro],
215
+
216
+ // Custom text sizes (fontSize = cap-height, lineHeight = total)
217
+ textStyles: [
218
+ { fontSize: 9, lineHeight: 19 }, // size 1
219
+ { fontSize: 11, lineHeight: 23 }, // size 2
220
+ { fontSize: 12, lineHeight: 25 }, // size 3 (mobile default)
221
+ { fontSize: 14, lineHeight: 28 }, // size 4 (desktop default)
222
+ { fontSize: 18, lineHeight: 30 }, // size 5
223
+ { fontSize: 24, lineHeight: 36 }, // size 6
224
+ { fontSize: 36, lineHeight: 44 }, // size 7
225
+ { fontSize: 48, lineHeight: 52 }, // size 8
226
+ { fontSize: 64, lineHeight: 64 }, // size 9
227
+ ],
228
+ })
229
+ ```
230
+
231
+ ## Font Pairing Recommendations
232
+
233
+ These pairings are drawn from [typography.js themes](https://github.com/KyleAMathews/typography.js), a collection of carefully designed typographic systems. Choose based on your app's personality.
234
+
235
+ ### Quick Reference Table
236
+
237
+ | Theme | Body | Heading | Vibe |
238
+ |-------|------|---------|------|
239
+ | Alton | Open Sans | Domine | Professional, authoritative |
240
+ | De Young | Alegreya | Alegreya Sans | Literary, sophisticated |
241
+ | Doelger | Cabin | Arvo | Friendly, sturdy |
242
+ | Elk Glen | PT Sans | Oswald | Bold, industrial |
243
+ | Fairy Gates | Quattrocento Sans | Work Sans | Warm, inviting |
244
+ | Funston | Cabin Condensed | Patua One | Playful, distinctive |
245
+ | Grand View | Arvo | Montserrat | Modern slab, geometric |
246
+ | Irving | Yrsa | Exo | Editorial, futuristic |
247
+ | Judah | Vollkorn | Roboto Condensed | Classic, efficient |
248
+ | Kirkham | Fira Sans | Playfair Display | Elegant contrast |
249
+ | Lawton | Libre Baskerville | Raleway | Traditional meets modern |
250
+ | Legible | Fira Sans | Merriweather | Highly readable |
251
+ | Lincoln | Lora | Varela Round | Bookish, friendly |
252
+ | Moraga | Source Sans Pro | Source Sans Pro | Clean, unified |
253
+ | Noriega | Lato | Lato | Simple, warm |
254
+ | Ocean Beach | Roboto | Roboto Slab | Technical, solid |
255
+ | Parnassus | Merriweather | Merriweather Sans | Literary, premium |
256
+ | St. Annes | Source Sans 3 | Source Serif 4 | Adobe superfamily |
257
+ | Stardust | Merriweather | Josefin Sans | Dreamy, vintage |
258
+ | Stern Grove | Georgia | Montserrat | Classic body, modern heads |
259
+ | Stow Lake | Lato | Neuton | Contemporary, refined |
260
+ | Sutro | Merriweather | Open Sans | Readable, friendly |
261
+ | Twin Peaks | Crimson Text | Rosario | Book typography |
262
+ | US Web Design | Source Sans 3 | Merriweather | Government standard |
263
+
264
+ ---
265
+
266
+ ### Clean & Modern (SaaS, Dashboards, Tools)
267
+
268
+ **Inter** - The gold standard for UI typography
269
+ ```typescript
270
+ import inter from "@capsizecss/metrics/inter"
271
+ import arial from "@capsizecss/metrics/arial"
272
+ capsizeRadixPlugin({
273
+ outputPath: `./public/typography.css`,
274
+ defaultFontStack: [inter, arial],
275
+ })
276
+ ```
277
+
278
+ **Lato** *(Noriega theme)* - Warm, humanist sans-serif
279
+ ```typescript
280
+ import lato from "@capsizecss/metrics/lato"
281
+ ```
282
+
283
+ **Roboto + Roboto Slab** *(Ocean Beach theme)* - Material Design inspired
284
+ ```typescript
285
+ import roboto from "@capsizecss/metrics/roboto"
286
+ import robotoSlab from "@capsizecss/metrics/robotoSlab"
287
+ capsizeRadixPlugin({
288
+ outputPath: `./public/typography.css`,
289
+ defaultFontStack: [roboto, arial],
290
+ headingFontStack: [robotoSlab, georgia],
291
+ })
292
+ ```
293
+
294
+ ---
295
+
296
+ ### Editorial & Content-Heavy (Blogs, Documentation)
297
+
298
+ **Source Serif 4 + Source Sans 3** *(St. Annes theme)* - Adobe's superfamily
299
+ ```typescript
300
+ import sourceSerif from "@capsizecss/metrics/sourceSerif4"
301
+ import sourceSans from "@capsizecss/metrics/sourceSans3"
302
+ capsizeRadixPlugin({
303
+ outputPath: `./public/typography.css`,
304
+ headingFontStack: [sourceSerif, georgia],
305
+ defaultFontStack: [sourceSans, arial],
306
+ })
307
+ ```
308
+
309
+ **Merriweather + Merriweather Sans** *(Parnassus theme)* - Screen-optimized serif
310
+ ```typescript
311
+ import merriweather from "@capsizecss/metrics/merriweather"
312
+ import merriweatherSans from "@capsizecss/metrics/merriweatherSans"
313
+ capsizeRadixPlugin({
314
+ outputPath: `./public/typography.css`,
315
+ defaultFontStack: [merriweather, georgia],
316
+ headingFontStack: [merriweatherSans, arial],
317
+ })
318
+ ```
319
+
320
+ **Merriweather + Open Sans** *(Sutro theme)* - Readable body, friendly headings
321
+ ```typescript
322
+ import merriweather from "@capsizecss/metrics/merriweather"
323
+ import openSans from "@capsizecss/metrics/openSans"
324
+ capsizeRadixPlugin({
325
+ outputPath: `./public/typography.css`,
326
+ defaultFontStack: [merriweather, georgia],
327
+ headingFontStack: [openSans, arial],
328
+ })
329
+ ```
330
+
331
+ **Source Sans 3 + Merriweather** *(US Web Design Standards)* - Government-grade clarity
332
+ ```typescript
333
+ import sourceSans from "@capsizecss/metrics/sourceSans3"
334
+ import merriweather from "@capsizecss/metrics/merriweather"
335
+ capsizeRadixPlugin({
336
+ outputPath: `./public/typography.css`,
337
+ defaultFontStack: [sourceSans, arial],
338
+ headingFontStack: [merriweather, georgia],
339
+ })
340
+ ```
341
+
342
+ **Fira Sans + Merriweather** *(Legible theme)* - Maximum readability
343
+ ```typescript
344
+ import firaSans from "@capsizecss/metrics/firaSans"
345
+ import merriweather from "@capsizecss/metrics/merriweather"
346
+ capsizeRadixPlugin({
347
+ outputPath: `./public/typography.css`,
348
+ defaultFontStack: [firaSans, arial],
349
+ headingFontStack: [merriweather, georgia],
350
+ })
351
+ ```
352
+
353
+ ---
354
+
355
+ ### Bold & Distinctive (Marketing, Landing Pages)
356
+
357
+ **Fira Sans + Playfair Display** *(Kirkham theme)* - Elegant contrast
358
+ ```typescript
359
+ import firaSans from "@capsizecss/metrics/firaSans"
360
+ import playfairDisplay from "@capsizecss/metrics/playfairDisplay"
361
+ capsizeRadixPlugin({
362
+ outputPath: `./public/typography.css`,
363
+ defaultFontStack: [firaSans, arial],
364
+ headingFontStack: [playfairDisplay, georgia],
365
+ })
366
+ ```
367
+
368
+ **Arvo + Montserrat** *(Grand View theme)* - Slab serif meets geometric
369
+ ```typescript
370
+ import arvo from "@capsizecss/metrics/arvo"
371
+ import montserrat from "@capsizecss/metrics/montserrat"
372
+ capsizeRadixPlugin({
373
+ outputPath: `./public/typography.css`,
374
+ defaultFontStack: [arvo, georgia],
375
+ headingFontStack: [montserrat, arial],
376
+ })
377
+ ```
378
+
379
+ **Libre Baskerville + Raleway** *(Lawton theme)* - Classic meets modern
380
+ ```typescript
381
+ import libreBaskerville from "@capsizecss/metrics/libreBaskerville"
382
+ import raleway from "@capsizecss/metrics/raleway"
383
+ capsizeRadixPlugin({
384
+ outputPath: `./public/typography.css`,
385
+ defaultFontStack: [libreBaskerville, georgia],
386
+ headingFontStack: [raleway, arial],
387
+ })
388
+ ```
389
+
390
+ **Open Sans + Domine** *(Alton theme)* - Professional authority
391
+ ```typescript
392
+ import openSans from "@capsizecss/metrics/openSans"
393
+ import domine from "@capsizecss/metrics/domine"
394
+ capsizeRadixPlugin({
395
+ outputPath: `./public/typography.css`,
396
+ defaultFontStack: [openSans, arial],
397
+ headingFontStack: [domine, georgia],
398
+ })
399
+ ```
400
+
401
+ ---
402
+
403
+ ### Literary & Sophisticated (Publishing, Portfolios)
404
+
405
+ **Alegreya + Alegreya Sans** *(De Young theme)* - Designed for literature
406
+ ```typescript
407
+ import alegreya from "@capsizecss/metrics/alegreya"
408
+ import alegreyaSans from "@capsizecss/metrics/alegreyaSans"
409
+ capsizeRadixPlugin({
410
+ outputPath: `./public/typography.css`,
411
+ defaultFontStack: [alegreya, georgia],
412
+ headingFontStack: [alegreyaSans, arial],
413
+ })
414
+ ```
415
+
416
+ **Crimson Text + Rosario** *(Twin Peaks theme)* - Classic book typography
417
+ ```typescript
418
+ import crimsonText from "@capsizecss/metrics/crimsonText"
419
+ import rosario from "@capsizecss/metrics/rosario"
420
+ capsizeRadixPlugin({
421
+ outputPath: `./public/typography.css`,
422
+ defaultFontStack: [crimsonText, georgia],
423
+ headingFontStack: [rosario, arial],
424
+ })
425
+ ```
426
+
427
+ **Vollkorn + Roboto Condensed** *(Judah theme)* - Old-style meets modern
428
+ ```typescript
429
+ import vollkorn from "@capsizecss/metrics/vollkorn"
430
+ import robotoCondensed from "@capsizecss/metrics/robotoCondensed"
431
+ capsizeRadixPlugin({
432
+ outputPath: `./public/typography.css`,
433
+ defaultFontStack: [vollkorn, georgia],
434
+ headingFontStack: [robotoCondensed, arial],
435
+ })
436
+ ```
437
+
438
+ **Lora + Varela Round** *(Lincoln theme)* - Bookish warmth
439
+ ```typescript
440
+ import lora from "@capsizecss/metrics/lora"
441
+ import varelaRound from "@capsizecss/metrics/varelaRound"
442
+ capsizeRadixPlugin({
443
+ outputPath: `./public/typography.css`,
444
+ defaultFontStack: [lora, georgia],
445
+ headingFontStack: [varelaRound, arial],
446
+ })
447
+ ```
448
+
449
+ **Merriweather + Josefin Sans** *(Stardust theme)* - Dreamy, vintage feel
450
+ ```typescript
451
+ import merriweather from "@capsizecss/metrics/merriweather"
452
+ import josefinSans from "@capsizecss/metrics/josefinSans"
453
+ capsizeRadixPlugin({
454
+ outputPath: `./public/typography.css`,
455
+ defaultFontStack: [merriweather, georgia],
456
+ headingFontStack: [josefinSans, arial],
457
+ })
458
+ ```
459
+
460
+ **Yrsa + Exo** *(Irving theme)* - Editorial meets sci-fi
461
+ ```typescript
462
+ import yrsa from "@capsizecss/metrics/yrsa"
463
+ import exo from "@capsizecss/metrics/exo"
464
+ capsizeRadixPlugin({
465
+ outputPath: `./public/typography.css`,
466
+ defaultFontStack: [yrsa, georgia],
467
+ headingFontStack: [exo, arial],
468
+ })
469
+ ```
470
+
471
+ ---
472
+
473
+ ### Technical & Industrial
474
+
475
+ **PT Sans + Oswald** *(Elk Glen theme)* - Bold, industrial feel
476
+ ```typescript
477
+ import pTSans from "@capsizecss/metrics/pTSans"
478
+ import oswald from "@capsizecss/metrics/oswald"
479
+ capsizeRadixPlugin({
480
+ outputPath: `./public/typography.css`,
481
+ defaultFontStack: [pTSans, arial],
482
+ headingFontStack: [oswald, arial],
483
+ })
484
+ ```
485
+
486
+ **Lato + Neuton** *(Stow Lake theme)* - Contemporary refinement
487
+ ```typescript
488
+ import lato from "@capsizecss/metrics/lato"
489
+ import neuton from "@capsizecss/metrics/neuton"
490
+ capsizeRadixPlugin({
491
+ outputPath: `./public/typography.css`,
492
+ defaultFontStack: [lato, arial],
493
+ headingFontStack: [neuton, georgia],
494
+ })
495
+ ```
496
+
497
+ ---
498
+
499
+ ### Approachable & Friendly (Consumer Apps)
500
+
501
+ **Quattrocento Sans + Work Sans** *(Fairy Gates theme)* - Warm and inviting
502
+ ```typescript
503
+ import quattrocentoSans from "@capsizecss/metrics/quattrocentoSans"
504
+ import workSans from "@capsizecss/metrics/workSans"
505
+ capsizeRadixPlugin({
506
+ outputPath: `./public/typography.css`,
507
+ defaultFontStack: [quattrocentoSans, arial],
508
+ headingFontStack: [workSans, arial],
509
+ })
510
+ ```
511
+
512
+ **Cabin + Arvo** *(Doelger theme)* - Friendly humanist with sturdy slab
513
+ ```typescript
514
+ import cabin from "@capsizecss/metrics/cabin"
515
+ import arvo from "@capsizecss/metrics/arvo"
516
+ capsizeRadixPlugin({
517
+ outputPath: `./public/typography.css`,
518
+ defaultFontStack: [cabin, arial],
519
+ headingFontStack: [arvo, georgia],
520
+ })
521
+ ```
522
+
523
+ **Cabin Condensed + Patua One** *(Funston theme)* - Playful, distinctive
524
+ ```typescript
525
+ import cabinCondensed from "@capsizecss/metrics/cabinCondensed"
526
+ import patuaOne from "@capsizecss/metrics/patuaOne"
527
+ capsizeRadixPlugin({
528
+ outputPath: `./public/typography.css`,
529
+ defaultFontStack: [cabinCondensed, arial],
530
+ headingFontStack: [patuaOne, georgia],
531
+ })
532
+ ```
533
+
534
+ **Josefin Sans** - Geometric elegance with vintage charm
535
+ ```typescript
536
+ import josefinSans from "@capsizecss/metrics/josefinSans"
537
+ capsizeRadixPlugin({
538
+ outputPath: `./public/typography.css`,
539
+ defaultFontStack: [josefinSans, arial],
540
+ })
541
+ ```
542
+
543
+ ---
544
+
545
+ ## Modern Fonts (2015-2025)
546
+
547
+ These fonts represent the best typography additions from the last decade, featuring variable font support and modern design sensibilities.
548
+
549
+ ### Modern Sans-Serifs
550
+
551
+ **Plus Jakarta Sans** - Geometric warmth, variable font
552
+ ```typescript
553
+ import plusJakartaSans from "@capsizecss/metrics/plusJakartaSans"
554
+ capsizeRadixPlugin({
555
+ outputPath: `./public/typography.css`,
556
+ defaultFontStack: [plusJakartaSans, arial],
557
+ })
558
+ ```
559
+
560
+ **Outfit** - Clean geometric, perfect for design systems
561
+ ```typescript
562
+ import outfit from "@capsizecss/metrics/outfit"
563
+ ```
564
+
565
+ **Manrope** - Humanist geometric, friendly and modern
566
+ ```typescript
567
+ import manrope from "@capsizecss/metrics/manrope"
568
+ ```
569
+
570
+ **Sora** - Futuristic, UI-optimized
571
+ ```typescript
572
+ import sora from "@capsizecss/metrics/sora"
573
+ ```
574
+
575
+ **Figtree** - Clean yet friendly, great for UI
576
+ ```typescript
577
+ import figtree from "@capsizecss/metrics/figtree"
578
+ ```
579
+
580
+ **Space Grotesk** - Tech-forward, futuristic
581
+ ```typescript
582
+ import spaceGrotesk from "@capsizecss/metrics/spaceGrotesk"
583
+ ```
584
+
585
+ **Geist** - Vercel's font, optimized for code/web apps
586
+ ```typescript
587
+ import geist from "@capsizecss/metrics/geist"
588
+ ```
589
+
590
+ ---
591
+
592
+ ### Modern Serifs
593
+
594
+ **Instrument Serif + Instrument Sans** - Rising star, editorial elegance
595
+ ```typescript
596
+ import instrumentSerif from "@capsizecss/metrics/instrumentSerif"
597
+ import instrumentSans from "@capsizecss/metrics/instrumentSans"
598
+ capsizeRadixPlugin({
599
+ outputPath: `./public/typography.css`,
600
+ headingFontStack: [instrumentSerif, georgia],
601
+ defaultFontStack: [instrumentSans, arial],
602
+ })
603
+ ```
604
+
605
+ **DM Serif Display + DM Sans** - Google/DeepMind family, cohesive
606
+ ```typescript
607
+ import dmSerifDisplay from "@capsizecss/metrics/dmSerifDisplay"
608
+ import dmSans from "@capsizecss/metrics/dmSans"
609
+ capsizeRadixPlugin({
610
+ outputPath: `./public/typography.css`,
611
+ headingFontStack: [dmSerifDisplay, georgia],
612
+ defaultFontStack: [dmSans, arial],
613
+ })
614
+ ```
615
+
616
+ **Newsreader + Figtree** - Designed for long-form reading
617
+ ```typescript
618
+ import newsreader from "@capsizecss/metrics/newsreader"
619
+ import figtree from "@capsizecss/metrics/figtree"
620
+ capsizeRadixPlugin({
621
+ outputPath: `./public/typography.css`,
622
+ defaultFontStack: [newsreader, georgia],
623
+ headingFontStack: [figtree, arial],
624
+ })
625
+ ```
626
+
627
+ **Literata** - Google Play Books default, exceptional for reading
628
+ ```typescript
629
+ import literata from "@capsizecss/metrics/literata"
630
+ ```
631
+
632
+ **Fraunces + Epilogue** - Expressive soft-serif with unique "wonk" axis
633
+ ```typescript
634
+ import fraunces from "@capsizecss/metrics/fraunces"
635
+ import epilogue from "@capsizecss/metrics/epilogue"
636
+ capsizeRadixPlugin({
637
+ outputPath: `./public/typography.css`,
638
+ headingFontStack: [fraunces, georgia],
639
+ defaultFontStack: [epilogue, arial],
640
+ })
641
+ ```
642
+
643
+ **Bodoni Moda + Outfit** - High-fashion luxury
644
+ ```typescript
645
+ import bodoniModa from "@capsizecss/metrics/bodoniModa"
646
+ import outfit from "@capsizecss/metrics/outfit"
647
+ capsizeRadixPlugin({
648
+ outputPath: `./public/typography.css`,
649
+ headingFontStack: [bodoniModa, georgia],
650
+ defaultFontStack: [outfit, arial],
651
+ })
652
+ ```
653
+
654
+ ---
655
+
656
+ ### Tech & Developer
657
+
658
+ **Space Grotesk + Space Mono** - Cohesive tech aesthetic
659
+ ```typescript
660
+ import spaceGrotesk from "@capsizecss/metrics/spaceGrotesk"
661
+ import spaceMono from "@capsizecss/metrics/spaceMono"
662
+ capsizeRadixPlugin({
663
+ outputPath: `./public/typography.css`,
664
+ defaultFontStack: [spaceGrotesk, arial],
665
+ codingFontStack: [spaceMono],
666
+ })
667
+ ```
668
+
669
+ **Geist + Geist Mono** - Vercel's Next.js default
670
+ ```typescript
671
+ import geist from "@capsizecss/metrics/geist"
672
+ import geistMono from "@capsizecss/metrics/geistMono"
673
+ capsizeRadixPlugin({
674
+ outputPath: `./public/typography.css`,
675
+ defaultFontStack: [geist, arial],
676
+ codingFontStack: [geistMono],
677
+ })
678
+ ```
679
+
680
+ **Be Vietnam Pro** - Neo-grotesque for tech companies
681
+ ```typescript
682
+ import beVietnamPro from "@capsizecss/metrics/beVietnamPro"
683
+ ```
684
+
685
+ **Bricolage Grotesque** - Editorial tech, variable width
686
+ ```typescript
687
+ import bricolageGrotesque from "@capsizecss/metrics/bricolageGrotesque"
688
+ ```
689
+
690
+ ---
691
+
692
+ ### Accessibility-Focused
693
+
694
+ **Atkinson Hyperlegible** - Braille Institute, maximizes character recognition
695
+ ```typescript
696
+ import atkinsonHyperlegible from "@capsizecss/metrics/atkinsonHyperlegible"
697
+ capsizeRadixPlugin({
698
+ outputPath: `./public/typography.css`,
699
+ defaultFontStack: [atkinsonHyperlegible, arial],
700
+ })
701
+ ```
702
+
703
+ **Lexend** - Reduces visual stress, improves reading performance
704
+ ```typescript
705
+ import lexend from "@capsizecss/metrics/lexend"
706
+ ```
707
+
708
+ ---
709
+
710
+ ### Versatile Modern Choices
711
+
712
+ **Commissioner** - Humanist with unique "flair" axis
713
+ ```typescript
714
+ import commissioner from "@capsizecss/metrics/commissioner"
715
+ ```
716
+
717
+ **Epilogue** - Clean variable sans, works at all sizes
718
+ ```typescript
719
+ import epilogue from "@capsizecss/metrics/epilogue"
720
+ ```
721
+
722
+ **Albert Sans** - Contemporary humanist warmth
723
+ ```typescript
724
+ import albertSans from "@capsizecss/metrics/albertSans"
725
+ ```
726
+
727
+ **Archivo** - Neo-grotesque superfamily (normal, condensed, black)
728
+ ```typescript
729
+ import archivo from "@capsizecss/metrics/archivo"
730
+ ```
731
+
732
+ ---
733
+
734
+ ### Modern Quick Reference
735
+
736
+ | Font | Type | Year | Best For | Variable |
737
+ |------|------|------|----------|----------|
738
+ | Plus Jakarta Sans | Sans | 2020 | Body/UI | Yes |
739
+ | Outfit | Sans | 2021 | Branding | Yes |
740
+ | Manrope | Sans | 2019 | UI/Body | Yes |
741
+ | Sora | Sans | 2020 | Apps/UI | Yes |
742
+ | Figtree | Sans | 2022 | UI/Body | Yes |
743
+ | Space Grotesk | Sans | 2018 | Tech/Display | No |
744
+ | Geist | Sans | 2024 | Web Apps | Yes |
745
+ | DM Sans | Sans | 2019 | Small Text | Yes |
746
+ | Instrument Sans | Sans | 2023 | Branding | Yes |
747
+ | Be Vietnam Pro | Sans | 2021 | Tech | Yes |
748
+ | Bricolage Grotesque | Sans | 2023 | Editorial | Yes |
749
+ | Instrument Serif | Serif | 2023 | Display | No |
750
+ | Newsreader | Serif | 2020 | Long-form | Yes |
751
+ | Literata | Serif | 2015 | Reading | Yes |
752
+ | DM Serif Display | Serif | 2019 | Headlines | No |
753
+ | Bodoni Moda | Serif | 2020 | Luxury | Yes |
754
+ | Fraunces | Serif | 2020 | Expressive | Yes |
755
+ | Atkinson Hyperlegible | Sans | 2021 | Accessibility | Yes |
756
+ | Lexend | Sans | 2019 | Readability | Yes |
757
+ | Commissioner | Sans | 2020 | Multilingual | Yes |
758
+ | Epilogue | Sans | 2018 | Versatile | Yes |
759
+ | Albert Sans | Sans | 2022 | Body/Heads | Yes |
760
+ | Archivo | Sans | 2017 | Headlines | Yes |
761
+
762
+ ---
763
+
764
+ ### System Fonts (Zero Network Requests)
765
+
766
+ For maximum performance, use system fonts. The plugin defaults to a carefully ordered system font stack:
767
+
768
+ ```typescript
769
+ // No font imports needed - plugin uses built-in system font metrics
770
+ capsizeRadixPlugin({
771
+ outputPath: `./public/typography.css`,
772
+ // omit defaultFontStack to use system fonts:
773
+ // Apple System, Segoe UI, Roboto, Ubuntu, Noto Sans
774
+ })
775
+ ```
776
+
777
+ ## Adding Custom Fonts
778
+
779
+ For fonts not in Fontsource or proprietary fonts:
780
+
781
+ ### 1. Get Font Metrics
782
+
783
+ Use `@capsizecss/unpack` to extract metrics from a font file:
784
+
785
+ ```bash
786
+ pnpm add -D @capsizecss/unpack
787
+ ```
788
+
789
+ ```typescript
790
+ // scripts/extract-metrics.ts
791
+ import { fromFile } from "@capsizecss/unpack"
792
+
793
+ const metrics = await fromFile("./fonts/MyCustomFont.woff2")
794
+ console.log(JSON.stringify(metrics, null, 2))
795
+ ```
796
+
797
+ ### 2. Create a Metrics File
798
+
799
+ Save the output as a TypeScript file:
800
+
801
+ ```typescript
802
+ // src/fonts/my-custom-font-metrics.ts
803
+ import type { FontMetrics } from "@capsizecss/core"
804
+
805
+ const myCustomFont: FontMetrics = {
806
+ familyName: "My Custom Font",
807
+ category: "sans-serif",
808
+ capHeight: 700,
809
+ ascent: 935,
810
+ descent: -265,
811
+ lineGap: 0,
812
+ unitsPerEm: 1000,
813
+ xHeight: 520,
814
+ xWidthAvg: 500,
815
+ }
816
+
817
+ export default myCustomFont
818
+ ```
819
+
820
+ ### 3. Add Font-Face CSS
821
+
822
+ ```css
823
+ /* src/fonts/my-custom-font.css */
824
+ @font-face {
825
+ font-family: "My Custom Font";
826
+ src: url("/fonts/MyCustomFont.woff2") format("woff2");
827
+ font-weight: 400;
828
+ font-style: normal;
829
+ font-display: swap;
830
+ }
831
+ ```
832
+
833
+ ### 4. Configure the Plugin
834
+
835
+ ```typescript
836
+ import myCustomFont from "./src/fonts/my-custom-font-metrics"
837
+ import arial from "@capsizecss/metrics/arial"
838
+
839
+ capsizeRadixPlugin({
840
+ outputPath: `./public/typography.css`,
841
+ defaultFontStack: [myCustomFont, arial],
842
+ })
843
+ ```
844
+
845
+ ### 5. Import the Font CSS
846
+
847
+ ```typescript
848
+ // main.tsx
849
+ import "@radix-ui/themes/styles.css"
850
+ import "./src/fonts/my-custom-font.css" // Your @font-face rules
851
+ import "/typography.css" // Generated capsize CSS
852
+ ```
853
+
854
+ ## Validating Your Setup
855
+
856
+ After configuration, verify:
857
+
858
+ 1. **Build succeeds**: `pnpm build` generates the CSS file
859
+ 2. **CSS file exists**: Check `outputPath` location
860
+ 3. **Variables are overridden**: Inspect `.radix-themes` in browser DevTools
861
+ 4. **Text is trimmed**: Text should align precisely to grid lines
862
+
863
+ ### Common Issues
864
+
865
+ **CSS not applying**: Check import order - typography CSS must come after Radix styles
866
+
867
+ **Font not loading**: Verify Fontsource import path and that font files are bundled
868
+
869
+ **Metrics mismatch**: Ensure the metrics package matches your font version
870
+
871
+ **Missing fallback**: Always include a fallback font (arial, georgia) for consistent rendering
872
+
873
+ ## Code Font Configuration
874
+
875
+ For code blocks and inline code, choose a monospace font:
876
+
877
+ | Font | Package | Metrics Import | Notes |
878
+ |------|---------|----------------|-------|
879
+ | Source Code Pro | `@fontsource/source-code-pro` | `@capsizecss/metrics/sourceCodePro` | Adobe, clean |
880
+ | Fira Code | `@fontsource/fira-code` | `@capsizecss/metrics/firaCode` | Ligatures |
881
+ | JetBrains Mono | `@fontsource/jetbrains-mono` | `@capsizecss/metrics/jetBrainsMono` | IDE-optimized |
882
+ | Geist Mono | `@fontsource/geist-mono` | `@capsizecss/metrics/geistMono` | Vercel/Next.js |
883
+ | Space Mono | `@fontsource/space-mono` | `@capsizecss/metrics/spaceMono` | Retro-tech |
884
+ | DM Mono | `@fontsource/dm-mono` | `@capsizecss/metrics/dmMono` | DeepMind family |
885
+ | IBM Plex Mono | `@fontsource/ibm-plex-mono` | `@capsizecss/metrics/ibmPlexMono` | Corporate |
886
+ | Inconsolata | `@fontsource/inconsolata` | `@capsizecss/metrics/inconsolata` | Compact |
887
+ | Roboto Mono | `@fontsource/roboto-mono` | `@capsizecss/metrics/robotoMono` | Material Design |
888
+
889
+ ```typescript
890
+ import sourceCodePro from "@capsizecss/metrics/sourceCodePro"
891
+
892
+ capsizeRadixPlugin({
893
+ outputPath: `./public/typography.css`,
894
+ defaultFontStack: [inter, arial],
895
+ codingFontStack: [sourceCodePro],
896
+ })
897
+ ```
898
+
899
+ Don't forget to import the font CSS:
900
+ ```typescript
901
+ import "@fontsource/source-code-pro/latin.css"
902
+ ```
903
+
904
+ ## Full Example
905
+
906
+ ```typescript
907
+ // vite.config.ts
908
+ import { defineConfig } from "vite"
909
+ import react from "@vitejs/plugin-react"
910
+ import { capsizeRadixPlugin } from "vite-plugin-capsize-radix"
911
+ import playfairDisplay from "@capsizecss/metrics/playfairDisplay"
912
+ import firaSans from "@capsizecss/metrics/firaSans"
913
+ import sourceCodePro from "@capsizecss/metrics/sourceCodePro"
914
+ import georgia from "@capsizecss/metrics/georgia"
915
+ import arial from "@capsizecss/metrics/arial"
916
+
917
+ export default defineConfig({
918
+ plugins: [
919
+ react(),
920
+ capsizeRadixPlugin({
921
+ outputPath: `./public/typography.css`,
922
+ headingFontStack: [playfairDisplay, georgia],
923
+ defaultFontStack: [firaSans, arial],
924
+ codingFontStack: [sourceCodePro],
925
+ }),
926
+ ],
927
+ })
928
+ ```
929
+
930
+ ```typescript
931
+ // main.tsx
932
+ import React from "react"
933
+ import ReactDOM from "react-dom/client"
934
+ import { Theme } from "@radix-ui/themes"
935
+ import App from "./App"
936
+
937
+ // CSS imports in correct order
938
+ import "@radix-ui/themes/styles.css"
939
+ import "@fontsource/playfair-display/latin.css"
940
+ import "@fontsource/fira-sans/latin.css"
941
+ import "@fontsource/source-code-pro/latin.css"
942
+ import "/typography.css"
943
+ import "./App.css"
944
+
945
+ ReactDOM.createRoot(document.getElementById("root")!).render(
946
+ <React.StrictMode>
947
+ <Theme accentColor="indigo">
948
+ <App />
949
+ </Theme>
950
+ </React.StrictMode>
951
+ )
952
+ ```
package/dist/index.js CHANGED
@@ -64,6 +64,7 @@ var template = `/* Auto-generated by vite-plugin-capsize-radix */
64
64
  {{#mobileFontData}}
65
65
  --font-size-{{{i}}}: {{{fontSize}}};
66
66
  --line-height-{{{i}}}: {{{lineHeight}}};
67
+ --heading-line-height-{{{i}}}: {{{lineHeight}}};
67
68
  {{/mobileFontData}}
68
69
 
69
70
  /* Larger devices */
@@ -71,6 +72,7 @@ var template = `/* Auto-generated by vite-plugin-capsize-radix */
71
72
  {{#fontData}}
72
73
  --font-size-{{{i}}}: {{{fontSize}}};
73
74
  --line-height-{{{i}}}: {{{lineHeight}}};
75
+ --heading-line-height-{{{i}}}: {{{lineHeight}}};
74
76
  {{/fontData}}
75
77
  }
76
78
  }
@@ -127,6 +129,37 @@ var template = `/* Auto-generated by vite-plugin-capsize-radix */
127
129
  {{{style}}}
128
130
  {{/fontData}}
129
131
  }
132
+
133
+ /* Native text-box-trim for browsers that support it (Chrome 133+, Safari 18.2+) */
134
+ @supports (text-box-trim: both) {
135
+ .rt-Text,
136
+ .rt-Heading,
137
+ .rt-Em,
138
+ .rt-Quote,
139
+ .rt-Link,
140
+ .rt-Code {
141
+ text-box-trim: both;
142
+ text-box-edge: cap text;
143
+ }
144
+
145
+ /* Disable capsize pseudo-elements when native trim is supported */
146
+ .rt-Text::before,
147
+ .rt-Text::after,
148
+ .rt-Heading::before,
149
+ .rt-Heading::after,
150
+ .rt-Em::before,
151
+ .rt-Em::after,
152
+ .rt-Quote::before,
153
+ .rt-Quote::after,
154
+ .rt-Link::before,
155
+ .rt-Link::after,
156
+ .rt-Code::before,
157
+ .rt-Code::after,
158
+ :where(.rt-Text, .rt-Heading, .rt-Em, .rt-Quote, .rt-Link)::before,
159
+ :where(.rt-Text, .rt-Heading, .rt-Em, .rt-Quote, .rt-Link)::after {
160
+ display: none !important;
161
+ }
162
+ }
130
163
  `;
131
164
  function validateOptions(options) {
132
165
  if (!options.outputPath) {
@@ -347,9 +380,9 @@ function capsizeRadixPlugin({
347
380
  { fontSize: 14, lineHeight: 28 },
348
381
  { fontSize: 18, lineHeight: 30 },
349
382
  { fontSize: 24, lineHeight: 36 },
350
- { fontSize: 36, lineHeight: 44 },
351
- { fontSize: 48, lineHeight: 52 },
352
- { fontSize: 64, lineHeight: 64 }
383
+ { fontSize: 36, lineHeight: 48 },
384
+ { fontSize: 48, lineHeight: 60 },
385
+ { fontSize: 64, lineHeight: 80 }
353
386
  ],
354
387
  defaultFontStack,
355
388
  headingFontStack,
package/dist/index.mjs CHANGED
@@ -34,6 +34,7 @@ var template = `/* Auto-generated by vite-plugin-capsize-radix */
34
34
  {{#mobileFontData}}
35
35
  --font-size-{{{i}}}: {{{fontSize}}};
36
36
  --line-height-{{{i}}}: {{{lineHeight}}};
37
+ --heading-line-height-{{{i}}}: {{{lineHeight}}};
37
38
  {{/mobileFontData}}
38
39
 
39
40
  /* Larger devices */
@@ -41,6 +42,7 @@ var template = `/* Auto-generated by vite-plugin-capsize-radix */
41
42
  {{#fontData}}
42
43
  --font-size-{{{i}}}: {{{fontSize}}};
43
44
  --line-height-{{{i}}}: {{{lineHeight}}};
45
+ --heading-line-height-{{{i}}}: {{{lineHeight}}};
44
46
  {{/fontData}}
45
47
  }
46
48
  }
@@ -97,6 +99,37 @@ var template = `/* Auto-generated by vite-plugin-capsize-radix */
97
99
  {{{style}}}
98
100
  {{/fontData}}
99
101
  }
102
+
103
+ /* Native text-box-trim for browsers that support it (Chrome 133+, Safari 18.2+) */
104
+ @supports (text-box-trim: both) {
105
+ .rt-Text,
106
+ .rt-Heading,
107
+ .rt-Em,
108
+ .rt-Quote,
109
+ .rt-Link,
110
+ .rt-Code {
111
+ text-box-trim: both;
112
+ text-box-edge: cap text;
113
+ }
114
+
115
+ /* Disable capsize pseudo-elements when native trim is supported */
116
+ .rt-Text::before,
117
+ .rt-Text::after,
118
+ .rt-Heading::before,
119
+ .rt-Heading::after,
120
+ .rt-Em::before,
121
+ .rt-Em::after,
122
+ .rt-Quote::before,
123
+ .rt-Quote::after,
124
+ .rt-Link::before,
125
+ .rt-Link::after,
126
+ .rt-Code::before,
127
+ .rt-Code::after,
128
+ :where(.rt-Text, .rt-Heading, .rt-Em, .rt-Quote, .rt-Link)::before,
129
+ :where(.rt-Text, .rt-Heading, .rt-Em, .rt-Quote, .rt-Link)::after {
130
+ display: none !important;
131
+ }
132
+ }
100
133
  `;
101
134
  function validateOptions(options) {
102
135
  if (!options.outputPath) {
@@ -317,9 +350,9 @@ function capsizeRadixPlugin({
317
350
  { fontSize: 14, lineHeight: 28 },
318
351
  { fontSize: 18, lineHeight: 30 },
319
352
  { fontSize: 24, lineHeight: 36 },
320
- { fontSize: 36, lineHeight: 44 },
321
- { fontSize: 48, lineHeight: 52 },
322
- { fontSize: 64, lineHeight: 64 }
353
+ { fontSize: 36, lineHeight: 48 },
354
+ { fontSize: 48, lineHeight: 60 },
355
+ { fontSize: 64, lineHeight: 80 }
323
356
  ],
324
357
  defaultFontStack,
325
358
  headingFontStack,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vite-plugin-capsize-radix",
3
3
  "description": "Great Typography with Radix & Capsize",
4
- "version": "0.1.4",
4
+ "version": "0.2.0",
5
5
  "author": "Kyle Mathews <mathews.kyle@gmail.com>",
6
6
  "dependencies": {
7
7
  "@capsizecss/core": "^4.1.3",
@@ -43,7 +43,8 @@
43
43
  "./package.json": "./package.json"
44
44
  },
45
45
  "files": [
46
- "dist"
46
+ "dist",
47
+ "SKILL.md"
47
48
  ],
48
49
  "keywords": [
49
50
  "capsizecss",
@@ -54,6 +55,16 @@
54
55
  "license": "MIT",
55
56
  "main": "./dist/index.js",
56
57
  "module": "./dist/index.mjs",
58
+ "scripts": {
59
+ "build": "pnpm run clean && tsup --external @capsizecss/core --external mustache --external @capsizecss/metrics",
60
+ "check": "tsc",
61
+ "clean": "shx rm -rf dist *.d.ts",
62
+ "lint": "eslint src tests --ext .ts,.tsx",
63
+ "format": "prettier --write .",
64
+ "format:check": "prettier --check .",
65
+ "prepublishOnly": "pnpm run build",
66
+ "test": "vitest run"
67
+ },
57
68
  "tsup": {
58
69
  "entry": [
59
70
  "src/index.ts"
@@ -64,14 +75,5 @@
64
75
  ],
65
76
  "dts": true
66
77
  },
67
- "types": "./dist/index.d.ts",
68
- "scripts": {
69
- "build": "pnpm run clean && tsup --external @capsizecss/core --external mustache --external @capsizecss/metrics",
70
- "check": "tsc",
71
- "clean": "shx rm -rf dist *.d.ts",
72
- "lint": "eslint src tests --ext .ts,.tsx",
73
- "format": "prettier --write .",
74
- "format:check": "prettier --check .",
75
- "test": "vitest run"
76
- }
77
- }
78
+ "types": "./dist/index.d.ts"
79
+ }