Progress ring
Shows how much of a task is done as a small ring that fills from 0 to 100. For a value against a target, use Gauge.
Installation
The CLI installs the Radix or Base UI file to match your project.
If your project doesn't have Wisty UI's theme yet, add it once with npx shadcn@latest add @wisty/cosmos. Until then, components keep shadcn's default look. Installation has the details.
When to use
Use it
- A task is partly done and you know how much, like a profile's completion, an import's progress or a setup step, and there's room for a small ring but not a bar.
- Time or a quota runs down, like the days left to respond to a case. Use
direction="drain". - The share needs a status beside it: the step people are on (
active-step), running late (warning), out of time (expired) or done (complete). - It replaces
lightning-progress-ring.
Don't use it
- You don't know how long the work will take. Use Spinner.
- There's room for a bar, or the progress is the main thing on the page, like an upload. Use Progress.
- A value is measured against a target, with ranges like behind and on track, like quota attainment. Use Gauge.
- People work through named steps in order. Use Progress indicator.
- You want to show the percent. Write it beside the ring, never in it. For a large dial with its value inside, use Gauge.
Usage
import { ProgressRing } from "@/components/wisty/progress-ring"<ProgressRing value={40} aria-label="Data import" />valueis a percent, from 0 to 100. Passnullwhen it isn't known yet, so the ring stays empty and screen readers hear no value.- Children go inside the ring: a step number, as a setup list numbers its steps. The warning, expired and complete variants show their icon there instead.
- With
variant="base-autocomplete", the ring turns complete, with a check, whenvaluereaches 100.
Examples
Variants
Base, active step, warning and expired at 60, then complete at 100, with the warning, expired and complete icons each carrying a hidden word.
Step number
A Setup Assistant step: a large `active-step` ring a third done, with the step number "2" as its children.
Countdown
With `direction="drain"`, the ring empties counterclockwise as time runs out, named by the text beside it through `aria-labelledby`.
Sizes
The default medium ring and `size="large"`, both at 40.
Completes at 100
With `variant="base-autocomplete"`, rings at 0 and 50 stay base, and the one at 100 turns complete with a check.
API reference
ProgressRing
| Prop | Type | Default | Description |
|---|---|---|---|
aria-label | string | Names what the ring measures, like "Upload progress". | |
aria-labelledby | string | The id of visible text that names what the ring measures. | |
children | React.ReactNode | A step number or one glyph inside the ring. Not shown with an icon. | |
variant | "base" | "base-autocomplete" | "active-step" | "warning" | "expired" | "complete" | "base" | |
size | "medium" | "large" | "medium" | |
value* | number | null | How much is done, from 0 to 100. Clamped. null when it isn't known. | |
direction | "fill" | "drain" | "fill" | fill grows the ring clockwise; drain empties it counterclockwise. |
iconLabel | string | Replaces the icon's hidden word ("Warning", "Expired", "Complete"). |
Also takes every <div> (opens in a new tab) prop.
SLDS mapping
ProgressRing is slds-progress-ring. The progressbar inside it is slds-progress-ring__progress, holding the arc, slds-progress-ring__path. Children and the variant's icon go in slds-progress-ring__content, and the dot at the arc's end is slds-progress-ring__progress-head.
Known gaps:
- The warning, expired and complete icons are Lucide's triangle alert, ban and check, standing for
utility:warning,utility:errorandutility:check. - The blueprint's warning and expired colors without their icon aren't a variant. Like
lightning-progress-ring, those variants always show it.
| Prop | Value | SLDS | Notes |
|---|---|---|---|
variant | base (added) | slds-progress-ring | Default. |
variant | base-autocomplete (added) | slds-progress-ring, slds-progress-ring_complete at 100 | Base until the value reaches 100, then complete with a check, as lightning-progress-ring's variant. |
variant | active-step (added) | slds-progress-ring_active-step | The step people are on, in the brand color. |
variant | warning (added) | slds-progress-ring_warning | A warning icon inside the ring (utility:warning). |
variant | expired (added) | slds-progress-ring_expired | An error icon inside the ring (utility:error). |
variant | complete (added) | slds-progress-ring_complete | A check on a filled circle (utility:check). |
size | medium (added) | slds-progress-ring | Default. |
size | large (added) | slds-progress-ring_large | |
direction | fill (added) | slds-progress-ring__path, swept clockwise | Default. |
direction | drain (added) | slds-progress-ring__path, swept counterclockwise |
Accessibility
- Name the ring with
aria-label, or pointaria-labelledbyat visible text beside it. Say what it measures, like "Upload progress". - The value is read as a percent of 100. To show a count, like 3 of 7 days, pass its percent and write the count beside the ring.
- The warning, expired and complete icons are read as a hidden word: "Warning", "Expired" or "Complete". Translate it with
iconLabel. - Children are read after the progressbar, not as its value. A bare "2" says little, so put the step in the label too, like "Step 2 of 4".
- The ring is never focusable. Don't put a link or button inside it.
Motion
- The arc doesn't animate. A new value jumps into place, in every theme.
Rules
- Keep
valuea percent. Convert a count or an amount first, likeMath.round((done / total) * 100). - Use
variant="complete"only at 100. To turn complete when the task finishes, usebase-autocomplete. - Children are a step number or one glyph, never a percentage or a word. The ring is sized for one or two characters.
- Never pass
asChildorrender.