Actions
Progress Bar
A fully styleable progress indicator for how much of a task is done.
When to use it: Use it while work completes over time, such as an upload.
Example
40% complete
import { useState } from "react";
import { Label } from "@comp0/react";
import { ProgressBar } from "@comp0/react";
export function Example() {
const [value, setValue] = useState(0.4);
return (
<div className="flex max-w-xs flex-col gap-2">
<Label
id="upload-progress-label"
className="text-base font-medium text-zinc-900 sm:text-sm dark:text-zinc-100"
>
Uploading photos
</Label>
<ProgressBar
id="upload-progress"
value={value}
aria-labelledby="upload-progress-label"
className="h-2 w-full overflow-hidden rounded-full bg-zinc-200 dark:bg-zinc-800"
>
<span className="block h-full w-[calc(var(--comp0-progress-value)*100%)] rounded-full bg-teal-700 transition-[width] dark:bg-teal-400" />
</ProgressBar>
<p className="text-base text-zinc-600 tabular-nums sm:text-sm dark:text-zinc-400">
{Math.round(value * 100)}% complete
</p>
<button
type="button"
className="self-start rounded bg-teal-700 px-3 py-2.5 text-base text-white sm:py-2 sm:text-sm dark:bg-teal-400 dark:text-zinc-950"
onClick={() => setValue((current) => Math.min(1, current + 0.2))}
>
Advance
</button>
<ProgressBar
aria-label="Preparing download"
className="h-2 w-full overflow-hidden rounded-full bg-zinc-200 dark:bg-zinc-800"
>
<span className="block h-full w-1/3 animate-pulse rounded-full bg-teal-700 motion-reduce:animate-none dark:bg-teal-400" />
</ProgressBar>
</div>
);
}Anatomy
Dashed frames are invisible state providers; shaded shapes own real DOM. Numbered pins match the list below.
A wireframe sketch of the assembled component. Each numbered marker matches a part in the list that follows.
ProgressBar
Styleable div with progressbar semantics and an optional custom fill. Owns a DOM element.
Step by step
- 1
Add the main part
Add ProgressBar where the task's status belongs.
- 2
Add the supporting parts
Name it with a wired Label or an aria-label.
- 3
Make the behavior clear
Pass value as the completed fraction of max, or omit value while the total is unknown; add your own fill and size it with --comp0-progress-value.
Exampletsx <ProgressBar aria-label="Uploading photos" value={0.4}><span className="fill" /></ProgressBar>
Keyboard
Forms and accessibility
No form behavior; progress reports status and submits nothing.
Accessibility checklist
- Always name the bar with a Label or an aria-label.
- Show the percentage as visible text when precision matters.
- Use Meter instead for a measurement that is not task progress.
API reference
import { ProgressBar } from "@comp0/react";ProgressBar
DOM elementStyleable div with progressbar semantics and an optional custom fill.
| Prop | Type | Description |
|---|---|---|
value | number | Completed amount between 0 and max; omit it for an indeterminate bar. |
max | number | Upper bound of the range; defaults to 1. |
children | ReactNode | (state: ProgressBarState) => ReactNode | Custom track contents or a render function receiving value, max, and percentage. |
aria-label | string | Names the bar when it is not labelled by visible text. |
aria-labelledby | string | Points to the visible text that names the bar. |
aria-valuetext | string | Explains a determinate value when the number alone is not meaningful, such as “3 of 5 files”. |
Style hooks
Attributes that appear while a state is true. Target them with Tailwind data variants such as data-open:bg-zinc-100, or with any CSS selector.
[data-indeterminate]on ProgressBar
- No value was given; the bar shows unknown progress.
--comp0-progress-valueon ProgressBar
- Normalized 0–1 value for sizing a custom fill.