Typography
Token-driven, theme-aware text with semantic roles.
Pick a semantic variant and Typography renders with the right size, line
height, weight, letter spacing, and font for the active theme — all from the
--cajon-type-* tokens, so switching themes or toggling dark mode restyles every
piece of text at once. No hand-authored font rules.
Variants
Typography uses a category × size matrix — four families on a T-shirt-size ladder, plus a focused Mono family for code and technical surfaces (23 roles total):
| Family | Sizes | Use |
|---|---|---|
display-* | lg · md · sm · xs | Oversized hero / marketing type |
heading-* | xxl · xl · lg · md · sm · xs | Document headings, largest to smallest |
label-* | lg · md · sm · xs · 2xs | UI labels, buttons, eyebrows, overlines (label-xs/label-2xs are uppercased; 2xs ≈ 10px for dense badges/counters) |
paragraph-* | lg · md · sm · xs · 2xs | Body copy and captions (paragraph-2xs ≈ 10px micro-text) |
mono-* | display-md · label-md · label-sm · paragraph-md · paragraph-sm | Code, data, technical readouts |
Heading sizes map to document heading levels by default (heading-xxl → h1 …
heading-xs → h6); Display is presentational and renders a div. Use as to
override the rendered element.
The legacy roles (display, h1–h6, subtitle1/subtitle2,
body1/body2, caption, overline) remain available unchanged for
back-compat — body1 is still the default variant.
import { Typography } from '@cajon-ui/react';
<Typography variant="heading-xxl">Page title</Typography>
<Typography>Body copy uses body1 by default.</Typography>
// keep the heading style, but render a <span> for inline use:
<Typography variant="heading-xl" as="span">Inline heading-styled text</Typography>
// a hero display that is also the page heading:
<Typography variant="display-lg" as="h1">Welcome</Typography>as swaps the rendered element but does not narrow its prop types — props
are typed as HTMLAttributes<HTMLElement>, so element-specific attributes
(e.g. href on as="a") require a cast. This is intentional for v1.
Tone, weight, alignment, truncation
tone recolors the text; weight overrides the role's default weight; align
sets text alignment; truncate clips to a single line with an ellipsis.
tone="primary" is the default and emits no class — the text inherits the base
color, so it shows through a colored parent rather than forcing the theme's
primary text color. Pass an explicit tone (including a deliberate
tone="inverse" on dark surfaces) to pin the color.
<Typography tone="muted">Secondary information</Typography>
<Typography variant="h3" weight="regular">Lighter heading</Typography>
<Typography align="center">Centered</Typography>
<Typography truncate>A very long line that clips…</Typography>Serif
Pass font="serif" to render any role in the brand serif (--cajon-font-serif,
Source Serif 4 on the Codazen themes) — an orthogonal family override that
composes with any variant, for editorial or long-form surfaces such as
AI/agent messages.
<Typography variant="body1" font="serif">A serif paragraph.</Typography>
<Typography variant="h2" font="serif">A serif heading</Typography>The bundled Source Serif 4 ships weights 400/500/600 only — font="serif" with
weight="bold" (700) or italic text is browser-synthesized from the nearest cut.
Props
| Prop | Type | Default | Notes |
|---|---|---|---|
variant | matrix role (display-*, heading-*, label-*, paragraph-*, mono-*) or a legacy role | body1 | Semantic type role — see Variants |
as | ElementType | per-variant | Override the rendered element or component |
tone | primary | secondary | muted | inverse | link | success | warning | error | info | primary | Text color |
weight | regular | medium | semibold | bold | role default | Override font weight |
align | left | center | right | — | Text alignment |
truncate | boolean | false | Single-line ellipsis |
font | serif | — | Override the role's font family with the brand serif |
All other native attributes pass through to the rendered element; the component
forwards its ref.