Motion UIComponentsComponent

Progress bar

A horizontal progress fill that reveals on entrance, with optional benchmark ticks.

npx shadcn@latest add @motion/progress-bar

API reference

Components

<ProgressBar />

A horizontal progress track with a determinate fill. Static by default (a determinate meter); pass reveal to spring the fill out of its left edge on the theme's ui spring, gated by revealed and cascaded by index. Add a referenceTick for a benchmark mark, highlight for the brand fill, progressbar for the ARIA role, and the label/valueLabel slots for a label row.

value

number

Fill length as a share in [0,1] (0 = empty, 1 = full). Drives the rendered fill width and, when progressbar is set, the reported aria-valuenow as a whole percentage. Values outside [0,1] are clamped.

reveal?

boolean = false

Animate the fill in with a left-anchored scaleX reveal on the theme's ui spring instead of painting it statically. Gate the reveal with revealed and cascade a column of bars with index. Default false: a static determinate meter, the shape a media scrubber wants.

revealed?

boolean = true

Gate for reveal: while false the fill holds empty (scaleX 0); flip it true to release the reveal. Drive it from your own entrance choreography so a row of bars stays at zero until the container has settled, then fills in one beat. Ignored when reveal is false. Default true: reveals as soon as it mounts / scrolls into view.

index?

number = 0

Stagger index for reveal: the reveal spring is delayed by index * theme.stagger.base, so a column of bars cascades in order. Ignored when reveal is false. Default 0.

referenceTick?

number

A fixed reference marker painted over the track, as a share in [0,1] (e.g. a category median the fill is benchmarked against). Omit for no tick. Decorative and aria-hidden: carry its meaning with an sr-only equivalent inside valueLabel.

highlight?

boolean = false

Paint the fill with the brand slot (bg-primary) - the one highlighted row in a group of bars. Default false: the neutral tone fill.

tone?

string = DEFAULT_FILL_TONE

The opaque colour of a non-highlighted fill. Defaults to a 55% --foreground into --card mix; pass your own color-mix off a semantic var when the bar sits on a different surface. Never a raw hex - keep it derived off the theme. Ignored when highlight is set.

size?

"sm" | "md" = "md"

Track height: "sm" is a 4px hairline (a media scrubber), "md" the 8px default (a benchmark / funnel bar).

progressbar?

boolean = false

Expose the track as an ARIA progressbar with aria-valuemin 0, aria-valuemax 100 and aria-valuenow derived from value. Pair with aria-label. Omit when the surrounding label already carries the value (the benchmark / funnel case) - then the track is aria-hidden.

"aria-label"?

string

Accessible name for the track when progressbar is set.

label?

ReactNode

Leading label slot, laid out opposite valueLabel. Fully styled by you (a metric name, a funnel step, an elapsed time). Omit for a bare track.

valueLabel?

ReactNode

Trailing label slot, laid out opposite label. Fully styled by you (the percentage plus a trend badge, or a remaining time). Put any sr-only detail - "category median 78%, up" - inside this node.

labelPlacement?

"top" | "bottom" = "top"

Where the label row sits relative to the track: "top" above (benchmark / funnel) or "bottom" below (a scrubber's time labels). Default "top". No effect when both label slots are omitted.

className?

string

Merged onto the root wrapper. Set spacing (gap-*) and layout here.

ref?

Ref<HTMLDivElement>

Merged onto the root wrapper, for consumers that need to measure it.