Actions
Button
Triggers an action. Four variants share one size scale and the density token.
Live example
Usage
<Button variant="primary" iconStart={<Icon name="plus" />} onClick={add}>
New booking
</Button>Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant? | 'primary' | 'secondary' | 'ghost' | 'danger' | 'secondary' | Visual weight. Use one primary button per view. |
size? | 'sm' | 'md' | 'lg' | 'md' | Height follows size.control tokens times the density scale. |
loading? | boolean | false | Shows a spinner and sets aria-busy. The button stays focusable and ignores clicks. |
iconStart? | ReactNode | none | Decorative icon before the label. |
iconEnd? | ReactNode | none | Decorative icon after the label. |
fullWidth? | boolean | false | Stretch to the container width. |
type? | 'button' | 'submit' | 'reset' | 'button' | Defaults to 'button' so it never submits a form by accident. |
Do and don't
Do
- Start labels with a verb: "Save booking", "Export CSV".
- Use LinkButton when the action navigates.
- Keep one primary action per view.
Don't
- Disable a submit button to hide validation; show the errors instead.
- Use a div or span with a click handler.
- Put two primary buttons side by side.
Accessibility
- Native button element, so Enter and Space work and it is announced as a button.
- Loading keeps focus in place and announces busy state instead of removing the button from the Tab order.
- Focus ring uses the focus token, checked at 3:1 against page and surface colors in every theme.
Keyboard
| Keys | Action |
|---|---|
| Enter, Space | Activates the button |
| Tab | Moves focus to and from the button |