Skip to main content
Graphite UI

Progress bar

A thin bar that shows how far a task has run, or that it is running when the end is unknown. Use it for work in motion, not for a quantity at rest like storage used.

Contract 2.0.0Kit · 3 sets · 31 variantsOpen in Figma

Live preview

Rendered by the component itself from the same generated tokens as the rest of the site.

Uploading report.pdf
About a minute left

Installation

Install it with the shadcn CLI, along with everything it uses. New project? Set it up first, as Quick start shows.

npx shadcn@latest add https://www.graphite-ui.com/r/progress-bar.json
import { ProgressBar } from '@/components/ui/progress-bar'

Anatomy

The label above the track, which is also its accessible name, and an optional helper below, 8 from it on each side. Nothing is ever painted inside the track.

Uploading report.pdf
About a minute left
  1. LabelRequiredThe task, painted above the track (beside it inline) and the bar's accessible name. hideLabel keeps the name and drops it from view.
  2. Helper textOptionalUnder the track, replaced by the success or error message once the task finishes. Not drawn inline.

Variants

Determinate when you know the total, indeterminate when you do not. Size is a 4px or 8px track. Alignment puts the label above, beside, or above and indented. Once the task ends, Success and Error fill the track and say so.

Variant: Determinate
Uploading report.pdf
About a minute left
Variant: Indeterminate
Preparing the export
This can take a while
Size: Big
Uploading report.pdf
About a minute left
Alignment: Inline
Uploading
Alignment: Indent
Uploading report.pdf
About a minute left
State: Success
Uploading report.pdf
Upload complete
State: Error
Uploading report.pdf
The upload failed. Try again.

API reference

Generated from the contract, versioned with it, and checked by drift-check. This table cannot describe props the component does not have.

Progress bar props
PropTypeDefaultNotes
value0–100—
variant'determinate' | 'indeterminate'—
size'sm' | 'lg'—The kit's Size, a 4px track (Small) or 8px (Big).
alignment'default' | 'inline' | 'indent'—The kit's Alignment. Default puts the label above and the helper below, 8 from the track; Inline puts the label beside a track that fills the rest, with no helper; Indent sets the label in Input Label type and indents label and helper 16.
status'active' | 'success' | 'error'—The kit's State. A finished task fills the track in success or danger, with the kit's status icon at the end of the label row and its message in place of the helper.
hideLabelboolean—
helperText——
successText——
errorText——

Design tokens

Every swatch is live. Change the source color in the header and this table repaints, because it reads the same roles the component does.

  • outlineThe track, through its subtle step (outline-subtle, the kit's border-subtle-00). It reads faintly against the page by design; the label and value carry the meaning.
  • primaryThe fill while active.
  • successThe fill and the status icon once the task succeeds.
  • dangerThe fill, the status icon and the message once the task fails.
  • on-surfaceThe label.
  • on-surface-variantThe helper and success messages.
  • textThe label at Body/3 (Input Label when indented), messages at 12/16.
  • spacingTrack height, the 8 between label, track and message, and the 16 indent and inline gap.
  • motionIndeterminate sweep duration and easing, defined once and shared with Spinner.
  • radiusTrack and indicator corner.

Usage

The contract's prohibitions, written as the choices you will actually face.

Do

  • Name the task in label and let the bar paint it. Use hideLabel only when a richer label already sits beside it, and the bar still keeps the name.
  • Switch to determinate as soon as you know the total. A bar heading toward an end is easier to wait on.
  • Name the task in label, like “Uploading report.pdf”, rather than “Progress”.
  • Set status to success or error when the task ends, with a message that says what happened next.

Don’t

  • Paint the percentage inside the bar. The track has no room and no slot for text; put it in the label or the helper.
  • Turn the fill green or red while the task is still running. Success and danger are for a finished task only.
  • Give the sweep its own duration or easing. The motion tokens set it once for every indeterminate indicator.
  • Use it for a value that is not moving, like a quota. It announces as progress, so a reader waits for it to finish.

Accessibility

What the component does for you, and what it leaves to you.

Roles
role="progressbar" with aria-valuemin 0, aria-valuemax 100 and aria-valuenow set to the current value.
Indeterminate
All three value attributes are dropped. Leaving out aria-valuenow is what tells assistive tech the end is unknown.
Labels
label is required, painted, and names the bar through aria-labelledby; hideLabel keeps it as the name while dropping it from view. The helper, success or error message is linked with aria-describedby.
Outcome
Success and error set the value to 100 and announce their message as a status when it arrives. The status icon is decorative: the message carries the meaning.
Values
Values outside 0 to 100 are clamped before they reach the width or ARIA, so the two always agree.
Motion
The sweep is a quarter of the track at a constant speed, as the kit runs it. Under prefers-reduced-motion the width stops animating and the sweep slows to 3 seconds rather than stopping, so the bar still reads as working.

Figma parity

The kit's Progress bar page ships 31 variants across 3 sets. The code exposes 9 props. This table is where those two facts are reconciled instead of quietly diverging.

Kit axes and how they map to code
Kit axisValuesCodeHow it maps
Progress0% · 25% · 50% · 75% · Indeterminate · Success · Errorvalue · variant · statusThe percentages are value, and any number from 0 to 100 works. Indeterminate is variant="indeterminate". Success and Error are status.
StateActive · Success · ErrorstatusA finished bar fills in success or danger, with the kit’s status icon at the end of the label row and its message in place of the helper.
SizeSmall · Bigsizesm and lg: a 4px or 8px track.
AlignmentDefault · Inline · IndentalignmentLabel above; beside, hugging, 16 before the track and with no helper; or above in Input Label type with label and helper indented 16. The kit draws Inline only with a 4px track; the code allows either size.
Trackborder-subtle-00—outline-subtle, the kit’s value. It was outline, a much darker track, until 2.0.0.
Status icons · messagesCarbon status icons; Caption/1 and Helper Text—One 12/16 message style for all three; the kit’s own Succeeded and Failed status icons.