ReferenceTypography tokens
Use pre-composed text styles. Let fluid type handle responsiveness. Pair semantic colours with semantic HTML.
Roadie has two font families: Intermission, a sans-serif set with
font-sans, and IBM Plex Mono, a monospace set with font-mono.
Sizes from text-lg up use clamp() to scale fluidly between viewport
widths, so they need no breakpoint overrides. On the docs site, each step is
set in its own size, with its size in pixels or its fluid range.
xsThe quick brown fox
12pxsmThe quick brown fox
14pxbaseThe quick brown fox
16pxlgThe quick brown fox
18 to 20pxxlThe quick brown fox
20 to 24px2xlThe quick brown fox
24 to 32px3xlThe quick brown fox
28 to 40px4xlThe quick brown fox
32 to 48px5xlThe quick brown fox
36 to 64px6xlThe quick brown fox
40 to 76px7xlThe quick brown fox
44 to 96pxPre-composed utilities combine font size, weight, line height, and letter spacing. They come in two contexts: UI for app interfaces, and prose for long-form content.
UI display styles are compact headings for dashboards, settings, and navigation, with tighter line height and tracking. Prose display styles are larger, heavier headings for articles, marketing pages, and rich content, designed for reading. On the docs site, each style is set in its own style, UI first, then prose.
ui-1
text-display-ui-1ui-2
text-display-ui-2ui-3
text-display-ui-3ui-4
text-display-ui-4ui-5
text-display-ui-5ui-6
text-display-ui-6prose-1
text-display-prose-1prose-2
text-display-prose-2prose-3
text-display-prose-3prose-4
text-display-prose-4prose-5
text-display-prose-5prose-6
text-display-prose-6| Utility | Size | Weight |
|---|---|---|
text-display-ui-1 | 4xl | Bold (700) |
text-display-ui-2 | 3xl | Bold (700) |
text-display-ui-3 | 2xl | Bold (700) |
text-display-ui-4 | xl | Bold (700) |
text-display-ui-5 | lg | Semibold (600) |
text-display-ui-6 | base | Semibold (600) |
text-display-prose-1 | 5xl | Black (900) |
text-display-prose-2 | 4xl | Bold (700) |
text-display-prose-3 | 3xl | Bold (700) |
text-display-prose-4 | 2xl | Bold (700) |
text-display-prose-5 | xl | Bold (700) |
text-display-prose-6 | lg | Bold (700) |
body already sets text-ui, so standard UI text needs no class. Each style
takes the line height and letter spacing of its context.
| Utility | Use for | Size | Context |
|---|---|---|---|
text-ui | App interface text, and the default on body | base | ui |
text-prose | Long-form content, such as articles and documentation | base | prose |
text-ui-meta | Secondary UI text, such as timestamps, counts, and hints | sm | ui |
text-code | Monospaced code | sm | code |
Semantic tokens keep rhythm consistent. Text style utilities set them by themselves, so use the tokens on their own only for custom compositions. On the docs site, each context is listed with its line height and letter spacing.
| Context | Line height | Letter spacing |
|---|---|---|
display | 1.2 | -0.02em |
ui | 1.35 | -0.01em |
prose | 1.5 | -0.01em |
code | 1.625 | 0em |
Use semantic colour utilities instead of raw colour values. They adapt to intents, themes, and dark mode by themselves.
<p className='text-strong'>text-strong for headings, emphasis, and high contrast</p><p className='text-normal'>text-normal for body text, inherited from the body reset</p><p className='text-subtle'>text-subtle for secondary text and descriptions</p><p className='text-subtler'>text-subtler for meta text, timestamps, and hints</p>
Roadie has no Text or Heading component. Use raw heading elements with a
display style utility and text-strong. Match the semantic level, h1 to
h6, to the document structure, and the visual style to the context.
Body inherits text-ui from the reset. Use <p> elements with semantic
colour classes.
Wrap CMS output, markdown, or user-generated content in <Prose> for
automatic typography and spacing. See Prose styles.
Intermission has two sets of figures. Proportional is the default, and each digit takes the width its shape wants. Tabular gives every digit the same width, so values line up in a column.
Equal-width digits are for columns and ticks. On a large standalone figure they read as gappy, because the 1s carry the same width as the 0s with nothing to line up against.
table column tabular-numsaxis ticks tabular-numsticking clock tabular-numshero figure proportional
Do
Tabular where values sit above one another, or where a digit changes under the eye. Proportional everywhere else.
hero figure tabular-nums
Don’t
A large static number with gaps where the narrow digits are.
A ticking countdown is the exception that proves the rule. Its digits don't align with anything, but they change while somebody is watching, so tabular figures stop the row shifting on every tick.
Text style utilities combine size, weight, line height, and letter spacing into a single class. Raw Tailwind size classes miss the other properties.
Body text inherits defaults
<h2 className='text-display-ui-3 text-strong'>Section title</h2><p>Body text inherits defaults</p><p className='text-ui-meta text-subtle'>Secondary text</p>
Do
Use pre-composed utilities. They set all typographic properties at once.
Body text
Secondary text
<h2 className='text-2xl font-bold'>Section title</h2><p>Body text</p><p className='text-sm text-subtle'>Secondary text</p>
Don’t
Don't use raw size and weight classes. They miss line height and letter spacing.
Semantic colours like text-subtle adapt to intents, themes, and dark mode. Raw colour values break when the context changes.
Strong text
Default text
Subtle text
Subtler text
<p className='text-strong'>Strong text</p><p className='text-normal'>Default text</p><p className='text-subtle'>Subtle text</p><p className='text-subtler'>Subtler text</p>
Do
Semantic colours adapt to the current intent and theme by themselves.
<p className='font-bold text-[#111827]'>Strong text</p><p className='text-[#374151]'>Default text</p><p className='text-[#6b7280]'>Subtle text</p><p className='text-[#9ca3af]'>Subtler text</p>
Don’t
Don't hardcode colour values. They won't respond to intent or dark mode.
UI styles are compact for app interfaces. Prose styles are larger for long-form reading. Mixing them creates visual inconsistency.
Dashboard
3 orders in the last 24 hours
<h3 className='text-display-ui-4 text-strong'>Recent orders</h3><p className='text-sm text-subtle'>3 orders in the last 24 hours</p>
Do
UI headings for dashboards, prose headings for articles.
Dashboard
3 orders in the last 24 hours
<h3 className='text-display-prose-4 text-strong'>Recent orders</h3><p className='text-sm text-subtle'>3 orders in the last 24 hours</p>
Don’t
Don't use prose display styles in app UI. They're too large and heavy.
Use the right element for the content type. Heading elements establish document structure for accessibility and SEO.
Do
Use headings for headings, paragraphs for text, and spans for inline fragments.
Don’t
Don't use divs for text content. Screen readers can't identify the structure.
Sizes from text-lg up already use clamp() to scale fluidly. Adding breakpoint overrides for font size fights the system.
{/* Automatically fluid */}<h1 className='text-display-ui-1 text-strong'>Dashboard</h1>
Do
Fluid type scales smoothly across all viewport widths.
{/* Fighting the fluid scale */}<h1 className='text-xl md:text-2xl lg:text-4xl'>Dashboard</h1>
Don’t
Don't add manual breakpoints for font size. It creates jarring jumps.
Heading levels follow document structure, h1 then h2 then h3. The display utility sets the visual weight, not the heading level.
<h1 className='text-display-ui-1 ...'>Page</h1><h2 className='text-display-ui-3 ...'>Section</h2><h3 className='text-display-ui-5 ...'>Sub</h3>
Do
Semantic levels follow structure. Visual style is independent.
<h1 className='text-display-ui-1 ...'>Page</h1>{/* Skipped h2 */}<h4 className='text-display-ui-5 ...'>Sub</h4>
Don’t
Don't skip heading levels for visual effect.
The Prose component styles nested HTML for CMS output, markdown, or user-generated content. It handles spacing, list markers, and element typography.
<Prose><h2>Title</h2><p>Paragraph with <a href='#'>link</a></p><ul><li>Item</li></ul></Prose>
Do
Prose handles all child element styling by itself.
<div><h2 className='text-2xl mb-4'>Title</h2><p className='mb-2 leading-6'>Text</p><ul className='list-disc pl-4'>...</ul></div>
Don’t
Don't manually style every element in user content.
| Element | When to use | Example |
|---|---|---|
<h1> to <h6> | Section headings | text-display-ui-3 text-strong |
<p> | Body text and descriptions | text-subtle |
<span> | Inline text fragments | text-sm text-subtler |
<strong> | Important text | text-strong |
<em> | Emphasis or stress | Italic inside <Prose> |
<Code> | Inline code, tokens, and commands | <Code>bg-normal</Code> |
<Prose> | CMS or markdown content | <Prose size='md'>...</Prose> |