Displays the status of a task that takes a long time.
Installation
Install the packages
Add the shadcn/ui component
Animate it
The CLI finds your shadcn/ui components through components.json, swaps their primitive imports for Animate UI's and removes the CSS animation classes Motion replaces.
Usage
Import the primitive from Animate UI instead of Base UI. Everything else stays the same.
import { Progress } from '@animate-ui/react/primitives/base-ui/progress';
export function Upload({ value }: { value: number }) {
return (
<Progress.Root value={value}>
<Progress.Label>Uploading</Progress.Label>
<Progress.Value />
<Progress.Track className="h-2 overflow-hidden rounded-full">
<Progress.Indicator className="bg-primary" />
</Progress.Track>
</Progress.Root>
);
}Using the @base-ui/react umbrella import instead? The barrel mirrors it: import { Progress } from '@animate-ui/react/primitives/base-ui'.
Animation
The motion of Animate UI v1's progress:
- Indicator: Base UI sizes it with a percentage
width, and its width springs to each new value (stiffness 300, damping 35: most of the way in ~230ms and settled by ~550ms, with no jump at the end; no overshoot), the width v1 animated. Right-to-left works as Base UI lays it out (inset-inline-start). - Value counts to each new value on the bar's own spring (stiffness 300, damping 35), so the number moves with the bar, formatted as Base UI formats it (a percentage, or your
formatandlocale, withinminandmax), frommin(0 by default) when it appears, as v1's counting value did. Achildrenfunction gets the counted text and number. - The indicator starts at its value on mount, with no animation.
- Indeterminate (
value={null}): the indicator is left to your styles, and the Value to Base UI. - shadcn/ui's
transition-allon the indicator would run on top of Motion: the CLI removes it. - Under reduced motion, the indicator jumps to each value (the Value still counts).
- Without a
locale, Base UI formats the numbers (the Value,aria-valuetext) in the runtime's locale: the server's on the server and the browser's in the browser, so a page rendered in English and opened in another language didn't hydrate cleanly ("13%" against "13 %"). Animate UI formats them in en-US on the server and while the page hydrates, then in the browser's locale, as React Aria does. Passlocaleto pick one yourself.
API Reference
Every part takes exactly the props of Base UI's Progress. Animate UI adds the animation props below.
Root, Track, Label
Base UI props only.
Indicator
Base UI props, plus:
| Prop | Type | Default |
|---|---|---|
transition? | Transition | { type: 'spring', stiffness: 300, damping: 35, restDelta: 0.01, restSpeed: 0.1 } |
Value
Base UI props, plus:
| Prop | Type | Default |
|---|---|---|
transition? | Transition | { type: 'spring', stiffness: 300, damping: 35, restDelta: 0.01, restSpeed: 0.1 } |
AnimateUIProvider's tempo scales these transitions with everything else.