Skip to content

Button

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

Variant
Size
Icon
State
Label
JSX
<Button>Place bid</Button>
  • 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.
  • 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.
  1. 1ContainerThe pill shape. Its fill or outline comes from the variant, and it sets the height and padding.
  2. 2Leading iconOptional20px. Helps explain the action.
  3. 3LabelA verb that says what happens, in semibold.
  4. 4Trailing iconOptional20px. Shows direction, like next or opening a new page.
default
secondary
ghost
destructive
  • 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.
DoOne primary button per view, with secondary buttons for the rest.
Don'tTwo primary buttons side by side. People can't tell which one matters.
DoDestructive for an action that can't be undone, named after what it deletes.
Don'tA red button for a falling price. That's data, not an action, so use negative text.
Small, 32px
Medium, 40px
Large, 48px
  • 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.

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.

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.

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.

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

  • 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.
DoA label that says what happens, starting with a verb.
Don'tA vague label. People have to read the rest of the screen to know what it does.
Key Action
Tab Moves focus to the button.
Enter or Space Runs the action.

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

  • 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 in both themes.
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.

  • An Icon button runs an action with just an icon.
  • A Badge labels a status and can’t be clicked.