Component gallery

Typography

Which kit component owns which type role, the ramp as it actually renders, the gray ink ladder, and the four places mono needs its own rule.

The ramp as shipped

Seven sizes. xs, sm and base carry almost everything the survey found (R6: 111-233 uses per app for those three vs. single digits above lg); lg and up come from PageTitle and Card, not raw classes.
The quick brown foxthe quick brown foxtext-xs · 12px/16px
The quick brown foxthe quick brown foxtext-sm · 14px/20px
The quick brown foxthe quick brown foxtext-base · 16px/24px
The quick brown foxthe quick brown foxtext-lg · 18px/28px
The quick brown foxthe quick brown foxtext-xl · 20px/28px
The quick brown foxthe quick brown foxtext-2xl · 24px/32px
The quick brown foxthe quick brown foxtext-3xl · 30px/36px

Weight steps at text-base

400 font-normal500 font-medium600 font-semibold700 font-bold

These are the sizes actually rendering on this page: the kit sets only --font-sans and --font-mono(theme/index.css:74-80), no root font-size. Speedway's own stylesheet sets body { font-size: 14px }(app.css:98-106), which is why that app's text-base reads 14px/24px while this playground's reads Tailwind's default 16px/24px, a per-consumer choice, not a kit-level one.

Roles, not sizes

Reach for the component that owns a role before reaching for its class. Each row names the kit component, then the exact classes it applies.

Page title

h1 text-2xl font-bold truncate (page-title.tsx:86)

Brake pads Q3

Display title

h2 text-2xl font-bold tracking-tight md:text-3xl (landing-sections.tsx:58, playground-only, not a kit export)

A section that opens the landing

Section / card title

card-title text-base (card.tsx:114)

Enrichment

Attribute confidence and provenance

The card title doubles as the section's own documentation.

Card table title

card-title text-base plus titleDivider (card.tsx:107-118)

Rows

3 in this job

The rule sits under the header, not around the whole card.

Group title

Kicker default: text-[11px] font-semibold tracking-[0.08em] uppercase text-base-content/65 (kicker.tsx:9,22)

Notifications

Tile label

Kicker bricked: text-xs font-semibold tracking-wide uppercase text-base-content/65 (kicker.tsx:10,22)

Buttons

Stat label

text-base-content/65 truncate text-xs font-semibold (stat-tile.tsx:78)
Parts enriched

Body

text-base-content/70 text-sm (ink ladder, doc 60 section 1, line 27)

A paragraph of body copy reads at 70% ink, one step under full.

Help text

text-base-content/65 text-xs (ink ladder, doc 60 section 1, line 27)

Helper copy under a field: what the value is for, not a status.

Mono identifier

font-mono text-xs (01-foundations.md:28, ItemsTable.tsx:48)
SKU-48213-A

Stat value

font-mono text-3xl font-semibold tabular-nums (stat-tile.tsx:85)
Parts enriched
4,212+8.3%
up from 3,890 last week

Badge text

badge-sm, sans, normal weight (chip.tsx:93-101)

The kicker idiom's tracking

The only tracked text in the system. Full story and every sanctioned seat on the kicker page.

Default, 0.08em

The section-opener: above a group, above a landing section.

Bricked, tracking-wide (0.025em)

The tile label, read at close range inside its own frame.

The ink ladder

Five opacity steps on text-base-content, each carrying its roles; nothing small sits below /65.
titles and valuestext-base-content
bodytext-base-content/70
card subtitles, stat labels, kickers, tile labels, hints and help text (the lightest small text that clears AA in light)text-base-content/65
counts inside a controltext-base-content/45
disabled icon washtext-base-content/30

Tone on text

Five tones, shown once. The full semantic grammar lives in the status-language doc, not repeated here.

Primary: brand emphasis on an otherwise neutral line

Success: a value or state that is good news

Info: a neutral fact worth a highlight

Warning: needs a look before it becomes a problem

Error: something is broken or blocked

Mono, four special cases

Mono is for identifiers, never decoration. Each place the rule needs its own clause.

Inside a button

The count inherits the button's size and colour with no separate opacity (landing-sections.tsx:62, doc 59 C3).

Inside a code block

import { Card } from '@versable-git/ui'
import { Card } from "@versable-git/ui";

The header title renders in mono today whether or not it is itself code (code-block.tsx:167-173 has no sans branch); doc 60 §4 anticipates a future split between a code-shaped title and a plain descriptive one that is not yet built.

Inside an alert

Row part_h83k2m needs a brand before it can export.

The identifier rides Alert's own markdown prop as an inline code chip, never a mono paragraph (internal/markdown-lite.tsx:32-37).

Inside a chip

The label stays sans; the value is mono because it is an id.

Truncation and clamping

Three ways a value stops, and what pairs with each.

truncate + Tooltip

fitment-update-full-catalog-2026-q3.csv

A truncated value always carries its full text on hover.

line-clamp-2

Content items always surface as "Missing" whatever the internal reason, one shared map across the row chip, the editor, and the filter, so the sentence stops after two lines regardless of length.

break-all

app/routes/workspaces/jobs/setup.tsx

A path breaks anywhere rather than overflowing (markdown.tsx:87).

Real-life examples

The same rules on shipping screens, not fixture text alone.

A speedway job row

Brake pads Q3run 43 files · Scrape · AC Delco Q3 taxonomy
running

The status pill matches the shipping job row's StagePill (speedway JobsTable.tsx:141-212); the mono run suffix is the freshly designed identity that now ships as the job-title pattern (job-title/example.tsx:44-61, ruling D6) rather than something the list row itself carries today.

A walmart part identity row

AC Delco brake rotor, 12.5in vented

sku

WM-48213-A

The mono SKU matches walmart's own row: ItemsTable.tsx:48 renders <code className="font-mono text-xs">{item.sku}</code>. Walmart has no Kicker yet, so the label here is this ruling's own composite, not a lift.

A docs paragraph, after G6.9

Palette ramps (Layer 0) flow into semantic slots (Layer 1), then app aliases (Layer 2) point into the semantic layer only, the size the reader complained was too small before the bump.

Docs prose renders at text-base (markdown.tsx:53), up from text-smper the owner's G6.9 ruling (docs/plan/53-showcase-feedback-2.md:68).

@versable-git/ui · all states, both themes