Skip to content

shadcn.io is an independent project built on shadcn/ui

Free

Loading Button (Standard) for React

A filled button, disabled, with a spinner and the word Loading, while the main action is still running its request.

The default button turns the click off and shows a spinner in front of Loading. A spinner on a button that still clicks will fire the request twice.

Use it for Save or Submit from the moment you send until you get an answer. If the wait is the whole page, a Spinner outside the button is clearer. In React, Base UI leaves the button disabled only while you keep it disabled.

Preview

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.
Use email insteadNo credit card

Anatomy

Button anatomy: root, icon, text

Usage

<Button disabled>
  <Spinner data-icon="inline-start" />
  Loading
</Button>

FAQ

Does this demo use isLoading?

No. It passes disabled, renders a Spinner with data-icon="inline-start", and keeps the word Loading. This one leaves variant off, so the primary fill stays while it runs.

When would I use isLoading instead?

isLoading hides the label visually, centers a spinner, keeps the button's width, sets aria-busy, and disables the button. Use this demo's pattern when the word should stay visible beside the spinner.

Why is the button disabled?

So a second click can't start the request again. You set disabled yourself here. isLoading does that for you. This demo doesn't.

Can the label say something other than Loading?

Yes. The children after the spinner are ordinary text. Saving, or Deleting 3 items, is fine. The demo says Loading so the state is obvious.

Will the spinner be announced as well as the word?

The spinner's default accessible name is Loading, and it has role="status". The button already says Loading, so pass aria-hidden on the spinner if once is enough. The demo doesn't.

Which variant is the loading button?

This one leaves variant off, so the primary fill stays while it runs. The spinner uses the button's text color. It doesn't pick a variant of its own.

API Reference

Button

Sets disabled. The rest is on the Button page.

Spinner

Sets data-icon="inline-start". The rest is on the Spinner page.