Prop Naming Conventions
WireKit components carry several prop names for what looks at first glance like the same concept — "which color, which shape, how much emphasis?". This page is the contract behind each name, so that a developer reading API tables across the catalog can tell them apart, and so that the answer to "which prop do I reach for here?" is a lookup rather than a guess.
One thing to know before the table: variant does not mean the same thing on every component. On most it picks a visual treatment. On a handful it is an older spelling of the color axis and is kept working on purpose. The alias matrix below names every component in that second group.
The four families
| Prop | Semantic | Values | Examples |
|---|---|---|---|
intent |
Semantic color identity. What is this thing FOR — is it the primary action, a warning, a success? | A shared vocabulary, applied per component — see below | button, badge, alert, callout, stat |
surface |
How that color is applied. Same intent, different weight of ink: solid fill, outline, soft tint, ghost. | filled, outline, soft, ghost, link |
button, badge, theme-controller |
variant |
Visual mode. Same content, different surface treatment or layout register. | Family-specific (outlined / elevated / flat on card; default / dark / accent / muted on marketing surfaces) |
card, hero, cta, link, tabs |
tone |
Qualitative emphasis. How loud should this read? | Per component | feature |
The Examples column is a handful of representative components, not the catalog — many more carry each prop. The API table on a component's own page is the authority for that component.
intent and surface are the two axes that compose: intent picks the color family, surface picks how much of it lands on the element. <x-wirekit::button intent="danger" surface="outline"> is a destructive action rendered as an outline rather than a solid fill — two independent choices, not seven pre-blended ones.
The alias matrix
On these components variant is a back-compat alias of intent. Both set the same axis, both validate against the same value set, and intent wins when a caller supplies both:
| Component | variant sets |
Prefer |
|---|---|---|
alert |
the color axis | intent |
callout |
the color axis | intent |
text |
the color axis | intent |
progress |
the color axis | intent |
progress.circle |
the color axis | intent |
reading-progress |
the color axis | intent |
timeline.item |
the color axis | intent |
On every other component, variant is the visual-mode family from the table above and is not an alias of anything.
Why the alias exists: intent is what button and badge call this axis, so it is what a developer moving between components reaches for. Adding it to these components without breaking the code already written meant accepting both. Nothing about it is deprecated in v2 — see Where this is heading for the v3 position.
The shared vocabulary is a vocabulary, not one fixed enum
intent draws from a shared set of role names — primary, neutral, info, success, warning, danger, plus accent on the components whose design calls for it. Which of those a given component accepts is that component's own decision, and the values are validated per component:
| Component | Accepts |
|---|---|
button |
primary, neutral, info, success, warning, danger |
badge, stat |
the same, plus accent |
alert, callout |
primary, neutral, info, success, warning, danger |
text |
default, muted, subtle, accent, success, warning, danger |
text is the instructive one. Its color axis is a typographic scale rather than a severity set, so it has no primary — and an intent spelling it does not carry fails validation rather than quietly rendering the default. Loud beats a silent fallback: a heading that came out in the wrong color with no error is the failure nobody notices.
The practical consequence: copying intent="primary" from a button onto a text is not a safe move, and neither is a blanket find-and-replace across a codebase. Check the component's own API table.
When you are authoring a component
- Reach for
intentwhen the modifier maps to a semantic state (warn / success / danger). Draw from the shared role names above rather than inventing synonyms. - Reach for
surfacewhen the modifier picks how heavily that color is applied — fill, outline, soft, ghost. - Reach for
variantwhen the modifier picks a visual mode that is neither of those: a card that is outlined instead of elevated, a hero that renders dark instead of default. - Do not reach for
tone. It exists on one component and is not the direction the vocabulary is going. - Validate with
WireKit::validateProp()so an unknown value raises in debug and falls back to the first allowed value in production. See Authoring Custom Components → Prop validation for the call shape.
Where this is heading
The short answer for planning
variant and tone are supported for the whole of v2 and will not be renamed in any v2 release. The unification lands in v3.0.0, which has no fixed date. If you are writing new code today, write intent and surface — those two names survive the transition unchanged.
v3.0.0 reduces the modifier vocabulary to two canonical axes: intent for the color role, surface for the surface treatment. variant and tone are the names that go.
The mapping is settled per component, and the two kinds of change are worth separating, because only one of them is mechanical:
| Component | Today | v3.0.0 | Kind of change |
|---|---|---|---|
| every component in the alias matrix | variant="…" |
intent="…" |
prop rename, value unchanged |
card |
variant="outlined" |
surface="outline" |
prop rename and value rename |
card |
variant="elevated" / "flat" |
surface="elevated" / "flat" |
prop rename, value unchanged |
feature |
tone="accent" |
intent="primary" |
prop rename and value rename |
feature |
tone="soft" |
intent="info" |
prop rename and value rename |
feature |
tone="success" / "warning" / "danger" |
intent="…" |
prop rename, value unchanged |
Every row in the alias matrix is in the first group: the value you already wrote is the value intent takes, because both spellings already resolve into one validated set. Renaming the prop on those components changes nothing about what renders.
The rows that also rename a value are the ones a find-and-replace gets wrong, and they are named above so the rewrite can be done per component rather than in one sweep.
Preparing early costs nothing and is safe today: intent is already accepted on every component in the alias matrix, and surface is already accepted on the components that will grow it. Moving a call site from variant to intent right now is a no-op at runtime.