Progress
Shows how far along a task is.
Installation
npx shadcn@latest add https://qure-ui.qure.ai/r/progress.jsonUsage
import { Progress } from '@/components/ui/progress'<Progress value={72} aria-label="Studies analysed" />value is required and runs 0–100 by default; pass min and max for another range. The
primitive keeps role="progressbar" and the aria-value* attributes in step, so the number is
announced without you writing any of it.
Progress is for work whose extent is known and whose end the user is waiting for. It is the wrong control for a proportion that is simply a fact — beds occupied, storage used, agreement between two readers. That is a meter, and dressing it as progress implies it is heading somewhere.
Determinate
Two bars at 28% and 72%. The indicator's width is set by the primitive and transitions over 240ms, so a value arriving in steps animates rather than jumps.
With a label and a value
The bar carries no text of its own. Put the name and the number in a row above it and point the
bar at the name with aria-labelledby — a bare bar with a percentage floating near it is two
unrelated things to a screen reader. Use tabular-nums on the figure so it does not jitter as
it counts.
A count rather than a percentage
Set max to the real total and pass the real count. "14 of 32 series" is more use than 44%, and
getAriaValueText puts the same sentence into the announcement rather than leaving a screen
reader to read out a bare number.
Inside a card
About 12 minutes remaining.
Where the job has a name, a subject and an estimate, those belong in a card and the bar is one
line of it. aria-label is enough here because the card title already says what is running.
Indeterminate
Pass value={null} when you cannot know the proportion — an upload that has not reported a
size, a job with no total. Do not fake it with an animation that implies a percentage.
Indeterminate is announced correctly (data-indeterminate lands on the root and the value text
becomes "indeterminate progress") but it has no look yet: the primitive leaves the indicator
without a width, and our stylesheet has no [data-indeterminate] rule, so the track renders
empty. Until it does, use a spinner for unknown-length work.
For something that finishes in under a second, no indicator at all is better than one that flashes. A progress bar that appears and vanishes reads as a glitch.
API Reference
Everything Base UI's Progress accepts. Our
wrapper renders the Root, Track and Indicator itself, so className reaches the root and the
parts are reached through their data-slot. The ones you will use:
Prop
Type