Button
Button for triggering actions. Use default for the primary action on a surface, secondary/ghost for progressively lower emphasis, destructive for dangerous actions, and link for navigation-style actions. Content is provided via the default snippet; extra attributes (e.g. disabled, aria-*) are forwarded to the underlying element. Passing an href renders an <a> instead — a link that looks and lines up like a button, so a destination never has to be dressed up as an action with an onclick. status covers the life of an action that takes a moment: pending swaps the label for a spinner, success for a check. The label keeps its space while either is showing, so the button never changes width under the pointer that just pressed it — a button that resizes as it works throws the whole row around it, and on the press itself it moves the target out from under the finger.
Variants
default for the primary action on a surface, secondary for one sitting beside it, ghost for a toolbar or low-emphasis action, destructive for something irreversible, and link for a destination dressed as text rather than as a control.
<Button>Save changes</Button>
<Button variant="secondary">Cancel</Button>
<Button variant="ghost">Filters</Button>
<Button variant="destructive">Delete</Button>
<Button variant="link">Learn more</Button>Sizes
Every button in a row of controls is one height, so they line up without anyone choosing. icon only squares it off for a lone glyph — remember an aria-label there — and lg is reserved for a call to action standing on its own, never inside a toolbar row.
<Button>Default</Button>
<Button size="lg">Get started</Button>
<Button size="icon" variant="secondary" aria-label="Settings">
<Settings class="size-4" />
</Button>Status
The life of an action that takes a moment. The label goes invisible rather than being replaced, so the button holds its idle width while the spinner sits over it — a button that resizes as it works throws the whole row around it. Hold success briefly, then return to idle: a check that never goes away stops meaning anything.
<Button status="pending">Save changes</Button>
<Button status="success">Save changes</Button>As a link
An href renders an <a> with identical styling, so a destination never has to be dressed up as an action. onclick and type are ignored once it is set.
<Button href="/components" variant="secondary">View components</Button>Disabled
Pointer events are removed and opacity reduced. Reach for it only where the action is genuinely unavailable — a button that is disabled without saying why is a dead end.
<Button disabled>Save changes</Button>
<Button variant="secondary" disabled>Cancel</Button>API
| Prop | Type | Default | Description |
|---|---|---|---|
children required | import('svelte').Snippet | Button content. | |
variant | 'default'|'destructive'|'secondary'|'ghost'|'link' | 'default' | Visual emphasis of the button. |
size | 'default'|'lg'|'icon' | 'default' |
|
status | 'idle'|'pending'|'success' | 'idle' | Progress of the action this button started. |
class | string | Additional Tailwind classes merged onto the button. | |
href | string | Renders an | |
onclick | (event: MouseEvent) => void | Click event handler. Ignored when | |
type | 'button'|'submit'|'reset' | 'button' | Native button type attribute. Ignored when |
disabled | boolean | Disables the button (forwarded via |