gray
radius
Actions

Button

Runs an action such as submitting a form or opening a dialog. Press handling and the keyboard contract come from base-react, so this layer is only appearance.

<Button>
<Icon name="add" />
Create
</Button>

Variant

Use variant to say what the button is for. At most one primary per view.

<Button variant="primary">Publish</Button>
<Button variant="secondary">Save draft</Button>
<Button variant="outline">Export</Button>
<Button variant="ghost">Preview</Button>
<Button variant="danger">Delete</Button>

Size

Use size to set the height: 32, 40 or 48px. Input and Select use the same three, so a field and its submit line up.

<Button size="s">Small</Button>
<Button size="m">Medium</Button>
<Button size="l">Large</Button>

Full width

fullWidth fills the container. Use it where the container is already the decision — a form, a sheet, a card — and leave it off in a row, where a button as wide as its label is what tells you how much it does.

<Button fullWidth>Continue</Button>
<Button fullWidth variant="secondary">
<Icon name="download" />
Export
</Button>

With icons

Nest icons directly inside the button, before or after the label. The size sets the glyph and the gap, and gives the icon's side a few pixels of padding back so it does not read as looser than the other.

l
m
s
<Button size="l"><Icon name="add" />Create</Button>
<Button size="l" variant="secondary">Export<Icon name="download" /></Button>
<Button size="l" variant="secondary">No icon</Button>
<Button size="m"><Icon name="add" />Create</Button>
<Button size="m" variant="secondary">Export<Icon name="download" /></Button>
<Button size="m" variant="secondary">No icon</Button>
<Button size="s"><Icon name="add" />Create</Button>
<Button size="s" variant="secondary">Export<Icon name="download" /></Button>
<Button size="s" variant="secondary">No icon</Button>

Icon only

Use iconOnly for a square button whose whole content is one icon.

<Button variant="ghost" iconOnly aria-label="More">
<Icon name="more_horiz" />
</Button>
<Button iconOnly aria-label="Add">
<Icon name="add" />
</Button>
<Button variant="secondary" iconOnly aria-label="Settings">
<Icon name="settings" />
</Button>
iconOnly squares the button but does not name it. Pass aria-label, or a screen reader has nothing to read.

Loading and disabled

loading swaps the label for a spinner and blocks interaction; disabled means not available. One says wait, the other says no.

<Button loading>Publishing</Button>
<Button disabled>Publish</Button>
<Button variant="secondary" disabled>Save draft</Button>

As a link

Use as="a" when it navigates. It keeps the tab order, the modified click, and the fact that a link ignores the space bar.

<Button as="a" href="/tokens/color" variant="secondary">
Read the color tokens
</Button>

Props

PropTypeDefaultNotes
variant'primary' | 'secondary' | 'outline' | 'ghost' | 'danger''primary'What the button is for, not what color it is.
size's' | 'm' | 'l''m'32, 40 or 48px tall. Shared with Input and Select.
fullWidthbooleanfalseFills the container. Off by default, since a button is as wide as its label. Cannot be combined with iconOnly.
iconOnlybooleanfalseSquare. Needs an aria-label, since there is no text to read. Cannot be combined with fullWidth.
loadingbooleanfalseShows a spinner, blocks interaction, sets aria-busy.
disabledbooleanfalseNot available. Distinct from loading, which means not yet.
as'button' | 'a' | 'div''button'Element to render. Non-button elements get button semantics applied.