Button
The pill button. Label as children, w-fit by default, type=button by default, asChild for links and triggers, one focus halo, one disabled recipe.
Variants
Primary is electric blue (blue-700 hover); secondary is the high-contrast black/white CTA. Pink/dark/sky carry the brand pairings for special moments.
Sizes
Three sizes share one vocabulary across the control family (Button, IconButton, Input, Select). Heights are h-8 / h-10 / h-11 on the 8pt grid; text steps 12 → 14 → 16 on the closed type scale. The app is compact-first: sm is the default — reach for md on prominent/primary CTAs and lg for hero actions.
Sizes with icon
A leading icon scales with the button — size-3.5 / size-4 / size-5 across sm / md / lg so the icon-to-label ratio stays constant.
Outline & ghost
Low-emphasis variants for secondary actions (shadcn outline/ghost, adapted to our tokens). Outline carries a hairline border; ghost is borderless and flat — no hover lift. Each comes in a neutral and a brand-blue tint.
Disabled states
Disabled keeps each variant's hue at reduced strength (per the brand button-states sheet) instead of collapsing to gray.
With icons
Buttons can include a leading icon.
Loading, then done
The spinner fades in over the label, which keeps its space; the button keeps its colour (no disabled dimming). `success` shows a check in the icon slot for the done beat — pair it with a changed label and clear it after a moment (useSaveState).
With keyboard shortcut
Display a keyboard shortcut hint inside the button.
Disabled
Disabled buttons with optional tooltip explaining why.
Width
A button is an inline control and sizes to its label (w-fit). Pass w-full to stretch it — a form's submit button, a card's single CTA.
Long labels
A width-constrained w-full button truncates its label and keeps its icon and shortcut whole; a w-fit button in a tight row keeps its full width instead of clipping.
asChild — links and triggers
Render another element with the button's classes. The child owns its own props; icon and right are placed inside it around its content, while loading and shortcut do not apply.
Icon-only sizes
icon / icon-md / icon-lg are square steps matching sm / md / lg. The SVG is sized to the step unless it carries its own size-* class. Always pass aria-label.
Shortcut and disabled tooltip
shortcut renders a Kbd on md+ screens. disabledTooltip disables the button and explains why on hover; the button stays a real, focusable element.