Browse the docs

Spinner

Indeterminate loading indicator. It is an SVG with Tailwind's animate-spin on it, so there is no keyframe to add to your stylesheet and nothing to clean up when it unmounts.

Props

PropValuesDefaultDescription
size"sm", "md", "lg""md"Diameter of the circle.
labelstring"Loading"Accessible name. Pass "" to hide it from assistive technology.
classNamestring""Appended after the component's own classes.

All other <span> attributes are forwarded, including ref.

Common patterns

// Standalone, while a region loads
<Spinner label="Loading invoices" />

// Inside a button whose text already says it — silence the spinner
// so it isn't announced twice
<Button disabled>
  <Spinner size="sm" label="" />
  Saving…
</Button>

// Tinted to the accent instead of the muted default
<Spinner className="text-accent" />

Notes

The colour comes from currentColor, so the spinner inherits whatever text colour it sits in. It defaults to text-muted; override with a text utility.

For a determinate operation — one where you know the percentage — use Progress instead. A spinner tells the reader something is happening; a progress bar tells them how much longer.

Under prefers-reduced-motion, Tailwind's animate-spin keeps running. If that matters to you, add a rule to your stylesheet:

@media (prefers-reduced-motion: reduce) {
  .animate-spin {
    animation-duration: 2s;
  }
}