Overview
A clickable button or anchor with built-in loading state, icon slots, and a discriminated prop union that forces consumers to provide an accessible name at compile time.
Usage
When href is set, the component renders as <a>; otherwise it renders as <button>. Setting loading swaps in a spinner, blocks the consumer's onclick, forces aria-disabled / aria-busy, and strips href to prevent navigation.
When to use
- Triggering a discrete action such as submit, save, or delete.
- Rendering a link that should look and behave like a button by passing href.
- Toggling a binary on or off state — use toggle instead.
- Selecting one of a small fixed set of options — use segmented-control instead.
Examples
Button as link
Passing href renders an anchor element with button styling.
Icon-only buttons
Icon-only buttons keep the visual surface compact while still carrying an accessible name through label or aria-label.
Loading state
A permanent loading button alongside one that toggles loading on click; both render the spinner and set aria-busy.
Primary button
The default button variant.
Button sizes
xs, sm, md, lg, and xl sizes.
Soft variants
Soft and soft-danger use a tinted fill with no border — mid-emphasis between ghost and primary/danger.
Text + icon buttons
leadingIcon and trailingIcon snippets are decorative-only and wrap their SVGs in aria-hidden. Meaning still lives in the button label.
Button variants
Primary, secondary, danger, and ghost styles.
Props
| Name | Type | Default | Required | Bindable | Description |
|---|---|---|---|---|---|
variant | 'primary''secondary''soft''danger''soft-danger''ghost''ghost-danger' | 'secondary' | Visual style. | ||
size | 'xs''sm''md''lg''xl' | 'md' | Size of the button. | ||
fullWidth | boolean | false | Expand to container width. | ||
loading | boolean | false | Disable the button and show a spinner. | ||
iconOnly | unknown | false | |||
leadingIcon | snippet | DECORATIVE icon rendered before the label/children. Always wrapped in aria-hidden.
If the icon conveys meaning, supply accessible text via label/aria-label instead. | |||
trailingIcon | snippet | DECORATIVE icon rendered after the label/children. Always wrapped in aria-hidden.
Same accessible-name guidance as leadingIcon. | |||
children | unknown | req | |||
label | unknown | req | |||
href | discriminated-union | ||||
onclick | unknown | req |