Progress

Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.

"use client"

import * as React from "react"
import { cn } from "cn"
import { Progress as ProgressPrimitive } from "@animate-ui/react/primitives/radix-ui"

function Progress({
  className,
  value,
  ...props
}: React.ComponentProps<typeof ProgressPrimitive.Root>) {
  return (
    <ProgressPrimitive.Root
      data-slot="progress"
      className={cn(
        "bg-muted h-1 rounded-full relative flex w-full items-center overflow-x-hidden",
        className
      )}
      {...props}
    >
      <ProgressPrimitive.Indicator
        data-slot="progress-indicator"
        className="bg-primary size-full flex-1"
        style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
      />
    </ProgressPrimitive.Root>
  )
}

export { Progress }

export default function ProgressDemo() {
  const [progress, setProgress] = React.useState(13)

  React.useEffect(() => {
    const timer = setTimeout(() => setProgress(66), 500)
    return () => clearTimeout(timer)
  }, [])

  return <Progress value={progress} className="w-[60%]" />
}

Installation

Install the packages

npm install @animate-ui/react motion
pnpm add @animate-ui/react motion
yarn add @animate-ui/react motion
bun add @animate-ui/react motion

Add the shadcn/ui component

npx shadcn@latest add progress
pnpm dlx shadcn@latest add progress
yarn dlx shadcn@latest add progress
bun x shadcn@latest add progress

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.

npx @animate-ui/cli@latest animate progress
pnpm dlx @animate-ui/cli@latest animate progress
yarn dlx @animate-ui/cli@latest animate progress
bun x @animate-ui/cli@latest animate progress

Usage

Import the primitive from Animate UI instead of Radix UI. Everything else stays the same.

import { Progress } from '@animate-ui/react/primitives/radix-ui';

export function Upload({ value }: { value: number }) {
  return (
    <Progress.Root value={value} className="h-2 overflow-hidden rounded-full">
      <Progress.Indicator
        className="size-full bg-primary"
        style={{ transform: `translateX(-${100 - value}%)` }}
      />
    </Progress.Root>
  );
}

Coming from the @radix-ui/react-progress package? Use the subpath: import * as ProgressPrimitive from '@animate-ui/react/primitives/radix-ui/progress'.

Animation

The motion of Animate UI v1's progress:

  • Indicator 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, which would uncover the start of the track). Radix leaves the indicator's position to you: shadcn/ui moves it with style={{ transform: translateX(-…%) }}, the x v1 animated. Animate UI animates that translation instead of jumping to it, as an x that keeps its momentum when a new value arrives mid-way.
  • It starts at its value on mount, with no animation.
  • shadcn/ui's transition-all on the indicator would run on top of Motion: the CLI removes it.
  • Under reduced motion, the indicator jumps to each value.

API Reference

Every part takes exactly the props of Radix UI's Progress. Animate UI adds the animation props below.

Root

Radix UI props only.

Indicator

Radix UI props, plus:

PropTypeDefault
transition?
Transition{ type: 'spring', stiffness: 300, damping: 35, restDelta: 0.01, restSpeed: 0.1 }

AnimateUIProvider's tempo scales these transitions with everything else.

Built by Skyleen. The source code is available on GitHub.

Last updated: 10/18/2026

On this page