Spinner
Something is happening and there is nothing to show yet.
Reach for Skeleton first
When you know the shape of what is coming — a list of rows, a card — a placeholder that matches the layout stops the page jumping when the content lands. A spinner is for when you genuinely do not know: a form submitting, a check running, a connection being tested.
Skeleton, for comparison
Sized to the content it replaces, so the page does not jump. A skeleton of the wrong height is worse than a spinner, because it promises a layout and then breaks it.
In both themes
light
dark
Guidance
Use it when
- An action in flight whose duration is unknown.
- A label saying what is loading, whenever a page can have more than one.
- Button's own loading prop when the wait belongs to a button — it disables and spins in one.
Reach for something else when
- A known proportion. That is Progress, and a spinner throws away information you have.
- A whole page. A screenful of nothing with a spinner in the middle tells the reader less than a skeleton of what is coming.
- Anything under about 300ms. A spinner that flashes reads as a glitch.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | "Loading" | Announced, not drawn. Say what is loading when the page has more than one. |
| size | "sm" | "default" | "lg" | "default" | Glyph size. |
Accessibility
role="status" with the label in an sr-only span and the glyph aria-hidden. Without the label a spinner is a silent animation — a blind user gets no signal at all that the page is busy, which is precisely the group that most needs telling. The rotation is safe under prefers-reduced-motion because tokens.css neutralises animation globally, so it becomes a static glyph rather than something each component has to remember.