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.