Skip to content
Component installs need the registry setup
VegaStack Design

Progress

Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.

Status
stable
Since
0.1.0
Accessibility pattern
ARIA progressbar

Last updated

x

Install

Configure registry credentials first using the Quickstart. Before copying this item or any transitive registry dependency, verify the signed manifest and save the exact bytes for Progress before installation. Retain the digest printed by this command.

pnpm exec vegastack-design verify progress

Install with the pinned shadcn CLI. Bare shadcn does not verify VegaStack signature or integrity.

pnpm dlx shadcn@4.21.0 add @vegastack/progress

Run the exact offline --post-write command printed by the preflight, using its saved item path and independently retained --expected-integrity digest. Use the saved preflight for every transitive registry dependency too; stop on any mismatch before using the components.

Usage

import { Progress } from "@/components/ui/progress";

<Progress value={33} />;

value is required. Pass null for a task whose extent is not known yet — the root reports data-status="indeterminate" and drops aria-valuenow.

x

Anatomy

Progress — data-slot="progress"
ProgressTrack — data-slot="progress-track"
ProgressIndicator — data-slot="progress-indicator"
ProgressLabel — data-slot="progress-label"
ProgressValue — data-slot="progress-value"

Examples

Composition

Progress renders its own ProgressTrack and ProgressIndicator after whatever children it is given, so a bar with a label and a read-out is two children and nothing else. ProgressTrack and ProgressIndicator are exported for the cases that need the lower-level parts.

Progress
├── ProgressLabel
├── ProgressValue
└── ProgressTrack
    └── ProgressIndicator
Upload progress
x

Label

Use ProgressLabel and ProgressValue to add a label and value display. ProgressLabel names the role="progressbar" through aria-labelledby, so a labelled bar needs no aria-label of its own; ProgressValue formats the current value with Intl.NumberFormat and takes format and locale from the root.

Upload progress
x

Controlled

value is a controlled prop — there is no uncontrolled mode and no internal timer. Drive it from whatever owns the task's state; here a Slider stands in for the upload.

x

RTL

Wrap the subtree in DirectionProvider direction="rtl". The track fills from the inline start, and ProgressValue takes a render function, which is where a locale's own numerals belong.

تقدم الرفع
x

Playground

Move the bar's value and copy the generated JSX.

Upload progress
x
<Progress value={50}>
  <ProgressLabel>Upload progress</ProgressLabel>
  <ProgressValue />
</Progress>

API Reference

Progress, ProgressTrack, ProgressIndicator, ProgressLabel and ProgressValue add no props of their own — each accepts everything the corresponding Base UI Progress part accepts (Root, Track, Indicator, Label, Value): the required value plus min, max, format, locale, getAriaValueText and aria-valuetext on the root, a render function as children on the value, and className, ref and render everywhere.

Accessibility

  • Renders Base UI's Progress: the root is the role="progressbar" and carries aria-valuemin, aria-valuemax and aria-valuenow, plus data-status — indeterminate, progressing or complete.
  • Name every bar. ProgressLabel does it through aria-labelledby; a bar with no visible label takes an aria-label on Progress instead.
  • A progress bar is a status output, not a control: it takes no focus and has no keyboard interaction, which is why no focus exception reaches this component.
  • The indicator's transition-all is upstream's; the global reduced-motion reset in base.css neutralises it (MOT-5) for a reader who asked for less motion.
  • Never report progress by colour alone — pair the bar with ProgressValue or with text nearby.
ContractStates tested
Behaviourindeterminate, progressing, complete
Accessibilitynative-or-base-ui-semantics, browser-accessibility-test
Visualindeterminate, progressing, complete

Do / Don't

Do
Use Progress for a task with a measurable extent, and give it a label or an aria-label that names the task.
Don't
Use Progress as a generic busy indicator with no known extent and no name — that is a Spinner.

Deviations

Upstream's file plus packages/ui/upstream/patches/progress.patch. Every hunk:

  • NO STYLING HUNK — Progress has no interactive element at all: no focus, no cursor, no disabled state, so no exception in the plan's matrix reaches it. transition-all on the indicator is upstream's, and the global reduced-motion reset (MOT-5) neutralises it.
  • DOC-2 — import { cn } from "cn" becomes @vegastack/design; our npm layer owns cn.
  • DOC-1 — prettier reflow plus the registry-stamp.mjs provenance header the three-copy model needs; no decision of its own.

On this page