Typography tokens

Tostada treats typography the same way it treats colors: a small primitive layer carries raw values; a semantic layer composes those primitives into named roles; every atom reads CSS variables, never hard-coded strings.

The model

font-family-* (primitive)  ─┐
                            ├─►  typography-* (semantic, composes 2 primitives)  ─►  atoms (--typography-<role>-{family,size,weight,line-height,...})
font-size-*   (primitive)  ─┘

A primitive holds a single CSS-ready value:

  • font-family-heading = 'Inter', sans-serif
  • font-size-md = 1rem

A semantic typography token references one primitive of each kind plus weight, line-height, and (optionally) letter-spacing / font-style / text-transform / text-decoration. The 11 semantic roles that ship with every library:

Role Default family Default size Weight Application rule
typography-display heading 3xl 700 Hero headlines and marketing moments only. Max one per page.
typography-heading heading 2xl 700 The page's primary title (h1). One per page.
typography-subheading heading xl 600 Major section titles within a page (h2).
typography-title heading lg 600 Sub-section, card, and block titles (h3–h4).
typography-body body md 400 Default for all paragraph and prose text.
typography-body-emphasis body md 600 Inline emphasis inside paragraphs, lead-in sentences, key terms.
typography-caption body sm 400 Image captions, helper text under form inputs, footnotes.
typography-label body sm 500 Form labels, table column headers, small UI labels.
typography-button body md 600 Button and link text inside interactive controls.
typography-code code md 400 Monospace, inline and block code.
typography-micro body xs 400 Smallest readable text: legal fine print, badge text.

Editing typography

PrimitivesLibrary → Typography → Primitives:

  • Edit any family by clicking Edit font: the picker covers the bundled Google Fonts catalog (54 families) and four system stacks. Selecting a Google Font loads it via <link> and rejects with an inline error if the network blocks it.
  • Edit individual sizes inline, or click Generate scale to regenerate the whole xs..3xl ladder from a base + ratio. Quick-picks: 1.2, 1.25, 1.333, 1.414, 1.5.
  • + Add font family / + Add font size appends new primitives.
  • Deleting a primitive that semantic tokens reference opens a reassign modal — pick a replacement before the delete proceeds. The last primitive of either kind can't be removed.

SemanticLibrary → Typography → Semantic:

  • Click any row to expand the editor (accordion: only one open at a time).
  • Family/size dropdowns over the existing primitives. Weight + line-height inputs.
  • Add property progressively reveals optional facets (letter-spacing, font-style, text-transform, text-decoration) — keeps the editor uncluttered for the common case.

How atoms consume typography

Every atom reads CSS variables, never strings. After any edit the injected :root { ... } block (and the exported tokens.css) carries:

/* primitives */
--font-family-body: 'Inter', sans-serif;
--font-size-md: 1rem;

/* semantic — one block per role, only set facets are emitted */
--typography-body-family: 'Inter', sans-serif;
--typography-body-size: 1rem;
--typography-body-weight: 400;
--typography-body-line-height: 1.5;

The preview-host iframe additionally aliases the typography primitives onto Tailwind v4's --font-sans, --font-mono, and --text-* variables, so utilities like text-sm or font-mono pick up the user's library automatically without any changes to the components themselves.

Application rules

Each semantic token carries its application rule in the usage.purpose field — the same field that already documents color tokens. That copy travels with the token through design-system.md exports and is consumed by the Spread + AI flows when applying the design system to new pages.

Related