Skip to main content

Storybook

Spinner

Indicates that a process is loading or in progress. Use for small or inline loading states. Don't use for large content areas — use a skeleton loader pattern instead.

Figma Storybook Docs

Description

What it does

Displays an animated circular indicator that communicates to users that a system process is underway and they should wait for it to complete.

Where it appears

Inside buttons during form submission, inline next to labels when fetching data, within small containers like cards or panels when their content is loading, and in toast or alert regions when a background task is running.

Why it exists

Government users frequently submit forms, run searches, or trigger exports that take a moment to complete. Without a loading indicator, users may submit twice or assume the system has failed. A spinner provides immediate feedback that the action was received and is being processed.

Dependencies

Button, Toast

Anatomy

PartRequired?Notes
Track Required The full circular path that the indicator arc travels along. Rendered as a faint ring using --op-color-border-default at reduced opacity.
Arc indicator Required The animated segment that rotates around the track. Inherits colour from the surrounding context or an explicit variant token.
Label (visually hidden) Recommended An accessible text label passed via aria-label or a visually hidden element. Announced by screen readers in place of the animation, which conveys no meaning to assistive technology.

Variants

Default

General-purpose loading state; inherits the current text colour.

Use within neutral containers, panels, or alongside body text when no specific brand colour is required.

Primary

Uses --op-color-interactive-default (green-400) to signal an in-progress action tied to a primary interaction.

Use inside or adjacent to a primary button that has been activated, or when confirming a key user action such as saving a consultation record.

Inverse

White arc on a dark or coloured background.

Use inside filled primary buttons, dark headers, or coloured banners where the default colour would not meet contrast requirements.

Muted

Reduced-prominence indicator using --op-color-text-tertiary.

Use for background or low-priority operations that should not compete with primary content, such as auto-saving a draft.

States

State Behaviour
Spinning The arc rotates continuously at a consistent speed. This is the only active state. The animation runs indefinitely until the process resolves or the component is removed from the DOM.
Reduced motion When the user has enabled prefers-reduced-motion, the continuous rotation is replaced by a pulsing opacity animation (fade in/out) so that motion-sensitive users still receive feedback without vestibular discomfort.
Hidden (resolved) Once the loading state ends, the spinner is removed or hidden and focus is managed to the resulting content or a relevant landmark, as appropriate.

Usage guidelines

When to use

  • A button action is in progress — for example, submitting a stakeholder engagement form or exporting a consultation report.
  • A small data region is fetching updated content, such as refreshing a stakeholder count or loading the next page of consultation responses.
  • An inline search is resolving results, displayed next to the search input.
  • A background auto-save is running on a community survey draft.

When not to use

  • When loading a full page or large content area — use a skeleton loader pattern instead, which better sets expectations about the content structure.
  • When progress can be quantified — use a progress bar (Progress Bar) so users know how much remains.
  • As a permanent or persistent element — spinners must always resolve. If a process has no deterministic end, show an error state with a retry action.
  • When the delay is under 300ms — avoid flashing a spinner for operations that complete almost instantly, as this introduces unnecessary visual noise.

Do / Don't

Do

Pair the spinner with a concise visible or screen-reader-only label that describes what is loading (e.g. 'Saving stakeholder record…').

Don't

Render the spinner alone with no accessible label. Screen readers will announce nothing meaningful about an unlabelled animation.

Do

Disable interactive controls (buttons, inputs) while the spinner is active to prevent duplicate submissions.

Don't

Leave the triggering button enabled while the spinner runs — users may click again, causing duplicate requests.

Do

Size the spinner to fit its container. Use the small size inside buttons and the default size in panels.

Don't

Place a large spinner inside a small button or tight inline context — it will break layout and look unpolished.

Do

Move focus to relevant content or show a success/error message once the spinner resolves.

Don't

Silently remove the spinner without any feedback. Users need confirmation that the action succeeded or failed.

Was this page helpful?

Updated 9 September 2026