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

PropTypeWhat it does
variant"primary" | "outline" | "ghost" | "danger"Defaults to primary.
size"sm" | "md" | "lg"Defaults to md (40px).
loadingbooleanShows a spinner in place of the leading icon and disables the button.
leftIcon, rightIconReactNode16px icons.
componentElementTypeButtonLink only: the element to render, next/link for client navigation.