Actions
Button
One button family: primary amber for the one main action, outline for the secondary, ghost for tertiary, danger for destructive.
Examples
Variants
<Button>Open Dashboard</Button>
<Button variant="outline" leftIcon={<GitHubIcon />}>View on GitHub</Button>
<Button variant="ghost">Cancel</Button>
<Button variant="danger" leftIcon={<Trash2 />}>Delete run</Button>
<IconButton aria-label="Refresh"><RefreshCw /></IconButton>Sizes, loading and disabled
<Button size="sm">Run backup</Button>
<Button size="lg" rightIcon={<ArrowRight />}>Start backing up</Button>
<Button loading>Backing up</Button>
<Button variant="outline" disabled>Disabled</Button>As a link
import Link from "next/link";
<ButtonLink component={Link} href="/backups" variant="outline">View history</ButtonLink>Guidelines
- One primary button per view, and it is the action the page exists for. Everything beside it is outline; anything inside a card header or row is ghost or an IconButton.
- Labels are sentence case with a verb first. A leading Lucide icon at 16px is optional; a trailing arrow marks navigation.
- Loading swaps the leading icon for a spinner and keeps the label, so the width does not jump.
- Sizes: 40px by default, sm (32px) inside cards and table rows, lg (48px) in a hero only.
- Links that look like buttons use ButtonLink with component={Link} for client navigation.
Props
| Prop | Type | What it does |
|---|---|---|
| variant | "primary" | "outline" | "ghost" | "danger" | Defaults to primary. |
| size | "sm" | "md" | "lg" | Defaults to md (40px). |
| loading | boolean | Shows a spinner in place of the leading icon and disables the button. |
| leftIcon, rightIcon | ReactNode | 16px icons. |
| component | ElementType | ButtonLink only: the element to render, next/link for client navigation. |