Anta design system

Button

An action control. Renders an <a-button> web component (or <a role="button"> when href is set) with a tone × priority matrix applied via attributes.

Preview
Every tone × priority × state combo from the Figma component set — 6 tones × 4 priorities × 7 states = 168 buttons. Tone groups stack vertically; within each group, columns are priorities (primary, secondary, tertiary, quaternary) and rows are states (rest, hover, pressed, disabled, loading, focus, selected).
style?set by code

Tones

Six named tones — brand (default), neutral, critical, info, success, warning — plus a one-off custom tone for any literal CSS color value:

<Button tone="brand" label="Save" />
<Button tone="#ff1493" label="Pink one-off" />
<Button tone="oklch(0.6 0.25 30)" label="oklch one-off" />

For custom tones, only the hue of the input is taken. Lightness and chroma come from the brand-tone curve, so pale or low-chroma inputs (tone="#cccccc", tone="white") still produce a legible button. The full priority × state matrix — rest, hover, active, secondary alpha overlay, tertiary fill — is derived automatically.

If you need pixel-precise color, set --button-fg-color, --button-bg-color, or --button-br-color directly via style — inline declarations beat the resolver.

Dark mode reuses the same curve. To pair light/dark variants for a custom tone, scope it yourself:

.dark a-button[tone=""] { --button-tone-source: ; }

Priorities

Four priorities, each with a distinct visual signature:

PriorityVisual
primarySaturated fill. Main call to action.
secondaryPastel background, no border. Everyday button.
tertiaryBackground-less at rest, fills on hover. Dense toolbars.
quaternaryText only — no background, no border, no transitions.

Two prop constraints follow from priority and are enforced at the type level:

<Button priority="tertiary" underline="dashed" label="Read more" />
<Button priority="quaternary" paddingless label="here" />

The underline holds at a 0.5px hairline in every state; only the underline alpha lifts from 75% → 100% on hover/active. The color tracks --button-fg-color so a tone shift updates the underline in lockstep with the label.

Sizes

Three sizes; only padding changes (font size stays at 15px):

<Button size="small" label="Small" />
<Button size="default" label="Default" />
<Button size="large" label="Large" />

Icon-only

Pass iconButton="<shape>" for a square icon button. The label and content slots are TypeScript errors in this mode — icon-only buttons render the named icon standalone:

<Button iconButton="check" />
<Button iconButton="trash" tone="critical" />
<Button iconButton="dots-vertical" size="small" />

A min-width is pinned to the natural square (20px / 24px / 28px for small / default / large) so a tight flex parent can’t clip the icon.

Leading and trailing icons

For non-icon-only buttons, pass leadingIcon and/or trailingIcon:

<Button leadingIcon="check" label="Confirm" />
<Button trailingIcon="external-link" label="Read the docs" />
<Button leadingIcon="info" trailingIcon="chevron-down" label="Filter" />

Icon shape names come from the IconShape union — see the Icon page for the full set.

States

<Button loading label="Submitting" />
<Button disabled label="Locked" />
<Button selected label="Toggled on" />
<Button loading disabled label="Critical" />

Anchor mode

Setting href switches the rendered tag from <a-button> to <a role="button">. Styling is identical — both selectors share the same CSS rules. Form-submission props (type, form) are TypeScript errors in anchor mode; navigation takes over.

<Button href="/docs" target="_blank" rel="noopener" label="Read the docs" />

Form submission

For non-anchor buttons, type="submit" and type="reset" integrate with native forms:

<form id="signup">
<Button type="submit" label="Sign up" />
<Button type="reset" label="Clear" />
</form>
{/* Associate with a form by id when the button is outside */}
<Button type="submit" form="signup" label="Submit from outside" />

type="submit" calls form.requestSubmit() and also dispatches a submitdetailed event on the form with { formData, submitter: { tag, attrs } } in detail — handy for analytics or multi-button forms.

Custom click events

data-custom-event="<name>" makes the button dispatch a bubbling CustomEvent("<name>") on click. Use it to instrument analytics without taking ownership of onClick:

<Button label="Save" data-custom-event="save-clicked" />

Children alongside label

Children render after the label and before the trailing icon, so you can mix custom inline content — keyboard hints, badges, counters — with the prop-driven API:

<Button label="Save" leadingIcon="check">
<span style={{ opacity: 0.7, fontSize: 12 }}>⌘S</span>
</Button>

Children also work without label — pass them as the only content.

Props

PropTypeNotes
tone'brand' | 'neutral' | 'critical' | 'info' | 'success' | 'warning' | <css color>Default brand. Literal colors derive the full matrix from the input hue.
priority'primary' | 'secondary' | 'tertiary' | 'quaternary'Default primary.
size'small' | 'default' | 'large'Default default. Only padding changes.
underline'solid' | 'dashed' | 'dotted'tertiary / quaternary only.
paddinglessbooleanquaternary only.
loadingbooleanStripe overlay; blocks clicks.
disabledbooleanDisabled palette; no clicks; removed from tab order.
selectedbooleanToggled-on visual (shares active look).
leadingIcon / trailingIconIconShapeIcon shape names. Forbidden with iconButton.
iconButtonIconShapeIcon-only mode. label / leadingIcon / trailingIcon / children are TypeScript errors when set.
labelstringRendered inside <a-button-label>.
hrefstringSwitches to <a role="button">.
target / relstringAnchor mode only.
type'button' | 'submit' | 'reset'Form integration. Forbidden with href.
formstringAssociate with a form by id. Forbidden with href.
onClick(e) => voidClick handler.
data-custom-eventstringDispatches CustomEvent(<name>) on click.

Component tokens

Override any of these on a single instance (style={{ '--button-padding-x': '12px' }}) or on a selector wrapping the button (e.g. a tone or variant of your own). Color tokens are dual-declared hex; oklch; alpha fills use color-mix(in oklch, …) with a hex8 fallback first.

TokenDescription
--button-fg-colorText and icon color. Resolved per tone × priority × state.
--button-bg-colorBackground fill.
--button-br-colorBorder color. Primary mirrors the fill; others are transparent.
--button-focus-colorFocus-ring outline color.
--button-padding-x / --button-padding-yInner spacing.
--button-br-radiusBorder radius (default 4px).
--button-br-widthBorder width (default 0 — no border). Set to 1px for an outlined variant.
--button-font-size / --button-font-family / --button-font-weight / --button-line-heightType.
--button-gapSpacing between icon, label, and children.
--button-timing-in / --button-timing-out / --button-timing-activePer-state transition durations (50ms / 150ms / 50ms). Quaternary zeroes all three.
--button-outline-offsetFocus-ring offset (default 1px).
--button-loading-durationOne slide cycle for the loading stripe (default 1.1s).
--button-loading-angleStripe angle (default 125deg).
--button-loading-periodStripe + gap along the gradient axis (default 30px).
--button-loading-stripe / --button-loading-stripe-gapStripe geometry (default 14px / 16px).
--button-loading-opacityOverlay opacity (default 0.3).
--button-loading-blurStripe-edge softening (default 1px).