Open most component libraries and the button has a variant prop with five or six values. It works until the day you need a soft, brand-colored, small button, and there is no seam to express that without a new one-off.
Three axes, not one list
ai2 splits the single variant list into three orthogonal axes: variant is the visual language, tone is the semantic color, size is the scale. They compose, so combinations are the point, not exceptions.
<Button variant="soft" tone="brand" size="sm">
Save
</Button>Thirty style pairs (five variants times six tones) across the size scale. The button covers them by composition, not by a growing list of hand-named variants.
The axis contract
- The vocabulary is fixed: variant, tone, size, density, shape, orientation. No synonyms.
- A given size is pixel-identical across every form control, so rows line up.
- Adding a value never changes existing defaults, so upgrades are safe.
A design system earns the name when the combinations are the product, not the edge cases.
Why it holds up
Because the axes are semantic tokens, a third theme changes nothing in the components. If a component needs a special case to re-theme, it is reaching past the contract, and that is the bug to fix.

