Components

Progress

Displays an indicator showing the completion progress of a task, such as a file upload or a multi-step form.

Basic usage

Pass a value between 0 and 100 to set how full the bar is.

Values

The indicator animates to the supplied value. An empty bar is 0 and a full bar is 100. The track keeps a --control-edge border so the 100% mark — and the control itself at value={0} — stays visible against the page.

Tones

tone recolours the bar and its track to the same ink step, so every tone keeps the same fill-versus-track structure. Those pairs were measured on the high-contrast palette, where they run 4.25:1 to 6.52:1. The default palette differs in light mode: there --primary-ink is --primary gold #E8B824, so default reads 1.55:1 against its track and 1.73:1 against the page — a recorded trade-off of the approved build, not a component defect. Use success for a finished job, warning as a quota approaches its ceiling, and destructive once it is over.

The warning tone also cuts diagonal hazard stripes through the filled part. That is not decoration: Comitor's brand is gold and warning is yellow, so --warning-ink and --primary-ink collapse to the same colour on three of the package's four palettes. The stripes carry the signal as shape, so it survives greyscale and colour blindness — never strip them off in a className override.

default
success
warning
destructive

Indeterminate

Leave value undefined while the total is still unknown. Radix marks the root data-state="indeterminate" and drops aria-valuenow; the package deliberately ships no sweep animation, so add one in your app or reach for Spinner when there is nothing to measure.

With a label

Progress bars carry no visible text on their own. Pair the bar with a heading and a percentage to give it context.

Uploading files72%

Variant helpers

progressTrackVariants and progressBarVariants are exported from @comitor/ui. Reach for them when you need a bar shape Radix cannot express — a stacked or segmented meter, for instance — so the custom markup inherits the same tokens instead of hand-picking colours.

Storage used40%

Props

PropTypeDefaultDescription
valuenumber | nullCompletion percentage from 0 to max. Omit it (or pass null) for the Radix indeterminate state, where the bar stays at 0.
tone'default' | 'success' | 'warning' | 'destructive''default'Recolours both the bar and its track to the matching ink step. warning additionally cuts hazard stripes through the bar, so it stays distinguishable without colour.
maxnumber100Maximum value the progress can reach. Inherited from the Radix Progress root.
getValueLabel(value: number, max: number) => stringBuilds the aria-valuetext string announced by screen readers.
classNamestringAdditional Tailwind classes merged onto the track — e.g. set a custom height with h-3.
...restProgressPrimitive.Root propsAll Radix Progress root props are forwarded to the underlying element.

Accessibility

  • Built on Radix Progress, the root element has role="progressbar" with aria-valuenow, aria-valuemin, and aria-valuemax set automatically.
  • Provide an accessible name with aria-label or aria-labelledby pointing at a visible heading so screen readers can announce what is loading.
  • The filled part is painted with --primary-ink rather than --primary, and the track carries a --control-edge border. That splits the two jobs WCAG 1.4.11 asks for: the border outlines the control against the page, the fill-versus-track pair carries the ratio.
  • Tone is never the only signal. warning adds hazard stripes precisely because colour alone cannot separate it from default on the high-contrast and dark palettes (WCAG 1.4.1).
  • Stripes say “approaching the limit”, not what the limit is. Keep an Alert, a StatusPill, or a line of text-warning-ink next to the bar to spell out the threshold and the next step.
  • Avoid using a progress bar as the sole feedback for very long operations — pair it with a live region announcement when the value changes significantly.