Spinner
An indeterminate loading indicator.
Spinner signals that something is loading and you cannot say how far along it is. When you can show progress — a known percentage or step count — use a determinate indicator instead.
Variants
Pixel
The default. Spells B A S E on a 5×5 pixel grid. Each letter fills in pixel by pixel, holds, then clears for the next. Use it when a page, a card, or another large region is loading; it needs the room to read.
<Spinner className="size-8" />Circle
A rotating arc on a faint track. Use it inside controls: Button's pending
status shows it at the button's icon size, where the other two variants are
too small to read.
<Spinner variant="circle" className="size-8" />Square
The Base square hops, turns a quarter in the air, and squashes as it lands.
A branded alternative to Pixel for a card or a page region, at size-6 or
larger.
<Spinner variant="square" className="size-8" />Sizes
Small
<Spinner className="size-4" />Medium
<Spinner className="size-6" />Large
<Spinner className="size-8" />Spinner has no size prop — set its dimensions with a size-* class and its
colour with text-*, since it draws in currentColor.
When to use
Use Spinner for a wait of unknown length whose result has no predictable shape.
Use something else when:
- The incoming content has a predictable structure. Use Skeleton.
- A button is waiting on its own action. Use the button's status states.
Usage
Do
Match the spinner to the surface it sits on — circle inside a control,
pixel or square at size-6 or larger when a page or card is loading.
Don't
Put pixel or square inside a button or other small control. At small
sizes the letters and the hop blur into noise; use circle there.
Don't
Show a spinner for waits under a moment. A control that flickers into a spinner and back reads as broken, not busy.
Props
| Prop | Type | Default |
|---|---|---|
render | Type((props: SVGProps<SVGSVGElement>) => ReactElement<unknown, string | JSXElementConstructor<any>>) | Default— |
strokeWidthStroke width of the `circle` variant. | Typenumber | Default3.5 |
variantThe shape of the loading animation. `pixel` (the default) spells | Type"pixel" | "circle" | "square" | Defaultpixel |
Accessibility
Spinner is an animated svg with no implicit role, so it announces nothing on
its own. Give the region it loads an accessible status — for example a
container with role="status" and a label like "Loading" — so the wait is
conveyed without relying on the animation.
When reduced motion is on, the pixel and square variants stop animating:
Pixel shows a still B and Square rests in place. Circle keeps rotating, since
the rotation is the only thing that tells it apart from a ring.