Skip to content

Button

Stable

Buttons trigger actions. Use them to submit forms, navigate, or initiate workflows.

Examples

Interactive previews with copy-ready code snippets. All buttons include keyboard focus rings, hover, active, and disabled states.

Default button

The primary button is used for the single most important action on a screen.

Button types

Four semantic variants covering every hierarchy level — from the main CTA to a ghost-style tertiary action.

Sizes

Three sizes — sm (32px), md (40px, default), lg (48px). Use sm inside compact UI like table rows; lg for hero or standalone CTAs.

With leading icon

A leading icon reinforces the action. Always pair with a visible label — use icon-only for space-constrained contexts.

With trailing icon

Trailing icons are best for navigation actions — arrows and chevrons signal that the button leads somewhere.

Icon only

When space is tight. Always provide an aria-label so screen readers announce the action.

Full width

Stretches to fill its container. Useful in forms, modals, and mobile layouts.

Disabled state

Reduces opacity to 50% and blocks pointer events. Where possible, explain why the button is disabled.

Loading state

Replaces the leading icon with a spinner and locks interaction. Apply after a user triggers an async action.

Anatomy

① Container② Leading icon③ Label④ Trailing icon

① Container

Rounded frame — background, border, shadow

② Leading icon

Optional — 16×16px (sm/md) or 20×20px (lg)

③ Label

Required — 1–3 words, sentence case

④ Trailing icon

Optional — best for navigation cues

States

Default
Hover
Pressed
Focus
Disabled
Loading

Design tokens

TokenValueDescription
background/brand/primary
#318272
Primary button fill
background/brand/hover
#226558
Primary hover state
background/brand/pressed
#15483e
Primary pressed state
background/muted
#e1e1e1
Disabled fill
background/state/error/bold
#bc1700
Destructive fill
text/inverse
#ffffff
Text on primary/destructive
text/disabled
#8f8f8f
Disabled text
border/Default
#cccccc
Secondary border
focus/Ring
#acffef
Focus shadow colour
Radius/md
8px
Corner radius

Props

PropTypeDefaultDescription
variant"primary" | "secondary" | "tertiary" | "destructive""primary"Visual style — maps directly to a semantic colour token set.
size"sm" | "md" | "lg""md"sm=32px · md=40px · lg=48px height.
disabledbooleanfalseReduces opacity and blocks interaction. Keep focusable where possible.
loadingbooleanfalseReplaces leading icon with a spinner and implies disabled.
fullWidthbooleanfalseStretches to fill the parent container width.
leadingIconReact.ElementTypeLucide (or any SVG) icon component rendered before the label.
trailingIconReact.ElementTypeIcon rendered after the label. Best for navigation cues.
onClick() => voidClick handler. Not called when disabled or loading.

Content guidelines

Do

  • Use 1–3 words that describe the action: "Save changes", "Create account"
  • Use sentence case, not ALL CAPS
  • Use one primary button per screen section
  • Pair icon-only buttons with aria-label
  • Explain why a button is disabled via tooltip or helper text

Don't

  • Use vague labels: "OK", "Yes", "Click here"
  • Place two primary buttons side by side
  • Use a button for page navigation — use a link
  • Use a destructive button for minor, reversible actions
  • Skip the label on icon-only buttons without aria-label