Button
Trigger an action — submit a form, open a dialog, confirm a destructive change.
Use primary for the one action a surface is really asking for, secondary for alternatives beside it, tertiary and ghost for low-priority actions, and danger for anything destructive. A surface with two primary buttons has no primary button.
For an icon with no label, reach for IconButton instead — it carries the accessible name and the tooltip for you.
Variants
Nine variants, plus two aliases kept for the shadcn-shaped call sites that predate the hand-rolled library: default resolves to primary and destructive to danger. Prefer the canonical names in new code.
Accent variants
accent and accent-soft take their colour from the surface they sit on rather than from a prop — see Contextual accent. The same markup is purple in the builder and green in the CMS.
Sizes
s for dense toolbars and panel rows, m for standalone actions, lg for a page's single main call to action. sm, md and default are accepted aliases that normalise to s, m and m.
Icons
Pass leftIcon or rightIcon rather than putting an icon in children — the wrapper spans set the gap and are marked aria-hidden, so the icon never reaches a screen reader as stray content.
Disabled
Disabled buttons are not focusable and give no explanation, so prefer leaving the button enabled and reporting the problem on submit — unless the reason is already visible on screen.
Rendering as a link
asChildhands the button's classes to the child element instead of rendering a <button>. Use it for navigation, so the thing that looks like a button is an anchor and behaves like one — middle-click, open in new tab, copy address.
leftIcon and rightIconwork here exactly as they do on a plain button: the icons are composed around the child's own content, inside the anchor.
Props
Button
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "primary" | "secondary" | "tertiary" | "ghost" | "danger" | "outline" | "link" | "accent" | "accent-soft" | "default" | "destructive" | "primary" | Semantic role. `default` and `destructive` are aliases for `primary` and `danger`. |
size | "s" | "m" | "lg" | "icon" | "sm" | "md" | "default" | "m" | `sm` → `s`, `md`/`default` → `m`. Use `icon` only for square icon buttons. |
leftIcon | ReactNode | — | Icon before the label, wrapped and hidden from assistive technology. |
rightIcon | ReactNode | — | Icon after the label, wrapped and hidden from assistive technology. |
asChild | boolean | false | Apply the button's styling to the single child element instead of a button. |
type | "button" | "submit" | "reset" | "button" | Defaults to `button` so a button inside a form does not submit by accident. |