Spinner
A CSS-only animated loading indicator. Communicates asynchronous activity to both sighted users and screen readers via role="status" and an accessible label.
When to use
Do
- ✓Use to indicate an ongoing background operation such as data fetching, file upload, or form submission.
- ✓Place inline with text for subtle progress feedback (sm size).
- ✓Use the lg size for full-page or panel-level loading states.
- ✓Always provide a meaningful label for screen readers — avoid the generic default when context is available.
- ✓Pair with a disabled button to prevent duplicate submissions during async operations.
Don't
- ✕Don't show a spinner for operations that complete in under 300ms — a flash of spinner is more disruptive than no feedback.
- ✕Don't use a spinner as a skeleton-screen replacement — use skeleton components for layout-level loading.
- ✕Don't leave the spinner on screen indefinitely — always handle errors and timeouts.
- ✕Don't use the spinner purely decoratively without a live region — it won't be announced to screen readers.
- ✕Don't omit the label prop when the surrounding context doesn't describe the operation.
Size guidance
sm (14px) — Inline with text, inside buttons, or inside compact UI controls. Use when the surrounding text already communicates context.
md (16px) — Default. Use for component-level loading states such as loading a card, a table row, or a form field.
lg (20px) — Use for full-panel or full-section loading states where the spinner is the primary visual focus.
Label guidance
The label prop sets the aria-label on the host element and is announced by screen readers when the spinner appears. The default value is "Loading". Provide a more specific value whenever possible:
label="Saving changes"- during form auto-savelabel="Uploading file"- during file uploadlabel="Loading results"- while fetching search results