Button
The primary affordance. Variant locks the colour, size locks the height. There are no other levers — by design.
Variants
One of: primary · secondary · ghost · outline · danger · link.
<Button>Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="outline">Outline</Button>
<Button variant="danger">Danger</Button>
<Button variant="link">Link</Button>Sizes
sm · md · lg · xl · icon. Use the smallest size that fits the surrounding density.
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
<Button size="xl">Extra large</Button>
<Button size="icon"><Plus /></Button>With icons
leftIcon and rightIcon slots wrap any node. Hover sets a 200ms ease-out colour shift.
<Button leftIcon={<Download />}>Download</Button>
<Button variant="secondary" rightIcon={<ArrowRight />}>Continue</Button>
<Button variant="danger" leftIcon={<Trash2 />}>Delete</Button>Loading + disabled
loading replaces the leftIcon with a spinner and disables the button.
<Button loading>Saving…</Button>
<Button disabled>Disabled</Button>Props
| Prop | Type | Default |
|---|---|---|
| variant | "primary" | "secondary" | "ghost" | "outline" | "danger" | "link" | "primary" |
| size | "sm" | "md" | "lg" | "xl" | "icon" | "md" |
| loading | boolean | false |
| leftIcon | React.ReactNode | — |
| rightIcon | React.ReactNode | — |
| asChild | boolean (renders via Radix Slot — e.g. <Button asChild><Link/></Button>) | false |