Progress
How far along something is.
Why it exists
Twenty files draw this bar by hand — Branch's goals and projects, Mint's budgets, Hana's onboarding and attendance, Bloom's charts — as a rounded div with an inline width inside another rounded div.
aria-valuenow appears in zero files across the platform
The bar
Given a label, a value and a tone. The value is clamped, so a computed 103% cannot overflow its track — which is what a raw style={{ width }} does.
Tone is given, never derived
90% of a budget spent is alarming and 90% of onboarding done is good news. The bar cannot tell which it is drawing, so it does not try.
Two offers out, one accepted.
In both themes
light
dark
Guidance
Use it when
- A known proportion: a budget, a quota, a checklist, a cycle.
- valueText whenever the percentage is not the fact — “$1,824 of $2,000 spent” beats “91%”.
- tone="brand" for the one bar on a page that is the page's subject; a wall of gradients means nothing.
Reach for something else when
- An unknown duration. That is Spinner — a bar that does not correspond to anything is worse than no bar.
- A count with no ceiling. Without a denominator there is no proportion to draw.
- Decoration. Every bar on the page is a claim that something is measurable.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| value | number | — | 0–100. Clamped, so a computed overflow cannot break the track. |
| label | string | — | Required. What this measures — an unlabelled meter announces a bare number. |
| tone | "brand" | "neutral" | "good" | "warn" | "bad" | "brand" | Whether this proportion is good news. |
| size | "sm" | "default" | "lg" | "default" | Track height. |
| valueText | string | — | What a screen reader says instead of the percentage. |
Accessibility
role="progressbar" with aria-valuenow, aria-valuemin and aria-valuemax — the whole point of the component, and the whole of what the twenty hand-rolled bars are missing. tests/accessibility.test.ts asserts all four are present, so a future refactor cannot quietly drop them and leave the bar looking identical.