get-shit-pretty 0.5.0 → 0.5.2
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/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/bin/install.js +38 -19
- package/gsp/agents/gsp-accessibility-auditor.md +1 -4
- package/gsp/agents/gsp-ascii-artist.md +1 -1
- package/gsp/agents/gsp-brand-auditor.md +0 -2
- package/gsp/agents/gsp-brand-strategist.md +0 -2
- package/gsp/agents/gsp-brand-syncer.md +125 -0
- package/gsp/agents/gsp-builder.md +11 -14
- package/gsp/agents/gsp-campaign-director.md +0 -20
- package/gsp/agents/gsp-critic.md +15 -18
- package/gsp/agents/gsp-designer.md +6 -6
- package/gsp/agents/gsp-identity-designer.md +0 -4
- package/gsp/agents/{gsp-system-architect.md → gsp-pattern-architect.md} +5 -67
- package/gsp/agents/gsp-project-researcher.md +0 -21
- package/gsp/agents/gsp-researcher.md +0 -2
- package/gsp/agents/gsp-reviewer.md +4 -14
- package/gsp/agents/gsp-scoper.md +1 -22
- package/gsp/hooks/hooks.json +11 -0
- package/gsp/prompts/01-design-system-architect.md +0 -46
- package/gsp/prompts/02-brand-identity-creator.md +1 -14
- package/gsp/prompts/03-ui-ux-pattern-master.md +1 -21
- package/gsp/prompts/04-marketing-asset-factory.md +1 -14
- package/gsp/prompts/05-implementation-spec-expert.md +0 -27
- package/gsp/prompts/06-design-critique-partner.md +1 -17
- package/gsp/prompts/07-design-trend-synthesizer.md +2 -29
- package/gsp/prompts/08-accessibility-auditor.md +4 -19
- package/gsp/prompts/09-design-to-code-translator.md +21 -20
- package/gsp/prompts/10-project-scoper.md +2 -36
- package/gsp/prompts/11-deliverable-reviewer.md +1 -50
- package/gsp/prompts/12-project-researcher.md +0 -39
- package/gsp/references/anti-patterns.md +173 -0
- package/gsp/references/block-patterns.md +135 -0
- package/gsp/references/chunk-format.md +31 -0
- package/gsp/references/phase-transitions.md +78 -33
- package/gsp/references/style-preset-schema.md +63 -0
- package/gsp/references/visual-effects.md +475 -0
- package/gsp/references/visual-taste.md +120 -0
- package/gsp/skills/gsp-accessibility/SKILL.md +1 -1
- package/gsp/skills/gsp-brand-audit/SKILL.md +1 -3
- package/gsp/skills/gsp-brand-identity/SKILL.md +1 -4
- package/gsp/skills/gsp-brand-patterns/SKILL.md +30 -50
- package/gsp/skills/gsp-brand-research/SKILL.md +7 -4
- package/gsp/skills/gsp-brand-strategy/SKILL.md +1 -4
- package/gsp/skills/gsp-brand-sync/SKILL.md +101 -0
- package/gsp/skills/gsp-design-system/SKILL.md +1 -1
- package/gsp/skills/gsp-doctor/SKILL.md +7 -7
- package/gsp/skills/gsp-help/SKILL.md +2 -1
- package/gsp/skills/gsp-launch/SKILL.md +2 -3
- package/gsp/skills/gsp-project-brief/SKILL.md +7 -22
- package/gsp/skills/gsp-project-build/SKILL.md +108 -26
- package/gsp/skills/gsp-project-critique/SKILL.md +5 -33
- package/gsp/skills/gsp-project-design/SKILL.md +25 -26
- package/gsp/skills/gsp-project-research/SKILL.md +8 -17
- package/gsp/skills/gsp-project-review/SKILL.md +6 -37
- package/gsp/skills/gsp-start/SKILL.md +29 -12
- package/gsp/skills/gsp-style/SKILL.md +20 -223
- package/gsp/skills/gsp-typescale/SKILL.md +23 -319
- package/gsp/skills/gsp-update/SKILL.md +18 -10
- package/gsp/templates/branding/brief.md +13 -1
- package/gsp/templates/branding/roadmap.md +2 -2
- package/gsp/templates/branding/state.md +1 -1
- package/gsp/templates/phases/brief.md +1 -1
- package/gsp/templates/phases/{system.md → patterns.md} +3 -3
- package/gsp/templates/phases/review.md +1 -1
- package/package.json +1 -1
- package/scripts/gsp-context-recovery.sh +71 -0
- package/scripts/gsp-statusline.js +5 -1
|
@@ -30,13 +30,11 @@ Apply a named style preset to produce production-ready design tokens and foundat
|
|
|
30
30
|
@${CLAUDE_SKILL_DIR}/styles/INDEX.yml
|
|
31
31
|
@${CLAUDE_SKILL_DIR}/../../references/design-tokens.md
|
|
32
32
|
@${CLAUDE_SKILL_DIR}/../../references/chunk-format.md
|
|
33
|
-
@${CLAUDE_SKILL_DIR}/../../templates/phases/
|
|
33
|
+
@${CLAUDE_SKILL_DIR}/../../templates/phases/patterns.md
|
|
34
34
|
</execution_context>
|
|
35
35
|
|
|
36
36
|
<rules>
|
|
37
37
|
- Always use `AskUserQuestion` for user interaction — never prompt via plain text
|
|
38
|
-
- Presets are the source of truth — expand tokens deterministically, don't improvise values
|
|
39
|
-
- Foundation chunks follow `references/chunk-format.md` format exactly
|
|
40
38
|
- `tokens.json` follows W3C Design Tokens format from `references/design-tokens.md`
|
|
41
39
|
- When mixing styles, later style values override earlier ones (last-wins precedence)
|
|
42
40
|
- Never mix clashing styles — check the compatibility matrix first
|
|
@@ -163,18 +161,18 @@ Determine where to write the system output:
|
|
|
163
161
|
|
|
164
162
|
### Within a brand
|
|
165
163
|
If a brand context exists (`.design/branding/{brand}/`):
|
|
166
|
-
- Write to `{BRAND_PATH}/
|
|
167
|
-
- This replaces the
|
|
164
|
+
- Write to `{BRAND_PATH}/patterns/`
|
|
165
|
+
- This replaces the patterns phase of the branding diamond
|
|
168
166
|
|
|
169
167
|
### Within a project (quick mode)
|
|
170
168
|
If invoked from a project context (`.design/projects/{project}/`):
|
|
171
169
|
- Check if a `brand.ref` exists pointing to a brand with a completed system
|
|
172
|
-
- If no brand system exists, write to `.design/branding/_style-{preset-name}/
|
|
170
|
+
- If no brand system exists, write to `.design/branding/_style-{preset-name}/patterns/`
|
|
173
171
|
- Create a minimal brand directory with just the system output
|
|
174
172
|
- Update the project's `brand.ref` to point to this auto-generated brand
|
|
175
173
|
|
|
176
174
|
### Standalone (no .design/ context)
|
|
177
|
-
- Write to `.design/branding/_style-{preset-name}/
|
|
175
|
+
- Write to `.design/branding/_style-{preset-name}/patterns/`
|
|
178
176
|
- Create minimal brand directory structure
|
|
179
177
|
|
|
180
178
|
## Step 5: Preview mode (`--preview`)
|
|
@@ -221,226 +219,25 @@ Stop here. Do not write any files.
|
|
|
221
219
|
|
|
222
220
|
Transform the YAML preset tokens into the full W3C Design Tokens JSON structure.
|
|
223
221
|
|
|
224
|
-
###
|
|
225
|
-
Map preset colors to the W3C structure with `$value` and `$type` fields:
|
|
226
|
-
|
|
227
|
-
```json
|
|
228
|
-
{
|
|
229
|
-
"color": {
|
|
230
|
-
"brand": {
|
|
231
|
-
"primary": { "$value": "{preset.color.primary}", "$type": "color" },
|
|
232
|
-
"secondary": { "$value": "{preset.color.secondary}", "$type": "color" },
|
|
233
|
-
"accent": { "$value": "{preset.color.accent}", "$type": "color" }
|
|
234
|
-
},
|
|
235
|
-
"semantic": {
|
|
236
|
-
"background": { "$value": "{preset.color.background}", "$type": "color" },
|
|
237
|
-
"surface": { "$value": "{preset.color.surface}", "$type": "color" },
|
|
238
|
-
"on-primary": { "$value": "{preset.color.on-primary}", "$type": "color" },
|
|
239
|
-
"on-background": { "$value": "{preset.color.on-background}", "$type": "color" },
|
|
240
|
-
"error": { "$value": "{preset.color.error}", "$type": "color" },
|
|
241
|
-
"success": { "$value": "{preset.color.success}", "$type": "color" },
|
|
242
|
-
"warning": { "$value": "{preset.color.warning}", "$type": "color" },
|
|
243
|
-
"info": { "$value": "{preset.color.info}", "$type": "color" }
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
### Typography tokens
|
|
250
|
-
```json
|
|
251
|
-
{
|
|
252
|
-
"font": {
|
|
253
|
-
"family": {
|
|
254
|
-
"primary": { "$value": "{preset.typography.font-family-primary}", "$type": "fontFamily" },
|
|
255
|
-
"mono": { "$value": "{preset.typography.font-family-mono}", "$type": "fontFamily" }
|
|
256
|
-
}
|
|
257
|
-
},
|
|
258
|
-
"typography": {
|
|
259
|
-
"display": {
|
|
260
|
-
"$value": {
|
|
261
|
-
"fontFamily": "{font.family.primary}",
|
|
262
|
-
"fontSize": "48px",
|
|
263
|
-
"fontWeight": "{preset.typography.font-weight-heading}",
|
|
264
|
-
"lineHeight": 1.1,
|
|
265
|
-
"letterSpacing": "-0.02em"
|
|
266
|
-
},
|
|
267
|
-
"$type": "typography"
|
|
268
|
-
},
|
|
269
|
-
"heading-1": {
|
|
270
|
-
"$value": {
|
|
271
|
-
"fontFamily": "{font.family.primary}",
|
|
272
|
-
"fontSize": "36px",
|
|
273
|
-
"fontWeight": "{preset.typography.font-weight-heading}",
|
|
274
|
-
"lineHeight": 1.2,
|
|
275
|
-
"letterSpacing": "-0.01em"
|
|
276
|
-
},
|
|
277
|
-
"$type": "typography"
|
|
278
|
-
},
|
|
279
|
-
"heading-2": {
|
|
280
|
-
"$value": {
|
|
281
|
-
"fontFamily": "{font.family.primary}",
|
|
282
|
-
"fontSize": "28px",
|
|
283
|
-
"fontWeight": "{preset.typography.font-weight-heading}",
|
|
284
|
-
"lineHeight": 1.3,
|
|
285
|
-
"letterSpacing": "0"
|
|
286
|
-
},
|
|
287
|
-
"$type": "typography"
|
|
288
|
-
},
|
|
289
|
-
"heading-3": {
|
|
290
|
-
"$value": {
|
|
291
|
-
"fontFamily": "{font.family.primary}",
|
|
292
|
-
"fontSize": "22px",
|
|
293
|
-
"fontWeight": "{preset.typography.font-weight-heading}",
|
|
294
|
-
"lineHeight": 1.4,
|
|
295
|
-
"letterSpacing": "0"
|
|
296
|
-
},
|
|
297
|
-
"$type": "typography"
|
|
298
|
-
},
|
|
299
|
-
"body-large": {
|
|
300
|
-
"$value": {
|
|
301
|
-
"fontFamily": "{font.family.primary}",
|
|
302
|
-
"fontSize": "18px",
|
|
303
|
-
"fontWeight": "{preset.typography.font-weight-body}",
|
|
304
|
-
"lineHeight": "{preset.typography.line-height-base}",
|
|
305
|
-
"letterSpacing": "0"
|
|
306
|
-
},
|
|
307
|
-
"$type": "typography"
|
|
308
|
-
},
|
|
309
|
-
"body": {
|
|
310
|
-
"$value": {
|
|
311
|
-
"fontFamily": "{font.family.primary}",
|
|
312
|
-
"fontSize": "{preset.typography.font-size-base}",
|
|
313
|
-
"fontWeight": "{preset.typography.font-weight-body}",
|
|
314
|
-
"lineHeight": "{preset.typography.line-height-base}",
|
|
315
|
-
"letterSpacing": "0"
|
|
316
|
-
},
|
|
317
|
-
"$type": "typography"
|
|
318
|
-
},
|
|
319
|
-
"body-small": {
|
|
320
|
-
"$value": {
|
|
321
|
-
"fontFamily": "{font.family.primary}",
|
|
322
|
-
"fontSize": "14px",
|
|
323
|
-
"fontWeight": "{preset.typography.font-weight-body}",
|
|
324
|
-
"lineHeight": "{preset.typography.line-height-base}",
|
|
325
|
-
"letterSpacing": "0"
|
|
326
|
-
},
|
|
327
|
-
"$type": "typography"
|
|
328
|
-
},
|
|
329
|
-
"caption": {
|
|
330
|
-
"$value": {
|
|
331
|
-
"fontFamily": "{font.family.primary}",
|
|
332
|
-
"fontSize": "12px",
|
|
333
|
-
"fontWeight": "{preset.typography.font-weight-body}",
|
|
334
|
-
"lineHeight": 1.4,
|
|
335
|
-
"letterSpacing": "0.01em"
|
|
336
|
-
},
|
|
337
|
-
"$type": "typography"
|
|
338
|
-
},
|
|
339
|
-
"overline": {
|
|
340
|
-
"$value": {
|
|
341
|
-
"fontFamily": "{font.family.primary}",
|
|
342
|
-
"fontSize": "11px",
|
|
343
|
-
"fontWeight": 600,
|
|
344
|
-
"lineHeight": 1.5,
|
|
345
|
-
"letterSpacing": "0.08em"
|
|
346
|
-
},
|
|
347
|
-
"$type": "typography"
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
### Spacing tokens
|
|
354
|
-
Generate from the preset's spacing scale:
|
|
355
|
-
|
|
356
|
-
```json
|
|
357
|
-
{
|
|
358
|
-
"spacing": {
|
|
359
|
-
"xs": { "$value": "4px", "$type": "dimension" },
|
|
360
|
-
"sm": { "$value": "8px", "$type": "dimension" },
|
|
361
|
-
"md": { "$value": "16px", "$type": "dimension" },
|
|
362
|
-
"lg": { "$value": "24px", "$type": "dimension" },
|
|
363
|
-
"xl": { "$value": "32px", "$type": "dimension" },
|
|
364
|
-
"2xl": { "$value": "48px", "$type": "dimension" },
|
|
365
|
-
"3xl": { "$value": "64px", "$type": "dimension" },
|
|
366
|
-
"4xl": { "$value": "96px", "$type": "dimension" }
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
```
|
|
222
|
+
### Token expansion mapping
|
|
370
223
|
|
|
371
|
-
|
|
372
|
-
Map preset elevation values to W3C shadow format. Parse the CSS shadow shorthand from the preset into the structured format:
|
|
373
|
-
|
|
374
|
-
```json
|
|
375
|
-
{
|
|
376
|
-
"shadow": {
|
|
377
|
-
"sm": { "$value": "{parsed from preset.elevation.shadow-sm}", "$type": "shadow" },
|
|
378
|
-
"md": { "$value": "{parsed from preset.elevation.shadow-md}", "$type": "shadow" },
|
|
379
|
-
"lg": { "$value": "{parsed from preset.elevation.shadow-lg}", "$type": "shadow" },
|
|
380
|
-
"xl": { "$value": "{parsed from preset.elevation.shadow-xl}", "$type": "shadow" }
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
```
|
|
224
|
+
Transform each YAML preset section into W3C Design Tokens JSON with `$value` and `$type` fields:
|
|
384
225
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
{
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
```
|
|
226
|
+
| Preset section | Token path | $type | Notes |
|
|
227
|
+
|---------------|------------|-------|-------|
|
|
228
|
+
| `color.*` | `color.brand.{key}`, `color.semantic.{key}` | `color` | Split into brand (primary, secondary, accent) and semantic (background, surface, on-primary, on-background, error, success, warning, info) |
|
|
229
|
+
| `typography.*` | `font.family.{primary,mono}` | `fontFamily` | — |
|
|
230
|
+
| `typography.*` | `typography.{level}` | `typography` | Composite: fontFamily, fontSize, fontWeight, lineHeight, letterSpacing. 9 levels: display, heading-1 through heading-3, body-large, body, body-small, caption, overline |
|
|
231
|
+
| `spacing.*` | `spacing.{xs,sm,md,lg,xl,2xl,3xl,4xl}` | `dimension` | — |
|
|
232
|
+
| `elevation.*` | `shadow.{sm,md,lg,xl}` | `shadow` | Parse CSS shadow shorthand into structured format |
|
|
233
|
+
| `shape.*` | `radius.{none,sm,md,lg,full}` | `dimension` | `full` = 9999px |
|
|
234
|
+
| `motion.*` | `motion.duration.{fast,normal}`, `motion.easing.default` | `duration`, `cubicBezier` | — |
|
|
397
235
|
|
|
398
|
-
|
|
399
|
-
If the preset has extra token groups (e.g., `glass` for glassmorphism, `glow` for cyberpunk, `gradient` for vaporwave, `syntax` for terminal), include them under an `$extensions` key:
|
|
400
|
-
|
|
401
|
-
```json
|
|
402
|
-
{
|
|
403
|
-
"$extensions": {
|
|
404
|
-
"gsp-style": "{preset-name}",
|
|
405
|
-
"gsp-style-specific": {
|
|
406
|
-
// style-specific tokens preserved as-is from the preset
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
```
|
|
236
|
+
**Style-specific tokens:** If preset has extra groups (e.g., `glass`, `glow`, `gradient`, `syntax`), include under `$extensions.gsp-style-specific`.
|
|
411
237
|
|
|
412
|
-
|
|
413
|
-
If the preset has a `dark_mode` section, include it under `$extensions.dark`:
|
|
414
|
-
|
|
415
|
-
```json
|
|
416
|
-
{
|
|
417
|
-
"$extensions": {
|
|
418
|
-
"dark": {
|
|
419
|
-
"color": {
|
|
420
|
-
"semantic": {
|
|
421
|
-
"background": { "$value": "{preset.dark_mode.color.background}" },
|
|
422
|
-
"surface": { "$value": "{preset.dark_mode.color.surface}" }
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
```
|
|
238
|
+
**Dark mode:** If preset has `dark_mode` section, include under `$extensions.dark` with semantic color overrides.
|
|
429
239
|
|
|
430
|
-
|
|
431
|
-
```json
|
|
432
|
-
{
|
|
433
|
-
"motion": {
|
|
434
|
-
"duration": {
|
|
435
|
-
"fast": { "$value": "{preset.motion.duration-fast}", "$type": "duration" },
|
|
436
|
-
"normal": { "$value": "{preset.motion.duration-normal}", "$type": "duration" }
|
|
437
|
-
},
|
|
438
|
-
"easing": {
|
|
439
|
-
"default": { "$value": "{preset.motion.easing}", "$type": "cubicBezier" }
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
```
|
|
240
|
+
**Extensions metadata:** Always include `$extensions.gsp-style` with the preset name.
|
|
444
241
|
|
|
445
242
|
## Step 7: Write tokens.json
|
|
446
243
|
|
|
@@ -507,7 +304,7 @@ Write `{OUTPUT_PATH}/INDEX.md`:
|
|
|
507
304
|
## Step 10: Update state
|
|
508
305
|
|
|
509
306
|
If a brand STATE.md exists at the brand path:
|
|
510
|
-
- Set
|
|
307
|
+
- Set patterns phase status to `complete`
|
|
511
308
|
- Record style preset name and completion date
|
|
512
309
|
- Set Prettiness Level to 60% (foundations only, no components)
|
|
513
310
|
|
|
@@ -34,15 +34,12 @@ Generate a production-ready typography system with fluid responsive sizing, vert
|
|
|
34
34
|
|
|
35
35
|
<rules>
|
|
36
36
|
- Always use `AskUserQuestion` for user interaction — never prompt via plain text
|
|
37
|
-
- Scales are deterministic — same inputs always produce the same output
|
|
38
37
|
- Foundation chunks follow `references/chunk-format.md` format exactly
|
|
39
38
|
- All sizes include px, rem, AND fluid clamp() values for headings
|
|
40
39
|
- Line heights snap to a 4px grid for vertical rhythm (body 24px = 6 × 4px)
|
|
41
40
|
- Letter spacing follows the size-dependent curve: negative for large type, positive for small type, wide for all-caps (see reference)
|
|
42
|
-
- When loading from a style preset, extract only typography-related tokens
|
|
43
41
|
- CSS output defaults to Tailwind v4 / shadcn format unless `--vanilla` is passed
|
|
44
42
|
- WCAG 2.2 AA compliance: body line-height ≥ 1.5, layout must survive SC 1.4.12 text spacing overrides
|
|
45
|
-
- Fluid type clamp() must always use rem-based min/max — never pure vw (breaks zoom per WCAG 1.4.4)
|
|
46
43
|
</rules>
|
|
47
44
|
|
|
48
45
|
<process>
|
|
@@ -291,133 +288,17 @@ If a brand context exists (`.design/branding/{brand}/`):
|
|
|
291
288
|
|
|
292
289
|
Write `{OUTPUT_PATH}/typography.md` as a foundation chunk per `references/chunk-format.md`:
|
|
293
290
|
|
|
294
|
-
|
|
295
|
-
# Typography
|
|
291
|
+
The typography.md chunk must include these sections with calculated values from Step 3:
|
|
296
292
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
| Secondary | {family or "—"} | {yes/no} | {source} | {system fallbacks} |
|
|
307
|
-
| Monospace | {family or "Geist Mono"} | {yes/no} | Google Fonts | ui-monospace, monospace |
|
|
308
|
-
|
|
309
|
-
**Google Fonts URL:**
|
|
310
|
-
`https://fonts.googleapis.com/css2?family={primary}:wght@{weights}&family={mono}:wght@400;700&display=swap`
|
|
311
|
-
|
|
312
|
-
**Self-hosting recommended** for production — eliminates third-party DNS lookup, improves GDPR compliance, and allows precise subsetting. Use WOFF2 only.
|
|
313
|
-
|
|
314
|
-
**Performance budget:** < 100KB total font weight, 2-3 weights max. If using a variable font, a single file replaces all static weights (< 150KB).
|
|
315
|
-
|
|
316
|
-
## Type Scale
|
|
317
|
-
|
|
318
|
-
Base: {base}px | Ratio: {ratio} ({ratio name}) | Grid: {grid}px
|
|
319
|
-
|
|
320
|
-
| Level | px | rem | Fluid | Weight | Line height | Letter spacing | Tailwind |
|
|
321
|
-
|-------|----|-----|-------|--------|-------------|----------------|----------|
|
|
322
|
-
| Display | {px} | {rem} | clamp({...}) | {heading wt} | {lh}px / {unitless} | -0.025em | text-[{rem}rem] tracking-tighter |
|
|
323
|
-
| H1 | {px} | {rem} | clamp({...}) | {heading wt} | {lh}px / {unitless} | -0.025em | text-4xl tracking-tight font-extrabold |
|
|
324
|
-
| H2 | {px} | {rem} | clamp({...}) | {heading wt} | {lh}px / {unitless} | -0.025em | text-3xl tracking-tight font-semibold |
|
|
325
|
-
| H3 | {px} | {rem} | clamp({...}) | {heading wt} | {lh}px / {unitless} | -0.015em | text-2xl tracking-tight font-semibold |
|
|
326
|
-
| H4 | {px} | {rem} | clamp({...}) | {heading wt} | {lh}px / {unitless} | -0.01em | text-xl tracking-tight font-semibold |
|
|
327
|
-
| body-large | {px} | {rem} | — | {body wt} | {lh}px / {unitless} | 0 | text-lg |
|
|
328
|
-
| body | {base}px | 1rem | — | {body wt} | {lh}px / {unitless} | 0 | text-base leading-7 |
|
|
329
|
-
| body-small | {px} | {rem} | — | {body wt} | {lh}px / {unitless} | 0.01em | text-sm |
|
|
330
|
-
| caption | {px} | {rem} | — | {body wt} | {lh}px / {unitless} | 0.015em | text-xs |
|
|
331
|
-
| overline | {px} | {rem} | — | 600 | {lh}px / {unitless} | 0.1em | text-xs uppercase tracking-wider |
|
|
332
|
-
|
|
333
|
-
## shadcn/ui Typography Classes
|
|
334
|
-
|
|
335
|
-
Ready-to-use className strings for shadcn projects. These match the calculated scale above:
|
|
336
|
-
|
|
337
|
-
```tsx
|
|
338
|
-
// Headings
|
|
339
|
-
<h1 className="scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl">
|
|
340
|
-
<h2 className="scroll-m-20 border-b pb-2 text-3xl font-semibold tracking-tight first:mt-0">
|
|
341
|
-
<h3 className="scroll-m-20 text-2xl font-semibold tracking-tight">
|
|
342
|
-
<h4 className="scroll-m-20 text-xl font-semibold tracking-tight">
|
|
343
|
-
|
|
344
|
-
// Body
|
|
345
|
-
<p className="leading-7 [&:not(:first-child)]:mt-6">
|
|
346
|
-
<p className="text-xl text-muted-foreground"> {/* Lead */}
|
|
347
|
-
<p className="text-lg font-semibold"> {/* Large */}
|
|
348
|
-
<p className="text-sm font-medium leading-none"> {/* Small */}
|
|
349
|
-
<p className="text-sm text-muted-foreground"> {/* Muted */}
|
|
350
|
-
|
|
351
|
-
// Special
|
|
352
|
-
<blockquote className="mt-6 border-l-2 pl-6 italic">
|
|
353
|
-
<code className="relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold">
|
|
354
|
-
<span className="text-xs uppercase tracking-wider font-semibold"> {/* Overline */}
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
To customize these for your exact scale, extend Tailwind with the CSS file below.
|
|
358
|
-
|
|
359
|
-
## Vertical Rhythm
|
|
360
|
-
|
|
361
|
-
Grid unit: {grid}px | Body line-height: {body lh}px ({unitless})
|
|
362
|
-
|
|
363
|
-
All line-heights are snapped to {grid}px multiples. The body line-height ({body lh}px) serves as the spacing anchor — use multiples of it for consistent vertical spacing:
|
|
364
|
-
|
|
365
|
-
| Token | Value | Lines | Usage |
|
|
366
|
-
|-------|-------|-------|-------|
|
|
367
|
-
| space-xs | {grid}px | {fraction} | Inline element gaps |
|
|
368
|
-
| space-sm | {grid*2}px | {fraction} | Related element gaps |
|
|
369
|
-
| space-md | {body lh / 2}px | 0.5 | Compact section spacing |
|
|
370
|
-
| space-lg | {body lh}px | 1 | Default paragraph spacing |
|
|
371
|
-
| space-xl | {body lh * 1.5}px | 1.5 | Section breaks |
|
|
372
|
-
| space-2xl | {body lh * 2}px | 2 | Major section breaks |
|
|
373
|
-
|
|
374
|
-
CSS `lh` and `rlh` units (94%+ browser support) can reference line-height directly:
|
|
375
|
-
```css
|
|
376
|
-
p + p { margin-block: 1lh; } /* one line of spacing */
|
|
377
|
-
section { padding-block: 2rlh; } /* two root-line-heights */
|
|
378
|
-
```
|
|
379
|
-
|
|
380
|
-
## Weights
|
|
381
|
-
|
|
382
|
-
| Name | Value | Usage |
|
|
383
|
-
|------|-------|-------|
|
|
384
|
-
| Regular | {body weight} | Body text, descriptions |
|
|
385
|
-
| Medium | 500 | Emphasized body, nav items, labels |
|
|
386
|
-
| Semibold | 600 | shadcn heading default (H2-H4), overlines |
|
|
387
|
-
| Bold / Extrabold | {heading weight} | H1, page titles, CTAs |
|
|
388
|
-
|
|
389
|
-
## Accessibility
|
|
390
|
-
|
|
391
|
-
This scale meets WCAG 2.2 AA requirements:
|
|
392
|
-
- Body line-height ≥ 1.5× font size (SC 1.4.12) ✓
|
|
393
|
-
- Layout survives 200% zoom (SC 1.4.4) — fluid clamp() uses rem bounds ✓
|
|
394
|
-
- Minimum text size: {caption px}px (practical floor 12px) ✓
|
|
395
|
-
- Max line length recommendation: 60–75 characters (`max-w-prose` in Tailwind = 65ch)
|
|
396
|
-
|
|
397
|
-
**SC 1.4.12 resilience:** Layout must not break when users override to: line-height ≥ 1.5×, letter-spacing ≥ 0.12×, word-spacing ≥ 0.16×, paragraph-spacing ≥ 2× font size. Avoid fixed-height text containers.
|
|
398
|
-
|
|
399
|
-
## Variable Font Notes
|
|
400
|
-
|
|
401
|
-
{If the primary font is a variable font:}
|
|
402
|
-
- Enable optical sizing: `font-optical-sizing: auto` (browser maps opsz to font-size automatically)
|
|
403
|
-
- Dark mode grade adjustment: `@media (prefers-color-scheme: dark) { body { font-variation-settings: 'GRAD' -25; } }` — reduces apparent weight of light-on-dark text
|
|
404
|
-
- Use `font-variation-settings: 'wght' {value}` for precise weight control beyond standard keywords
|
|
405
|
-
{End if}
|
|
406
|
-
|
|
407
|
-
## Modern CSS Enhancements
|
|
408
|
-
|
|
409
|
-
```css
|
|
410
|
-
h1, h2, h3, h4 { text-wrap: balance; } /* Auto-balance heading line lengths */
|
|
411
|
-
p { text-wrap: pretty; } /* Avoid orphans in paragraphs */
|
|
412
|
-
```
|
|
413
|
-
|
|
414
|
-
---
|
|
415
|
-
|
|
416
|
-
## Related
|
|
417
|
-
|
|
418
|
-
- [tailwind.typography.css](./tailwind.typography.css)
|
|
419
|
-
- [palettes.json](./palettes.json)
|
|
420
|
-
```
|
|
293
|
+
- **Font Families** — table with Role, Family, Variable (yes/no), Source, Fallback stack. Include Google Fonts URL and self-hosting note.
|
|
294
|
+
- **Type Scale** — table with Level, px, rem, Fluid clamp(), Weight, Line height (px + unitless), Letter spacing, Tailwind class. All 10 levels: Display, H1-H4, body-large, body, body-small, caption, overline.
|
|
295
|
+
- **shadcn/ui Typography Classes** — ready-to-use className strings for headings, body, and special elements (blockquote, code, overline). Customize values to match the calculated scale.
|
|
296
|
+
- **Vertical Rhythm** — grid unit, body line-height as spacing anchor, spacing token table (space-xs through space-2xl) with values, lines, and usage. Include CSS `lh`/`rlh` unit examples.
|
|
297
|
+
- **Weights** — table mapping Regular/Medium/Semibold/Bold to values and usage.
|
|
298
|
+
- **Accessibility** — WCAG 2.2 AA compliance notes: body line-height ≥ 1.5, zoom survival, minimum text size, max line length. SC 1.4.12 resilience note.
|
|
299
|
+
- **Variable Font Notes** — conditional section: optical sizing, dark mode grade adjustment, precise weight control.
|
|
300
|
+
- **Modern CSS Enhancements** — `text-wrap: balance` for headings, `text-wrap: pretty` for paragraphs.
|
|
301
|
+
- **Related** — links to companion files.
|
|
421
302
|
|
|
422
303
|
## Step 7: Write CSS output
|
|
423
304
|
|
|
@@ -425,201 +306,24 @@ p { text-wrap: pretty; } /* Avoid orphans in paragraphs */
|
|
|
425
306
|
|
|
426
307
|
Write `{OUTPUT_PATH}/tailwind.typography.css` — extends Tailwind v4 via `@theme` with the calculated scale. Drop into your project and import in `globals.css`:
|
|
427
308
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
/* ─── Tailwind v4 theme extension ─── */
|
|
438
|
-
@theme {
|
|
439
|
-
/* Font families */
|
|
440
|
-
--font-sans: '{primary}', ui-sans-serif, system-ui, sans-serif;
|
|
441
|
-
--font-mono: '{mono}', ui-monospace, 'SFMono-Regular', monospace;
|
|
442
|
-
|
|
443
|
-
/* Custom font size tokens (extend Tailwind's built-in scale) */
|
|
444
|
-
--text-display: {display rem}rem;
|
|
445
|
-
--text-display--line-height: {display lh};
|
|
446
|
-
--text-display--letter-spacing: -0.025em;
|
|
447
|
-
--text-display--font-weight: {heading weight};
|
|
448
|
-
|
|
449
|
-
--text-h1: {h1 rem}rem;
|
|
450
|
-
--text-h1--line-height: {h1 lh};
|
|
451
|
-
--text-h1--letter-spacing: -0.025em;
|
|
452
|
-
--text-h1--font-weight: {heading weight};
|
|
453
|
-
|
|
454
|
-
--text-h2: {h2 rem}rem;
|
|
455
|
-
--text-h2--line-height: {h2 lh};
|
|
456
|
-
--text-h2--letter-spacing: -0.025em;
|
|
457
|
-
--text-h2--font-weight: {heading weight};
|
|
458
|
-
|
|
459
|
-
--text-h3: {h3 rem}rem;
|
|
460
|
-
--text-h3--line-height: {h3 lh};
|
|
461
|
-
--text-h3--letter-spacing: -0.015em;
|
|
462
|
-
--text-h3--font-weight: 600;
|
|
463
|
-
|
|
464
|
-
--text-h4: {h4 rem}rem;
|
|
465
|
-
--text-h4--line-height: {h4 lh};
|
|
466
|
-
--text-h4--letter-spacing: -0.01em;
|
|
467
|
-
--text-h4--font-weight: 600;
|
|
468
|
-
|
|
469
|
-
--text-body-large: {body-large rem}rem;
|
|
470
|
-
--text-body-large--line-height: {body-large lh};
|
|
471
|
-
|
|
472
|
-
--text-overline: {overline rem}rem;
|
|
473
|
-
--text-overline--line-height: {overline lh};
|
|
474
|
-
--text-overline--letter-spacing: 0.1em;
|
|
475
|
-
--text-overline--font-weight: 600;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
/* ─── Fluid type (clamp) ─── */
|
|
479
|
-
:root {
|
|
480
|
-
--fs-display: clamp({display min}rem, {display intercept}rem + {display slope}vw, {display max}rem);
|
|
481
|
-
--fs-h1: clamp({h1 min}rem, {h1 intercept}rem + {h1 slope}vw, {h1 max}rem);
|
|
482
|
-
--fs-h2: clamp({h2 min}rem, {h2 intercept}rem + {h2 slope}vw, {h2 max}rem);
|
|
483
|
-
--fs-h3: clamp({h3 min}rem, {h3 intercept}rem + {h3 slope}vw, {h3 max}rem);
|
|
484
|
-
--fs-h4: clamp({h4 min}rem, {h4 intercept}rem + {h4 slope}vw, {h4 max}rem);
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
/* ─── Typography utility classes ─── */
|
|
488
|
-
/* Use these or compose with Tailwind's built-in classes */
|
|
489
|
-
|
|
490
|
-
.text-display {
|
|
491
|
-
font-size: var(--fs-display);
|
|
492
|
-
line-height: {display lh};
|
|
493
|
-
letter-spacing: -0.025em;
|
|
494
|
-
font-weight: {heading weight};
|
|
495
|
-
text-wrap: balance;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
.prose-headings h1, .text-h1 {
|
|
499
|
-
font-size: var(--fs-h1);
|
|
500
|
-
line-height: {h1 lh};
|
|
501
|
-
letter-spacing: -0.025em;
|
|
502
|
-
font-weight: {heading weight};
|
|
503
|
-
text-wrap: balance;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
.prose-headings h2, .text-h2 {
|
|
507
|
-
font-size: var(--fs-h2);
|
|
508
|
-
line-height: {h2 lh};
|
|
509
|
-
letter-spacing: -0.025em;
|
|
510
|
-
font-weight: 600;
|
|
511
|
-
text-wrap: balance;
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
.prose-headings h3, .text-h3 {
|
|
515
|
-
font-size: var(--fs-h3);
|
|
516
|
-
line-height: {h3 lh};
|
|
517
|
-
letter-spacing: -0.015em;
|
|
518
|
-
font-weight: 600;
|
|
519
|
-
text-wrap: balance;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
.prose-headings h4, .text-h4 {
|
|
523
|
-
font-size: var(--fs-h4);
|
|
524
|
-
line-height: {h4 lh};
|
|
525
|
-
letter-spacing: -0.01em;
|
|
526
|
-
font-weight: 600;
|
|
527
|
-
text-wrap: balance;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
.text-body-large {
|
|
531
|
-
font-size: {body-large rem}rem;
|
|
532
|
-
line-height: {body-large lh};
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
.text-overline {
|
|
536
|
-
font-size: {overline rem}rem;
|
|
537
|
-
line-height: {overline lh};
|
|
538
|
-
letter-spacing: 0.1em;
|
|
539
|
-
font-weight: 600;
|
|
540
|
-
text-transform: uppercase;
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
/* ─── Optical sizing + dark mode (variable fonts) ─── */
|
|
544
|
-
body {
|
|
545
|
-
font-optical-sizing: auto;
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
@media (prefers-color-scheme: dark) {
|
|
549
|
-
body {
|
|
550
|
-
/* Reduce apparent weight for light-on-dark text */
|
|
551
|
-
-webkit-font-smoothing: antialiased;
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
/* ─── Modern CSS enhancements ─── */
|
|
556
|
-
h1, h2, h3, h4, h5, h6 { text-wrap: balance; }
|
|
557
|
-
p { text-wrap: pretty; }
|
|
558
|
-
```
|
|
309
|
+
The CSS file must include these sections, using calculated values from Step 3:
|
|
310
|
+
|
|
311
|
+
- **Header comment** — font family, ratio name, date, import instruction
|
|
312
|
+
- **Font imports** — Google Fonts `@import url()` for primary + mono families
|
|
313
|
+
- **Tailwind v4 @theme extension** — `--font-sans`, `--font-mono` families, plus custom `--text-{level}` tokens for Display, H1-H4, body-large, overline (each with `--line-height`, `--letter-spacing`, `--font-weight` sub-tokens)
|
|
314
|
+
- **Fluid type custom properties** — `:root` block with `--fs-display` through `--fs-h4` using `clamp()` (rem-based min/max, never pure vw — required for WCAG 1.4.4 zoom compliance)
|
|
315
|
+
- **Typography utility classes** — `.text-display`, `.text-h1` through `.text-h4`, `.text-body-large`, `.text-overline` with corresponding font-size (using fluid var), line-height, letter-spacing, font-weight, and `text-wrap: balance` for headings
|
|
316
|
+
- **Optical sizing + dark mode** — `font-optical-sizing: auto`, dark mode antialiasing
|
|
317
|
+
- **Modern CSS** — `text-wrap: balance` on headings, `text-wrap: pretty` on paragraphs
|
|
559
318
|
|
|
560
319
|
### Vanilla mode (`--vanilla`)
|
|
561
320
|
|
|
562
321
|
If `--vanilla` flag is set, write `{OUTPUT_PATH}/typescale.css` instead — plain CSS custom properties without Tailwind-specific syntax:
|
|
563
322
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
@import url('https://fonts.googleapis.com/css2?family={primary}:wght@{weights}&family={mono}:wght@400;700&display=swap');
|
|
569
|
-
|
|
570
|
-
:root {
|
|
571
|
-
/* Font families */
|
|
572
|
-
--font-primary: '{primary}', {fallback stack};
|
|
573
|
-
--font-secondary: '{secondary or primary}', {fallback stack};
|
|
574
|
-
--font-mono: '{mono}', ui-monospace, monospace;
|
|
575
|
-
|
|
576
|
-
/* Font weights */
|
|
577
|
-
--fw-regular: {body weight};
|
|
578
|
-
--fw-medium: 500;
|
|
579
|
-
--fw-semibold: 600;
|
|
580
|
-
--fw-bold: {heading weight};
|
|
581
|
-
|
|
582
|
-
/* Type scale — fluid */
|
|
583
|
-
--fs-display: clamp({...});
|
|
584
|
-
--fs-h1: clamp({...});
|
|
585
|
-
--fs-h2: clamp({...});
|
|
586
|
-
--fs-h3: clamp({...});
|
|
587
|
-
--fs-h4: clamp({...});
|
|
588
|
-
--fs-body-large: {rem}rem;
|
|
589
|
-
--fs-body: {base}rem;
|
|
590
|
-
--fs-body-small: {rem}rem;
|
|
591
|
-
--fs-caption: {rem}rem;
|
|
592
|
-
--fs-overline: {rem}rem;
|
|
593
|
-
|
|
594
|
-
/* Line heights (4px grid-snapped) */
|
|
595
|
-
--lh-display: {value};
|
|
596
|
-
--lh-h1: {value};
|
|
597
|
-
--lh-h2: {value};
|
|
598
|
-
--lh-h3: {value};
|
|
599
|
-
--lh-h4: {value};
|
|
600
|
-
--lh-body-large: {value};
|
|
601
|
-
--lh-body: {value};
|
|
602
|
-
--lh-body-small: {value};
|
|
603
|
-
--lh-caption: {value};
|
|
604
|
-
--lh-overline: {value};
|
|
605
|
-
|
|
606
|
-
/* Letter spacing */
|
|
607
|
-
--ls-display: -0.025em;
|
|
608
|
-
--ls-h1: -0.025em;
|
|
609
|
-
--ls-h2: -0.025em;
|
|
610
|
-
--ls-h3: -0.015em;
|
|
611
|
-
--ls-h4: -0.01em;
|
|
612
|
-
--ls-body-large: 0;
|
|
613
|
-
--ls-body: 0;
|
|
614
|
-
--ls-body-small: 0.01em;
|
|
615
|
-
--ls-caption: 0.015em;
|
|
616
|
-
--ls-overline: 0.1em;
|
|
617
|
-
|
|
618
|
-
/* Vertical rhythm */
|
|
619
|
-
--grid-unit: {grid}px;
|
|
620
|
-
--space-line: {body lh}px;
|
|
621
|
-
}
|
|
622
|
-
```
|
|
323
|
+
Plain CSS custom properties (no Tailwind syntax). Include:
|
|
324
|
+
|
|
325
|
+
- **Font imports** — Google Fonts `@import`
|
|
326
|
+
- **:root custom properties** — font families (`--font-primary`, `--font-secondary`, `--font-mono`), font weights (`--fw-regular` through `--fw-bold`), fluid font sizes (`--fs-display` through `--fs-overline` with clamp() for headings, rem-based min/max only — never pure vw per WCAG 1.4.4), line heights (`--lh-display` through `--lh-overline`, 4px grid-snapped), letter spacing (`--ls-display` through `--ls-overline`), vertical rhythm (`--grid-unit`, `--space-line`)
|
|
623
327
|
|
|
624
328
|
## Step 8: Completion output
|
|
625
329
|
|