Progress
A determinate bar showing how far a known-length task has advanced.
@garn/ui/progressDefault
A labeled determinate bar at 60%.
Installation
garn is copy-in — the garn CLI writes this component's source into your project, so you own and can edit it. It resolves any base files and installs the npm dependencies below for you.
npx garn-ui add progress- Registry
progress- Source
- progress.tsx
- Deps
@radix-ui/react-progressclass-variance-authority- Registry deps
utils
Import
import { Progress } from "@garn/ui/progress";Props
Generated from the component's TypeScript types.
format- Description
- Format the read-out + `aria-valuetext`. Default: rounded percent.
- Type
(value: number, max: number) => string
indeterminate- Description
- Force indeterminate even with no value (the unknown-progress mode).
- Type
boolean
label- Description
- A visible caption (rendered in a ProgressLabel; becomes the accessible name).
- Type
React.ReactNode
showValue- Description
- Show the value read-out beside the label.
- Type
boolean
size- Description
- Track height.
- Type
"lg" | "md" | "sm"
thresholds- Description
- Ascending value→tone map for `tone="auto"`. Default: 0 success · 75 warning · 90 danger.
- Type
ProgressThreshold[]
tone- Description
- `neutral | brand | success | warning | danger | info`, or `"auto"` to drive the tone from the value via `thresholds`. Default `brand`.
- Type
"auto" | ProgressTone
value- Description
- 0–`max`. `null`/`undefined` → indeterminate (or set `indeterminate`).
- Type
number
Plus 282 inherited native <div> attributes.
Styling
Target these data-slots and remap these tokens to restyle without forking the component.
[data-slot="progress"]Overview
Progress shows the determinate progress of a task with a known percentage — an upload, an install, multi-step completion — as a filled bar with a tone that can shift at thresholds, and it doubles as a capacity meter (storage used, quota). Use it when you can report a real fraction; for an indeterminate wait use a Spinner, and to hold a content shape while loading use a Skeleton.
Guidelines
Use Progress only when you know the fraction. A determinate bar that actually advances reassures users; faking it (or snapping 0→100) erodes trust. For unknown-duration work, a Spinner is the honest choice.
Pair the bar with a real number and context. Show the percentage or "3 of 5", and label what's progressing — a bar alone leaves users guessing. As a capacity meter, make the tone shift meaningful (e.g. warning as a quota fills).
Wire it for assistive tech. Expose the value via the progress role (aria-valuenow/min/max) and an accessible name so the state is announced, not just shown. Keep updates smooth and avoid jarring jumps; respect reduced-motion on any animation.
Best practices
- Pass
valueas 0–100 and give the bar an accessible name (aria-label or aria-labelledby). - Pair it with a visible percentage or step label when the number matters.
- Don't use Progress for unknown-duration loading — that's a Spinner.
- Don't animate a fake value just to look busy.
Content guidelines
- Give it an accessible label naming the task (“Uploading photo”).
- When you show a percentage or count, keep it true to the real value.
Accessibility
- Role
progressbar
- • Radix sets aria-valuenow / aria-valuemin / aria-valuemax from `value` and `max`.
- • The bar carries no text — give it an accessible name via aria-label or aria-labelledby.
- Status
- Stable
- Version
v0.3.0- Introduced
v0.1.0
garn doesn't yet record a per-release version history. This reflects the component's current lifecycle state; full changelog entries will appear once the metadata pipeline emits a lifecycle.history field.