Progress
A progress bar shows how much of a task is done. Pass a value for a
determinate bar; leave it out (or pass null) when the amount of work is
unknown and the indicator sweeps the track instead. The track is always
--muted; the fill takes a semantic colour.
import Progress from '@zuilib/components/progress'
Determinate and indeterminate
value is clamped to 0..max. A determinate indicator slides with a
transform so updates animate cheaply; an indeterminate one is a third of
the track sweeping across it (a pulse under prefers-reduced-motion).
Variants
Sizes
Track heights step with --spacing (h-1, h-2, h-3); the value label
steps with the type scale.
Custom max and format
max sets aria-valuemax (aria-valuemin is always 0). formatValue
produces both the visible label and aria-valuetext, so a unit-based
format is announced as such. Use aria-labelledby when a visible heading
names the bar.
Props
ProgressProps extends the <div> attributes (minus children and role)
with:
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | null | — | Current value, clamped to 0..max. null / undefined renders indeterminate |
max | number | 100 | Must be finite and positive; anything else falls back to 100 |
size | 'sm' | 'md' | 'lg' | 'md' | Track height h-1 / h-2 / h-3 |
variant | 'primary' | 'success' | 'warning' | 'destructive' | 'primary' | Fill colour; the track is always --muted |
showValue | boolean | false | Renders the formatted value beside the bar (determinate only) |
formatValue | (value: number, max: number) => string | whole percentage | Used for the visible label and aria-valuetext |
aria-label | string | — | Accessible name for a self-contained bar. One of aria-label / aria-labelledby is required (typed) |
aria-labelledby | string | — | Id of a visible heading or label that names the bar |
className | string | — | Merged last onto the root |
Slots
| Slot | Element | Notes |
|---|---|---|
[data-slot="progress"] | div | Root, role="progressbar". Also data-state="determinate" | "indeterminate", data-variant, data-size |
[data-slot="progress-track"] | div | Clips the indicator; mirrored under dir="rtl" |
[data-slot="progress-indicator"] | div | The fill (transform) or the sweeping third |
[data-slot="progress-label"] | span | The formatted value; aria-hidden. Present with showValue on a determinate bar |
/* Consumer CSS: square track and fill */
[data-slot="progress-track"],
[data-slot="progress-indicator"] {
border-radius: 0;
}
Tokens
| Token | Used for |
|---|---|
--muted | Track |
--primary, --success, --warning, --destructive | Fill per variant |
--muted-foreground | Value label |
--spacing, --text-xs/sm/base | Track height and label size per size |
--duration-normal | Fill transition |
--animate-progress-indeterminate | Indeterminate sweep |
Accessibility
- Root is
role="progressbar"witharia-valuemin={0},aria-valuemax,aria-valuenow(omitted while indeterminate) andaria-valuetextfromformatValue. - Indeterminate bars set
aria-busy="true". - A name is required:
aria-labeloraria-labelledby. The types enforce one of the two; a development-only console warning fires when neither reaches the DOM. - The visible value label is
aria-hidden;aria-valuenow/aria-valuetextalready announce it. - Motion: the fill transition and the sweep are disabled under
prefers-reduced-motion(the sweep becomes a pulse). - Direction-aware: under
dir="rtl"the fill anchors to the right edge and the sweep runs right-to-left.
Related
- Spinner: indeterminate progress without a track.
- Skeleton: placeholder while content loads.
- Step Indicator: progress through discrete steps.