Components · Feedback & status

Progress

A determinate bar. It knows how much is done and says so, in the units the work is counted in.

Stable · v1.0 shadcn/ui WCAG 2.2 AA

Overview

Progress is the determinate half of a wait: the work has countable units and the interface can say how many are done. Where the count is not known, the honest control is Activity, and using it is not a lesser answer — inventing a fraction to look reassuring is.

This was one page

Progress, Activity, Skeleton and PendingValue were documented together under the title “Progress & activity”, and the code shipped as one item. The code was split first and the page was left, which was the wrong way round: most of what was on it — the shapes, the thresholds, the long wait, cancelling — was about the indeterminate case, filed under the determinate one's name. Three pages now, one per item.

Which to use

SituationUseWhy
Loading a list or a recordSkeleton Shows the shape of what is coming and reserves its space, preventing layout shift — see Motion.
Analysing a recording, uploading, exportingProgress (determinate) Steps or bytes are countable. Say how far.
A query of unknown durationActivity (indeterminate) Honest about not knowing.
A button awaiting a serverPending state on the button Feedback belongs on the control that was pressed — see Interaction states.
Background work the clinician need not wait forStatus chip Persistent, non-interruptive — see Status chip.
Two components, not one

The table above has always named these separately, and until recently they were one component with an optional value. That conflation produced both of the defects the split removes. max defaulted to 100, so a bar for seven of twelve leads rendered 7 % — a figure nobody computed, from a denominator nobody supplied. And the circular and inline shapes returned before reading value at all, so a determinate value passed with either was silently discarded. Progress now requires value, max and unit and has no shape; Activity has no value on its type.

Anatomy

Determinate · indeterminate · inline activity
Analysing 12-lead ECG7 of 12 leads
started 14:26:41~8 s remaining
Searching prior studiesduration unknown
started 14:27:02times out in 00:20
Contacting cath lab…
ElementRule
Label Names the work in clinical terms. "Analysing 12-lead ECG", not "Loading…".
Countable state Where determinate — steps, leads, bytes. Never a bare percentage where a unit exists.
Started at Absolute time. Lets a clinician judge whether something has stalled.
Bound Estimated remaining, or the timeout. Every indicator states one or the other.

What it must never do

Never blocks the alert region

Full-screen loading states, blocking overlays and progress modals are prohibited on patient-scoped screens. A busy system must still be able to alarm — see Elevation, where the alarm layer sits above everything. Work in progress occupies the region it belongs to and nothing more.

Timeout · a spinner that ended
Do
Analysing 12-lead ECG7 of 12 leads

Named work, countable units, real progress. A clinician can decide whether to wait.

Don't
Please wait…

Unnamed, unbounded, uninformative — and if this covered the screen it would also be hiding any alarm that arrived.

Formatting

What the component enforces, and what it only asks for

The fraction is held; what the fraction is counting is not.

RuleHeld by How
A bar cannot be shown without its denominatorThe component value, max and unit are all required. max used to default to 100, which turned 7 of 12 into “7 %”.
Asserted: Progress: the count is shown, not only a percentage
The count is shown, not only a percentageThe component “7 of 12 leads” renders as text and as aria-valuetext.
Asserted: Progress: the count is shown, not only a percentage
There is no shape that discards the valueThe component No shape prop. The circular and inline forms had nowhere to put a value and silently dropped it; they belong to Activity.
Asserted: Progress has no shape that could discard its value
The denominator does not change mid-flightYou You pass max on every render. Nothing here notices it grew.
Completion means successYou A full bar is a full bar. Whether the work succeeded, and whether part of it failed quietly, is yours to say beside it.
The last step is countedYou If the write to the record is not in max, the bar sits full while it happens.
Why this is written down

A rule stated on a component page reads as a rule the component keeps. 3 of these 6 are; 3 are obligations this page was quietly handing to the reader. Every way a fraction can be true and still mislead is on your side of this table.

Do's and don'ts

The determinate case. The other pairs moved to Activity and Skeleton.

Do
Analysing 12-lead ECG7 of 12 leads

Named work, countable units, real progress. The clinician can decide whether to wait.

Don't
Please wait…

Unnamed, unbounded, uninformative — and full-screen it would be hiding any alarm that arrived.

The pairs below are about the determinate bar specifically: what a fraction claims, and the ways a fraction can be true and still mislead. The indeterminate cases are on Activity.

Do
Analysing 12-lead ECG12 of 12 leads

Finished with 3 leads unreadable. V4–V6 excluded — anterior interpretation limited.

The bar reached the end and the work did not succeed. Those are two different facts and the bar can only carry one of them.

Don't
Analysing 12-lead ECG12 of 12 leads

Complete

Twelve counted, nine analysed. A clinician reads a full bar as a finished job and takes the interpretation at face value, including the part of the heart nobody looked at.

Do
Loading prior studies7 of 40 studies

Scope known before the count started.

The denominator was settled first, so the fraction means the same thing at the end as it did at the beginning.

Don't
Loading prior studies7 of 12 studies

… a moment later: 7 of 40 studies

The set grew as it was read, so a bar that looked nearly done is now a fifth of the way. The clinician who decided to wait made that decision on a number that no longer exists.

Do
Filing the report4 of 5 steps

Writing to the record…

The commit is a step and it is counted. The bar is at four fifths because one fifth of the work has not happened yet.

Don't
Filing the report4 of 4 steps

(still writing to the record)

Full for eleven seconds while the write completes. The reader concludes it is either finished or stuck, and both conclusions are wrong — one of them navigates away mid-write.

Do
Uploading study7 of 12 series

Connection dropped at series 8. Resuming from 7 — nothing already sent is being sent again.

A retry keeps the count and says what happened. Progress that stalls and explains itself is still progress.

Don't
Uploading study2 of 12 series

… it was at 7 of 12 a second ago

The bar went backwards with no explanation. A clinician watching a transfer to another site cannot tell a retry from data being lost, and the second reading is the one that gets acted on.

Do
Exporting — HARLAND, A. · MRN 44 812 9073 of 9 studies

Continues in the background. Named wherever it is shown.

Work that outlives the screen it started on carries the patient it belongs to, so it cannot be read as belonging to whoever is on screen now.

Don't
Exporting studies3 of 9 studies

Now viewing: OKAFOR, C. · MRN 51 330 264

The export is for the previous patient and the header is for this one. Nothing on the bar says so, and the interface has put one patient's work under another patient's name.

Accessibility

Outcomes of use

Clinical safety notes

Risk controls this page specifies

Trace these in your risk file (ISO 14971) and usability engineering file (IEC 62366-1). Which of these the component keeps and which are yours is stated in the guarantees table; a control the component does not keep is one your risk file must show you keep.

Implementation

$ npx shadcn@latest add https://md.notjustany.tech/r/progress.json
<Progress
  label="Analysing 12-lead ECG"
  value={7} max={12} unit="leads"   // all three required
  startedAt="14:26:41"
/>

// No shape prop: a determinate value has to be shown somewhere, and the
// circular and inline forms had nowhere to put it — they used to discard
// it silently. Those shapes belong to Activity.
NotJustAnyMed.Tech Design System · Progress & activity · v1.0 · draft for review
Reference applications named in this system are fictional; all patient data shown is fabricated.