Typography
The type system and its showcase page at /ui/typography — the heading scale, body/article text, the type-scale reference table, and the skin-aware font utilities (.font-display, .font-data, .font-numeral) that read the --font- tokens so type re-skins with the active design and localizes for CJK languages.
Overview
Typography in Luminaux is token-driven, exactly like color. Three CSS custom properties define the
faces (--font-sans, --font-display, --font-mono), three utility classes expose them
(.font-display, .font-data, .font-numeral), and everything else uses Tailwind's built-in type scale
(text-xs … text-4xl, font-*, tracking-*, leading-*). Because the faces are tokens, a skin or a
full design (Bento, Console) can swap the display/mono faces, and a language (Japanese, Chinese)
can swap the whole stack — with no component changes.
/ui/typography (src/pages/ui/TypographyPage.tsx) is the live reference for this system: it renders the
heading scale, display type, body copy, lists, a long-form article sample, the font faces each skin uses,
and a type-scale table. It's a showcase, not a reusable component — the reusable parts are the tokens
and the three utilities documented here.
Architecture & files
| File | Responsibility |
|---|---|
src/styles/index.css | Defines --font-sans / --font-display / --font-mono (base + skin + html[lang] overrides) and the .font-display / .font-data / .font-numeral utilities. |
src/pages/ui/TypographyPage.tsx | The /ui/typography showcase — HEADINGS and SCALE data arrays + the section panels. |
src/styles/_skin-*.scss | Per-design font overrides (e.g. Console → JetBrains Mono, Bento keeps the default display face). |
index.html | Loads the web fonts (Plus Jakarta Sans, Inter, JetBrains Mono; Noto Sans JP/SC on demand for CJK). |
src/locales/<lng>/demo.json | The showcase page's section labels + sample copy (typography* keys). |
Usage
Use Tailwind's type utilities for size/weight/spacing, and the three font utilities when you need a specific face:
// A display heading (uses the skin's display face)
<h2 className="font-display text-2xl font-bold tracking-tight text-foreground">Revenue</h2>
// A numeric readout with column-aligned digits
<span className="font-data text-lg text-foreground">$48,290.00</span>
// Body copy inherits --font-sans automatically — no utility needed
<p className="text-sm text-muted-foreground">Standard body text.</p>API / Props
Font tokens
Defined in src/styles/index.css and mapped into Tailwind via @theme inline:
| Token | Base value (default skin) | Purpose |
|---|---|---|
--font-sans | Plus Jakarta Sans, system fallbacks | The base UI font — applied to <body>. |
--font-display | Inter, system fallbacks | Headings / display text; skins may override. |
--font-mono | JetBrains Mono / ui-monospace fallbacks | Monospace / numeric-data readouts. |
Font utilities
| Utility | Maps to | Use for |
|---|---|---|
.font-display | var(--font-display) | Headings / display text. Follows the active skin's display face. |
.font-data | var(--font-mono) + tabular-nums + tight letter-spacing | Numeric/data readouts where digits must align in columns (KPI values, tables). |
.font-numeral | JetBrains Mono (fixed, skin-independent) | Oversized numerals that must stay monospace regardless of skin (e.g. error-page status codes). |
The type scale
The /ui/typography scale table (SCALE in TypographyPage.tsx) documents the sizes the template uses,
via Tailwind's default scale:
| Class | Size | Typical use |
|---|---|---|
text-xs | 12px | Captions, meta labels |
text-sm | 14px | Body / UI default |
text-base | 16px | Long-form reading |
text-lg | 18px | Leads / subheads |
text-2xl | 24px | Section titles |
text-4xl | 36px | Hero / page titles |
Weights and tracking follow Tailwind (font-medium/font-semibold/font-bold, tracking-tight on
large display text). No custom scale config is needed — Tailwind v4 is config-less here.
Configuration & customization
Per-skin & per-design fonts
A color skin is token-only and normally keeps the default faces. A full design may also swap
fonts: Console uses JetBrains Mono throughout (tight radius, terminal feel), while Bento keeps the
default display face. These overrides live in the design's _skin-*.scss partial (or the skin block in
index.css) by redefining --font-display / --font-mono under the [data-skin="…"] selector. See
Design Skins.
CJK language overrides
For Japanese and Chinese, the entire font stack swaps to a CJK face so glyphs render correctly, via
html[lang] overrides in index.css:
html[lang="ja"] { --font-sans: 'Noto Sans JP', 'Plus Jakarta Sans', ui-sans-serif, system-ui, sans-serif; /* + display/mono */ }
html[lang="zh"] { --font-sans: 'Noto Sans SC', 'Plus Jakarta Sans', ui-sans-serif, system-ui, sans-serif; /* + display/mono */ }All other languages keep the default faces. The CJK subsets download on demand. See i18n.
The showcase page sections
/ui/typography presents these sections (each a Panel with a title + description):
| Section | Shows |
|---|---|
| Headings | The heading scale (HEADINGS data) with size badges. |
| Display | Large .font-display display type. |
| Motion text | The animated-text FX (Typewriter, ScrambleText, RotatingWord) applied to type. |
| Body | Paragraph copy, inline code, emphasis. |
| Lists | Ordered / unordered list styling. |
| Article | A long-form article sample (h1/h2 + paragraphs) for reading rhythm. |
| Fonts | The .font-display and .font-data faces the active skin resolves to. |
| Scale | The type-scale reference table (SCALE). |
Examples
A KPI tile mixing display and data faces (values stay column-aligned across rows):
<div className="rounded-xl border border-border bg-surface p-4">
<p className="text-xs text-muted-foreground">Monthly revenue</p>
<p className="font-data text-2xl font-semibold text-foreground">$48,290.00</p>
<p className="font-display text-sm text-muted-foreground">vs last month</p>
</div>An oversized status numeral that must stay monospace regardless of skin (error pages):
<span className="font-numeral text-[8rem] leading-none text-primary">404</span>Best practices
- Never hardcode a font family in a component — use
.font-display/.font-data/.font-numeralor the--font-*tokens, so type re-skins and localizes automatically. - Use
.font-datafor numbers in tables/KPIs so digits align (tabular-nums). - Reserve
.font-numeralfor the rare case where a numeral must stay monospace even when a skin overrides--font-mono. - Size with Tailwind's scale (
text-*,font-*,tracking-*); don't introduce custom pixel sizes. - Color type with tokens (
text-foreground,text-muted-foreground) — never raw palette or hex.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Headings don't change with the Console design | Hardcoded font family instead of .font-display | Use the utility / --font-display |
| Numbers misalign in a table | Using the default sans instead of .font-data | Apply .font-data to numeric cells |
| Japanese text renders with tofu / wrong glyphs | html[lang] not set, or Noto font not loaded | Ensure the language switch sets <html lang> (it does via i18n) |
| A numeral changed face under a skin | Used .font-data where you meant skin-independent | Use .font-numeral for fixed-monospace numerals |
FAQ
Why is /ui/typography not a reusable component? It's a showcase of the type system. The reusable
pieces are the tokens and the three utilities — those are what you compose in real pages.
Can I add a font weight or face? Load it in index.html and point a --font-* token (or a skin's
override) at it. Keep it in the token layer so skins/CJK stay consistent.
Where does the showcase copy live? In the demo i18n namespace (typography* keys in
src/locales/<lng>/demo.json).
Notes for designers & content editors
- Faces are tokens. Change
--font-sans/--font-display/--font-monoinsrc/styles/index.css(or a skin block) — never inline afont-familyin a component. - Sample copy on the showcase page is i18n text (
demo:typography*), safe to edit; letterform specimens and font names stay literal. - CJK is handled automatically per
<html lang>— you don't add per-string overrides.
Related
Core & Feedback components
the broader UI primitives (this page expands its Typography subsection)
Design tokens & dark mode
where the --font- tokens are defined
Design Skins
per-skin / per-design font overrides (Console, Bento)
Internationalization
CJK font stacks + html[lang] overrides
Animation & Effects
the animated-text FX demoed on the page
Was this page helpful?
