Skip to content
SproutAceve · v3.31.0
Overview What is your role? Connect to Sprout MCP reference Adopting Sprout
Brand & logos Color Typography Spacing & layout Elevation Iconography Accessibility
Overview Alert Avatar Badge Breadcrumb Buttons Cards Checkbox Data grid Dialog Dropdown button Fab button Floating tabs Inputs Menu Navigation Numeric input Progress bar Progress ring Radio button Ribbon toolbar Switch Tabs Tag Tooltip
Interaction & motion Voice & content Product patterns
AI patterns AI transparency & disclosure AI disclosure label
Design principles Personas Trust and ethics Meet the makers
Build the systemplay Tower of tokensplay Site runnerplay
How it works Changelogv3.31 Roadmap Contribute
Components

Progress ring.

A progress ring is the circular counterpart to the progress bar — the same status, in a compact footprint that fits inside a card, a dashboard tile or a button. Use determinate whenever a percentage is knowable; indeterminate spins continuously for a duration that genuinely can't be predicted.

Colour

65%
primary
65%
neutral
65%
info
65%
success
65%
warning
65%
danger

Size

Two sizes, matching the Figma Size variant (100 / 200px). Track and indicator width stay a fixed 4px at both sizes.

70%
Small — 100px
70%
Large — 200px

Value label

The Figma component's Show value boolean — an optional centred percentage. Omit it when the number already appears beside the ring.

45%
Show value: yes
Show value: no

State

Determinate shows a real value. Indeterminate — not part of the Figma component — is a token-built addition for when the duration genuinely can't be known.

82%
Determinate — a known percentage.
Indeterminate — duration unknown. The arc spins continuously; never shows a value.

Anatomy

60%
TrackThe full circle, var(--surface-3), 4px stroke — always visible as the total the arc is measured against.
IndicatorThe coloured arc, same 4px stroke, round line cap. Starts at 12 o'clock and sweeps clockwise with the value.
Size100px (small) or 200px (large). Track and indicator width stay fixed at 4px at both sizes.
Value labelOptional, centred. 14px at 100px size, 20px at 200px size. Omit it when the number already appears elsewhere on the screen.

Do & don't

38%
Do — use the ring where a bar won't fit — a dashboard tile, a card corner, inside a button.
38%
Don't — use the large ring for a minor, low-stakes status. Size should match how much attention the progress deserves.
Do — reach for indeterminate only when no percentage can honestly be computed, like an open-ended network request.
Don't — show a determinate ring frozen at 0% while work is actually happening — that reads as broken, not as progress.

Accessibility

role="progressbar"On the wrapping element, not the SVG — screen readers announce the role once, on the container that owns the value.
aria-valuenow / min / maxDeterminate only. Omit all three on an indeterminate ring rather than reporting a number that doesn't exist.
aria-label / aria-labelledbySay what is progressing — "Report generating" — not just "Progress". The ring carries no text of its own unless Show value is on.
ColourNever the only cue, same rule as Progress bar, Alert and Badge — pair a status colour with the label or surrounding copy.
Reduced motionThe indeterminate spin honours prefers-reduced-motion and the in-app Motion: reduced setting — the arc freezes in place rather than rotating, same mechanism as the skeleton loaders and the indeterminate progress bar.
Live updatesA determinate ring whose value changes while off-screen should sit in an aria-live="polite" region.

Props (React)

No primitive ships yet — this is the target API if one is built, not something you can import today.

type ProgressRingProps = {
  value?: number;            // current amount
  max?: number;               // default 100
  color?: "primary" | "neutral" | "info" | "success" | "warning" | "danger";
  size?: 100 | 200;           // small or large
  trackWidth?: number;        // default 4
  showValue?: boolean;        // renders a centred "NN%" label
  indeterminate?: boolean;    // spins continuously; value/max are ignored
  label: string;              // required — feeds aria-label
};
← PreviousProgress barNext →Radio button
Sprout · Aceve Design System · v3.31.0
Figma library GitLabReleases