forms contract
Button
Primary interactive control for triggering actions. Use whenever a user must commit a decision (save, submit, confirm, cancel, navigate to a destructive flow).
Variants
- primary
- Filled, brand tint. The single CTA per scope. White label on tint.
- secondary
- Tinted (alpha 12-16% of brand). Sits next to a primary as an alternate path; never repeated.
- ghost
- No background, label in body color. For tertiary actions in toolbars and menus.
- outline
- 1px hairline border + transparent fill. Fallback when ghost reads too quiet.
- destructive
- Filled with semantic.destructive tint. Confirms data loss; pairs with a confirmation dialog.
- link
- Underlined inline action that visually reads as a hyperlink but performs a button action.
Sizes
- sm
- 28pt height, body 13/18, 12pt horizontal padding
- md
- 36pt height, body 15/20, 16pt horizontal padding (default)
- lg
- 44pt height, body 17/22, 20pt horizontal padding (touch comfort)
- xl
- 52pt height, headline 17/22-semibold — hero CTAs only
Slots
- children
- Label text
- leading
- Optional icon or avatar before the label
- trailing
- Optional icon (chevron, external) after the label
Example
Primary CTA with leading icon, follows the variant + size + slot pattern.
<Button variant="primary" size="md" leading={<PlusIcon />}>New project</Button>Usage rule
Exactly one primary button per visual scope. If two are needed, demote one to secondary.
The full Button contract has 9 more rules and 3 more examples, plus the do-not patterns. Get the full recipe.