Typography
Six components over one scale. Two faces: the display font for headings, the reading font for everything else. Sizes are px throughout, because the old guide’s rems were on a 10px root and converting them by hand is how a 36px heading becomes 3.6rem of something else.
import { Header, SubHeader, Text, Caption, MetaText, Quote } from '@/components/ui/Typography';Source: src/components/ui/Typography.tsx
Examples
Header — page and band titles
Renders an <h1> by default. Change the LEVEL with `as` and the SIZE with `size`: they are separate on purpose, because the right heading level is a document-structure question and the right size is a visual one, and tying them together forces you to break one to get the other.
Header lg
Header md — the default
Header sm
weight="bold"
weight="black"
SubHeader — section titles
An <h2> by default, one step down the display scale.
SubHeader lg
SubHeader md
SubHeader sm
SubHeader sm bold
Text, Caption, MetaText, Quote
Text is body copy — a <p> by default. Caption is 12px and muted (`muted={false}` when it needs full contrast). MetaText labels a value. Quote pulls a sentence out without being a blockquote.
Text lg — 18px, an intro paragraph
Text md — 16px, the default body size
Text sm — 14px, dense copy
Text bold
Text italic
Caption — 12px, muted by defaultCaption with muted={false}MetaText — a label beside a valueQuote — a pulled sentence
Level and size are independent
A section’s second-level heading that should look small is `<SubHeader as="h2" size="sm">`. Never pick the wrong level to get the right size — the heading outline is what a screen reader navigates by.
as="h2" size="sm"
as="span" — inline, no paragraph breakProps
<Header> props
| Prop | Type | Default | Description |
|---|---|---|---|
size | 'sm' | 'md' | 'lg' | 'md' | — |
weight | 'regular' | 'bold' | 'black' | 'regular' | — |
asfrom TypeProps | ElementType | 'h1' | — |
italicfrom TypeProps | boolean | false | — |
classNamefrom TypeProps | string | '' | — |
childrenrequiredfrom TypeProps | ReactNode | — | — |
Also accepts everything in HTMLAttributes<HTMLElement> — so native attributes (id, onClick, aria-*, data-*) pass straight through.
<SubHeader> props
| Prop | Type | Default | Description |
|---|---|---|---|
size | 'sm' | 'md' | 'lg' | 'md' | — |
weight | 'regular' | 'bold' | 'black' | 'regular' | — |
asfrom TypeProps | ElementType | 'h2' | — |
italicfrom TypeProps | boolean | false | — |
classNamefrom TypeProps | string | '' | — |
childrenrequiredfrom TypeProps | ReactNode | — | — |
Also accepts everything in HTMLAttributes<HTMLElement> — so native attributes (id, onClick, aria-*, data-*) pass straight through.
<Text> props
| Prop | Type | Default | Description |
|---|---|---|---|
size | 'sm' | 'md' | 'lg' | 'md' | — |
bold | boolean | false | — |
asfrom TypeProps | ElementType | 'p' | — |
italicfrom TypeProps | boolean | false | — |
classNamefrom TypeProps | string | '' | — |
childrenrequiredfrom TypeProps | ReactNode | — | — |
Also accepts everything in HTMLAttributes<HTMLElement> — so native attributes (id, onClick, aria-*, data-*) pass straight through.
<Caption> props
| Prop | Type | Default | Description |
|---|---|---|---|
muted | boolean | true | — |
asfrom TypeProps | ElementType | 'span' | — |
italicfrom TypeProps | boolean | — | — |
classNamefrom TypeProps | string | '' | — |
childrenrequiredfrom TypeProps | ReactNode | — | — |
Also accepts everything in HTMLAttributes<HTMLElement> — so native attributes (id, onClick, aria-*, data-*) pass straight through.
<MetaText> props
| Prop | Type | Default | Description |
|---|---|---|---|
size | 'sm' | 'md' | 'lg' | 'md' | — |
asfrom TypeProps | ElementType | 'span' | — |
italicfrom TypeProps | boolean | — | — |
classNamefrom TypeProps | string | '' | — |
childrenrequiredfrom TypeProps | ReactNode | — | — |
Also accepts everything in HTMLAttributes<HTMLElement> — so native attributes (id, onClick, aria-*, data-*) pass straight through.
<Quote> props
| Prop | Type | Default | Description |
|---|---|---|---|
size | 'sm' | 'md' | 'lg' | 'md' | — |
italicfrom TypeProps | boolean | false | — |
classNamefrom TypeProps | string | '' | — |
childrenrequiredfrom TypeProps | ReactNode | — | — |
Also accepts everything in HTMLAttributes<HTMLElement> — so native attributes (id, onClick, aria-*, data-*) pass straight through.
Accessibility
- One <h1> per page. Every page in this catalog puts it on the component name.
- Heading levels must not skip: h1 → h3 leaves a hole in the outline a screen reader reads as a missing section.
Usage
Do
- Pick the level for the document outline, then the size for the design.
- Use Caption for metadata; it is already grey-600, the lightest grey allowed for text.
Don’t
- Don’t skip heading levels to get a size — pass `size` instead.
- Don’t set font sizes with utility classes on top of these; the scale exists so two pages agree.
- Don’t use grey-400 for anything readable — 2.60:1 on white, and it fails AA.