Skip to main content
Copy for LLM

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? On feature it is the older name for the color axis rather than a family of its own. 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

Two more components carry the same arrangement, each on its own axis and under a different older name:

Component Older name Sets Prefer
card variant the surface axis surface
feature tone the color axis intent

card takes surface="outline", "elevated" or "flat" — outline spelled the way button spells it — and keeps accepting variant="outlined" with its trailing d. feature takes the shared role names, where primary resolves to the chip treatment it calls accent and info is a tint of its own, and keeps accepting tone. On both, the canonical name wins when a caller supplies both.

On every component not named above, 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
feature accent, neutral, soft, success, warning, danger — plus primary, which resolves to accent, and info, a tint of its own

feature takes intent, so both halves of the migration line up — intent="primary" and tone="accent" are the same call, written in two vocabularies — and tone keeps working for the whole of v2.

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

  1. Reach for intent when the modifier maps to a semantic state (warn / success / danger). Draw from the shared role names above rather than inventing synonyms.
  2. Reach for surface when the modifier picks how heavily that color is applied — fill, outline, soft, ghost.
  3. Reach for variant when 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.
  4. Do not reach for tone. It exists on one component and is not the direction the vocabulary is going.
  5. 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:

Both columns work today — the canonical name is accepted on every component below, and v3.0.0 is when the older one goes rather than when the newer one arrives.

Component Older spelling Canonical spelling 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; the same chip until you give info a color of its own
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 and surface are accepted on every component in the tables above, feature and card included. Moving a call site from variant to intent, or from tone to intent, is a no-op at runtime (for tone="soft", as long as info keeps the accent's color); moving card from variant="outlined" to surface="outline" is the one pair that also changes the value, and both spellings resolve to the same treatment.

Finding your own call sites

You do not have to read the tables above against your templates by hand:

php artisan wirekit:doctor:props

It reports every prop written in the older of two spellings and names the canonical one, file by file. The report is advisory: by default it does not change the exit code, because both spellings are supported API. Once your own tree has converted, --fail-on-legacy-axis makes a relapse a failure. Full flags: CLI Reference.

The pairs it knows are read out of the component templates themselves rather than kept as a list, so a component that gains its canonical spelling in a later release is covered by the same command on the day it ships.

Was this page helpful?

Thank you for your feedback!

Voting requires cookies or local storage. What we store