Axes — tone · appearance · variant
Styling axes are named by what they mean, and every component reaches for the same names. That's what makes the API predictable: you never have to guess whether variant="danger" exists (it doesn't — color intent is always tone).
tone
Color intentFrom the shared vocabulary neutral · brand · info · success · warning · danger · discovery (plus component-specific tones like Stat's positive/negative). Color intent is never expressed through an axis named variant.
<Badge tone="danger" />appearance
Fill / surface treatmentHow the color is applied to the surface: solid · soft · outline · ghost · subtle · framed, and friends.
<Alert tone="warning" appearance="soft" />variant
Kind / structureReserved for structural axes — line|bar, arc|needle, dot|icon — that swap geometry, not color or fill. Two exceptions are sanctioned in the lint: Button's variant is its action-emphasis (fill) axis with color intent still on tone, and Tabs' variant (underline|pill|enclosed) swaps indicator geometry.
<Sparkline variant="bar" />look
Bundled visual languageA lint-sanctioned Stepper-only one-off (filled | outline): a bundled indicator visual language, deliberately distinct from Badge-style fill appearance. No other component may declare a look axis.
<Stepper look="outline" />tone × appearance, rendered
The same component (Badge) across every tone, under four appearances. Tone carries the intent; appearance carries the fill.
solidsoftoutlinesubtleEvery enum axis also reflects to a matching data-<axis> attribute (data-tone, data-appearance, data-variant) so styling and testing can target semantics, not class soup. See it applied on any component page under Appearance — browse the roster →
These names aren't a convention you can opt out of: a metadata lint fails the build if a color axis is called variant, or a fill axis is misnamed. The structural variant axes and the Stepper look one-off are individually allowlisted there — a new one requires a doctrine review, not just a new prop.