Button
Loading without layout shift, shortcuts, tooltips and a built-in confirm step.
Installation
npx shadcn@latest add @quireui/buttonUsage
<Button variant="primary" onClick={save}>
Save changes
</Button>Variants and sizes
variant: primary, secondary (default), ghost, danger.
size: sm, md (default), lg, icon. Sizes follow the density setting.
Loading
loading disables the button and keeps its width. The spinner only appears if loading takes longer than 150ms, so fast actions never flash one.
The quick one never shows a spinner. Neither button changes width.
<Button variant="primary" loading={saving} onClick={save}>
Save changes
</Button>Shortcut
shortcut shows the key hint and binds it on the page. mod is ⌘ on Apple devices and Ctrl elsewhere. Shortcuts without a modifier never fire while someone is typing.
Press the shortcut anywhere on the page. Saved 0 times.
<Button variant="primary" shortcut="mod+s" onClick={save}>
Save
</Button>Tooltip
tooltip shows on hover and focus. On icon buttons it also becomes the accessible label, so they can't ship unlabelled, and the shortcut moves into the tooltip.
<Button size="icon" variant="ghost" tooltip="Bold" shortcut="mod+b">
<TextBIcon />
</Button>Confirm
confirm adds a second step without a dialog. The first click swaps to the confirm label, the second runs onClick. It resets after 3 seconds, on blur, or with Esc. Both labels share one space, so the button never changes width.
3 invoices left.
<Button variant="danger" confirm="Click again to delete" onClick={remove}>
<TrashIcon /> Delete invoice
</Button>Changing labels
For labels that change on their own, pair the button with the optional Text morph.
<Button onClick={toggle}>
<TextMorph>{following ? "Following" : "Follow"}</TextMorph>
</Button>Accessibility
It is a native button. While loading it is marked busy and keeps its label, so screen readers never hear it go blank. An icon-only button takes its name from tooltip, and a shortcut is exposed as aria-keyshortcuts.
| Key | Action |
|---|---|
| Enter / Space | Runs onClick. With confirm, the first press arms the button and the second runs it. |
| Esc | Cancels an armed confirm step. |
| Tab | Moves focus. Leaving the button also cancels an armed confirm step. A loading button stays in the tab order. |
The shortcut keys | Clicks the button from anywhere on the page. Shortcuts without a modifier never fire while someone is typing. |
API reference
Button
Prop
Type
Also takes every prop of Base UI's Button. Style it with [data-slot="button"].