/// Feedback
Spinner
A minimal 1em border spinner that announces an indeterminate loading status inline.
import { Spinner } from "@protocore/pds";Basics
A single spinner. It carries role="status" and a visually-hidden label so assistive tech announces the wait.
Sizes
Three diameters — sm (14px), md (18px), lg (24px). The spinner scales to 1em, so it also inherits the font size of its context.
Inline with a label
Pair the spinner with visible text for anything longer than a beat, so sighted users get the same context the label gives screen readers.
When to use it
Reach for a Spinner when the wait is short and its length is unknown — a button submitting, a panel fetching, a row saving. It says *something is happening* without implying a measurable amount.
- Known, measurable progress (upload, migration, sync)? Use ProgressBar instead — a spinner that never ends reads as a hang.
- Replacing a specific block of content that is about to appear? Use LoadingSkeleton — it holds the layout and reduces the shift when data lands.
- Inside a submitting button? Button has a built-in
loadingstate; don't nest a bare Spinner in it.
Usage
Do
- Give every Spinner a meaningful `label` ("Loading ledger", not the default).
- Use it for short, indeterminate waits where progress can't be measured.
- Match the size to the surrounding text or control.
- Show visible text alongside it once a wait exceeds a second or two.
Don't
- Use a Spinner for long or measurable work — that's a ProgressBar.
- Cover a whole page in one when a skeleton would preserve the layout.
- Render more than one Spinner for a single logical wait.
- Nest a Spinner inside a Button that already has a `loading` prop.
Accessibility
- The root is `role="status"` (an `aria-live="polite"` region), so the `label` is announced when the spinner mounts.
- The spinning ring is `aria-hidden`; only the visually-hidden label text is exposed.
- The animation respects `prefers-reduced-motion` via the shared PDS keyframes.
- A Spinner alone is not focusable and takes no keyboard interaction — it is a status indicator, not a control.
Mobile (React Native)
Preview. @protocore/pds-mobile ships the React Native sibling of Spinner. It mirrors the web API where React Native allows; the package is a preview with no device-level QA yet, so pin it and expect small changes.
Import it from the mobile package (not @protocore/pds), inside a <PdsProvider> — there is no stylesheet, so style (a ViewStyle) replaces className and every value comes from the theme:
import { Spinner } from "@protocore/pds-mobile";Parity with web. Wraps the native ActivityIndicator (web is a CSS border-spinner).
sizemaps to a dp diameter (sm14 ·md18 ·lg24) and is tinted withink.labelis announced to assistive tech.
<Spinner size="md" label="Loading deployments" />Spinner props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | |
label | string | Loading | Accessible status label announced to assistive tech. |
size | enum | md | Diameter preset: `sm` 14px · `md` 18px · `lg` 24px. |
style | CSSProperties | — |