Skip to content

fix(ui): typography overrides replace defaults instead of appending#1417

Merged
ssilvius merged 3 commits intomainfrom
fix/typography-classy-override
Apr 24, 2026
Merged

fix(ui): typography overrides replace defaults instead of appending#1417
ssilvius merged 3 commits intomainfrom
fix/typography-classy-override

Conversation

@ssilvius
Copy link
Copy Markdown
Collaborator

Summary

Token props on typography (color, size, weight, line, tracking, family, align, transform) now replace the matching default dimension at emit time instead of appending on top of a flat default string.

Tailwind v4 orders utilities alphabetically in generated CSS, so the cascade cannot be trusted for overrides:

  • text-accent would lose to default text-foreground (a < f)
  • text-2xl override would lose to default text-4xl
  • @lg:text-5xl CQ defaults survived bare size overrides

Audited the other 50+ UI components -- they're fine because they use map-lookup replacement patterns (variantClasses[v], sizeClasses[s]) rather than flat-string append. Typography was the outlier because its props are free-form dimensions (not enum variants) and went through tokenPropsToClasses which appended.

Approach

  • typography.classes.ts: variant defaults stored dimensionally (size, weight, color, line, tracking, family, align, transform + optional layout extras + cq responsive overrides), resolved via resolveTypography(variant, props).
  • Resolver reads overrides[key] ?? defaults[key] per dimension and emits utilities through a single DIM_TO_UTIL map -- one source of truth for the dimension-to-Tailwind mapping.
  • emitProps shared primitive handles both the base emit and the CQ-prefixed emit; tokenPropsToClasses is a one-line wrapper kept as a test-only entry point.
  • CQ variants survive only where the matching dimension isn't overridden (so size="2xl" correctly drops @lg:text-5xl).
  • typographyClasses flat-string export preserved for consumers that don't take token props (List's li, CodeBlock wrapper), computed from the dimensional defaults.
  • All React + Astro typography components switched to resolveTypography. Missing align/transform destructures added to React variants for parity with Astro.
  • classy unchanged.
  • One-line .gitignore chore adds .scratch/ so scratchwork doesn't gate pushes via biome.

Test plan

  • pnpm --filter=@rafters/ui test typography -- 288 tests pass
  • Full @rafters/ui suite -- 4907 pass, 6 pre-existing skips
  • Typecheck + lint + preflight green
  • Override-replaces-default asserted for color, size, weight
  • CQ variant survives when the matching dimension is not overridden

ssilvius and others added 3 commits April 23, 2026 22:21
Token props (color, size, weight, line, tracking, family, align, transform)
now replace the matching default dimension at emit time instead of appending
on top of a flat default string. Tailwind v4 orders utilities alphabetically
in generated CSS, so cascade order could not be trusted: e.g. `text-accent`
would lose to `text-foreground` (a < f), `text-4xl` would beat a smaller
override like `text-2xl`, and `@lg:text-5xl` CQ defaults would survive a
bare size override.

Variant defaults in typography.classes.ts are now stored dimensionally and
resolved via resolveTypography(variant, props), which merges non-null
overrides into the defaults and emits utilities through a single
DIM_TO_UTIL map. CQ variants are kept only when the matching dimension is
not overridden. typographyClasses flat-string export is preserved (computed
from the dimensional defaults) for back-compat with the few remaining
consumers that do not take token props (li, codeblock, lists).

All React + Astro typography components switched to resolveTypography.
Missing align/transform destructures added to React variants for parity
with Astro.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Scratch notes and prototype dumps belong outside version control and
shouldn't gate pushes via biome. Matches the intent of the directory name.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- emitProps shared primitive used by both resolveTypography and
  tokenPropsToClasses, with a prefix parameter reused for CQ emit
- resolveTypography reads overrides[key] ?? defaults[key] directly per
  dimension instead of pickDefined + object spread + delete
- tokenPropsToClasses comment says what it's for (test helper) instead of
  narrating the previous change

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ssilvius ssilvius merged commit f374bdd into main Apr 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant