# Button

A button starts an action, like placing a bid, saving a form or closing a dialog.

## When to use

- To start an action on the current page, like *Place bid*, *Deposit* or *Cancel*.
- To confirm or close a dialog, or to move through the steps of a flow.

## When not to use

- To go to another page, use a link. If it has to look like a button, wrap the link with `asChild`.
- To turn a setting on or off, use a switch.
- To filter a list or pick one of a few options, use a segmented control or chips.
- For an action shown only as an icon, like close or copy, use an [Icon button](/components/icon-button/).

## Anatomy

## Variants

- **Primary** (`default`) is for the main action in a view, like *Place bid* or *Confirm*. Use it once per view.
- **Secondary** is for every other action, like *Deposit*, *Withdraw* or *Cancel*.
- **Ghost** is for quieter actions in toolbars, menus and dense rows.
- **Destructive** is for actions that can't be undone, like *Delete* or *Remove*.

## Sizes

- **Small** (32px) fits dense layouts, tables and inline actions.
- **Medium** (40px) is the default.
- **Large** (48px) suits the main action in a panel or on mobile.

Buttons that sit side by side should be the same size.

## With icons

An icon before the label helps explain the action. An icon after it shows direction, like an arrow to the next step. Icons are 20px at every size, and a button has one icon at most.

## States

Try the examples above to see hover, pressed and focus. A pressed button shrinks slightly, to 97%, unless it's loading or the user has turned on reduced motion.

### Disabled

Disable a button only when you have to. If an action isn't available, say why next to it so people aren't left guessing.

### Loading

Show this while the action runs, for example while waiting for a wallet signature. The button keeps its width and ignores more clicks.

## Content

- Start with a verb that says what happens, like *Place bid* or *Confirm withdrawal*.
- Use sentence case, no full stop, and two or three words.
- Name the thing when it helps. *Delete draft* is clearer than *Delete*.

## Behaviour

| Key | Action |
| --- | --- |
| <kbd>Tab</kbd> | Moves focus to the button. |
| <kbd>Enter</kbd> or <kbd>Space</kbd> | Runs the action. |

<kbd>Tab</kbd> skips disabled buttons. A loading button keeps focus but ignores <kbd>Enter</kbd>, <kbd>Space</kbd> and clicks.

## Accessibility

- Keyboard focus shows a 2px ring with a 2px gap (`focus/ring`). It appears at once on focus, then fades and pulls back to the edge over 150ms when focus leaves (no movement under reduced motion). Don't remove it.
- While loading, the button sets `aria-busy` and keeps its label as the accessible name.
- Use the variant tokens for colour. If you change one, check the [contrast table](/reference/colors/) in both themes.

## Props

| Prop | Type | Default | Notes |
| --- | --- | --- | --- |
| `variant` | `"default"` \| `"secondary"` \| `"ghost"` \| `"destructive"` | `"default"` | `default` is Primary. |
| `size` | `"sm"` \| `"default"` \| `"lg"` | `"default"` | |
| `loading` | `boolean` | `false` | Shows a spinner, keeps the width and ignores clicks. |
| `asChild` | `boolean` | `false` | Gives the child, usually a link, the button's styles. |

Every other `<button>` prop passes through, including `disabled`, `type` and `onClick`.

## Related

- An [Icon button](/components/icon-button/) runs an action with just an icon.
- A [Badge](/components/badge/) labels a status and can't be clicked.
