Spinner
Indeterminate loading indicator — an operation in progress with no
predictable duration (initial loading, network request). For known
progress, use ProgressBar.
When to use
| ✅ Use when… | 🚫 Avoid when… |
|---|---|
|
|
Size
The size prop accepts a number (px) or a CSS string. Without a value, it
uses 1em — inheriting from the context's font-size.
<Spinner size={50} />Color
Spinner supports all theme colors via color (maps to the SVG's
stroke).
<Spinner color="primary" />
<Spinner color="warning" size={32} />Countdown ring
variant="countdown" is a determinate ring: the arc drains over duration
(ms) and refills whenever cycle changes — pass the last poll timestamp
or a counter. It announces as role="timer", not as a loading status.
<Spinner variant="countdown" duration={15000} cycle={lastPollAt} color="primary" />Use it for "next refresh in…" next to polled data. For task progress with a
known percentage, use ProgressBar.
Composing with IconButton/Notification
Since the size inherits from font-size, the spinner fits naturally into any
slot that accepts an Icon.
<IconButton icon={<Spinner />} size="small" />
<Notification
type="block"
variant="primary"
title="please wait…"
message="We are processing your request"
icon={<Spinner />}
/>Accessibility
role="status" with the accessible name coming from label (default 'Carregando'). Use label to say what is loading when there is more than one region on the screen.
Keep only one Spinner announcing per loading region — several spinners
firing role="status" at once turn into noise for screen reader users.
<Spinner label="Loading statement" />When the spinner is decorative — there is already a visible loading text next to it — hide it to avoid duplicating the announcement:
<Flex gap="small" alignItems="center">
<Spinner aria-hidden />
<Text text="Loading statement…" />
</Flex>Properties
Prop | Type | Default | Description |
|---|---|---|---|
color | string | — | Theme token (`theme.colors`) used as `color`. Has lower precedence than
`contrast`: when both are provided, the contrast calculation wins.
Stays `string` (not the typed union): `color` is also an HTML attribute
(`<li color>`, etc.) and interfaces extending native props require
identical types on the name collision. |
containment | string | — | Containment marker for the `cq` channel: emits
`container-type` (+ `container-name` when the string form carries one,
e.g. `'inline-size card'`). Apply on the immediate wrapper of the
adapting component — NEVER on page-level shells. |
cycle | string | number | — | Restart key for the countdown. Any change (a poll timestamp, a counter)
refills the ring and starts draining again. Ignored by the
indeterminate variant. |
duration | number | 15000 | Countdown length in milliseconds. Ignored by the indeterminate variant. |
label | string | Carregando | Accessible name announced by screen readers (`role="status"`, or
`role="timer"` for the countdown variant). Override it to localize or
to say WHAT is loading.
When the spinner is purely decorative — another visible, associated
loading text already exists nearby — pass `aria-hidden`. |
legibility | "on-photo" | — | Reading-shadow preset for text over a photographic background
(`on-photo`). Replaces the inline `style={{ textShadow }}` in the
consumer (brasil_2030 radar, gap A3). Token emission is deferred until a
2nd consumer asks for the raw var (see backlog). |
pageShell | boolean | — | Centers the element and caps the width at `theme.layout.pageMaxWidth`.
The page shell of a classic centered layout. |
readable | number | boolean | — | Makes the `color` legible against the page surface: `true` = WCAG AA
(4.5), a number sets a custom floor. Ignored with `contrast`.
See the Layout Props concept page for the full semantics. |
size | string | number | — | Spinner size. Accepts a number (px) or a CSS string (`em`, `rem`, etc.).
When omitted, uses `1em` to inherit the context's `font-size` — so the
spinner stays naturally proportional wherever it is embedded. |
transform | string | — | CSS `transform` value (e.g. `translate(-50%, -33px)`). Never leaks
to the DOM as an attribute. |
variant | "indeterminate" | "countdown" | indeterminate | `'indeterminate'` spins forever. `'countdown'` is a determinate ring
that drains over `duration` and stays empty until `cycle` changes. |
Besides the props above, every component accepts the layout props (spacing, color, flex/grid, sizing, border) — not repeated here.
See also
- Storybook story: Components / Spinner
- Determinate alternative:
ProgressBar