Skip to content
Navigation

Typography

Which text style each UI role gets — and when numbers switch to mono. Prose recipes live in the `typography` export; this doc covers app screens.

Two layers

  • Prose — document-like content (long descriptions, legal text, rendered markdown): use the shared recipes from @stroeer-labs/design-library/typography (typography.h1 … typography.muted) verbatim.
  • UI chrome — screens, cards, dialogs, forms: the role recipes below. UI headings are smaller and quieter than the prose scale — never apply typography.h1 to an app screen title.

Roles

  • Page title — text-3xl font-bold tracking-tight (up to sm:text-4xl on hero/status screens); embedded or secondary page headers step down to text-2xl font-semibold leading-tight. (Existing code mixes the two weights within one tier — follow this split, don’t copy the code.)
  • Section title — text-lg font-semibold in dense dashboards, text-xl font-semibold in roomier layouts. No tracking-tight at this size.
  • Card title — the component default (text-base font-medium). Don’t override casually; cards are quiet.
  • Dialog title — the component default (font-medium, inherited size).
  • Body / secondary text — text-sm text-muted-foreground (the most common secondary-text pattern).
  • Caption / meta — text-xs text-muted-foreground.
  • Form label — the component default (text-sm font-medium).

Numbers and machine data

  • Prices, budgets, counts (contacts, impressions), quantities → font-mono tabular-nums, font-semibold when emphasized. Tabular figures are mandatory so digits hold their column and don’t jitter on live updates.
  • Codes, IDs, voucher codes, links, step numbers → font-mono (inside <code> where it is semantically a code).
  • Numeric table columns keep tabular-nums even when they stay font-sans.
  • Dates and times stay font-sans. Mono marks amounts, counts and codes — not every string that happens to contain digits.
  • Never mono for prose, headings, labels or button text. Mono is a token (font-mono → Martian Mono) — never hardcode a font family.

Never

  • Ad-hoc pixel sizes (text-[22px], text-[12.5px]) — stay on the --text-* scale. If a step is genuinely missing, raise it against the bridge instead of inlining pixels. (Existing code violates this in places — don’t copy those.)
  • Tailwind’s gray palette (text-gray-600) — color comes from tokens (text-muted-foreground, text-foreground).
  • Hand-rolling a heading style per file — pick a role above so screens agree.
  • The type scale itself (--text-*) is owned in tailwind-bridge.css; fonts are tokens (font-sans → Hanken Grotesk, font-mono → Martian Mono).
  • docs/patterns/copy.md — what the text says: voice, casing, labels, error messages.
  • docs/patterns/forms.md — label and error text sit within these roles.