shadimage

Progress

registry/pouf/progress.tsx

import * as RProgress from '@radix-ui/react-progress'
import clsx from 'clsx'
import { motion, useReducedMotion } from 'framer-motion'
import { toneClass, type Tone } from './tone'

interface ProgressProps {
  value: number
  max?: number
  tone?: Tone
  label?: string
}

export function Progress({ value, max = 100, tone = 'purple', label }: ProgressProps) {
  const reduceMotion = useReducedMotion()
  const pct = Math.min(100, Math.max(0, (value / max) * 100))
  return (
    <RProgress.Root className="pouf-progress" value={value} max={max} aria-label={label}>
      <RProgress.Indicator asChild>
        <motion.div
          className={clsx('pouf-progress__fill', toneClass(tone))}
          initial={false}
          animate={{ scaleX: pct / 100 }}
          transition={
            reduceMotion
              ? { duration: 0 }
              : { type: 'spring', stiffness: 200, damping: 24 }
          }
        />
      </RProgress.Indicator>
    </RProgress.Root>
  )
}

No selection tags yet — empty means no evidence, not lack of support.

DependenciesBundle weight · medium

ui-primitives
@radix-ui/react-progress
animation
framer-motion