Loading Button
A Loading Button shows users that a request is in progress by displaying a spinner in place of its label.
When to Use
- for an action that waits on a request, such as “Save changes”
- when a Button would otherwise be
disabledwhile its request is in progress
Avoid disabling a Button while its request is in progress. If the Button has focus when it becomes disabled, focus moves to the page. LoadingButton keeps focus and reports aria-busy.
Anatomy
| Element | Usage |
|---|---|
| Content | Required |
| Container | Required |
| Spinner | Loading state only |
The content is the label and the icons of a Button. While the Button is loading, a Spinner is displayed over the content.
Behavior
The spinner appears 150ms after loading becomes true, so users never see it if the request finishes sooner. When the spinner has appeared, it stays for at least 400ms.
While the Button is loading, and until the spinner has disappeared, it has aria-busy and aria-disabled, and it keeps focus. Clicks, Enter, and Space are ignored. The label fades out and keeps its position, so the width of the Button doesn’t change.
Accessibility
A Loading Button has the role and the keys of a Button. Keyboard users can still move focus to it with Tab while it’s loading. The spinner is hidden from assistive technology, so the accessible name is still the label.
Installation
npx shadcn@latest add @summit/loading-buttonThe CLI also adds @summit/button and @summit/spinner.
Usage
To show the spinner while a request is in progress, pass its pending state to loading.
import { LoadingButton } from '@/components/ui/loading-button';
<LoadingButton loading={saving}>Save changes</LoadingButton>;API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
loading | boolean | Required | Shows the spinner after 150ms and keeps it visible for at least 400ms |
Other props are passed to the Button that LoadingButton renders. See Button for the variants and the sizes.