Docs
AnimatedNumber

AnimatedNumber

A simple animated number animation

Custom Spring Properties

1,000

Precision

14.57

Format

$10.00

Callbacks

10

Installation

Copy and paste the following code into your project.

"use client"
 
import { useEffect } from "react"
import { MotionValue, motion, useSpring, useTransform } from "motion/react"
 
interface AnimatedNumberProps {
  value: number
  mass?: number
  stiffness?: number
  damping?: number
  precision?: number
  format?: (value: number) => string
  onAnimationStart?: () => void
  onAnimationComplete?: () => void
}
 
export function AnimatedNumber({
  value,
  mass = 0.8,
  stiffness = 75,
  damping = 15,
  precision = 0,
  format = (num) => num.toLocaleString(),
  onAnimationStart,
  onAnimationComplete,
}: AnimatedNumberProps) {
  const spring = useSpring(value, { mass, stiffness, damping })
  const display: MotionValue<string> = useTransform(spring, (current) =>
    format(parseFloat(current.toFixed(precision)))
  )
 
  useEffect(() => {
    spring.set(value)
    if (onAnimationStart) onAnimationStart()
    const unsubscribe = spring.onChange(() => {
      if (spring.get() === value && onAnimationComplete) onAnimationComplete()
    })
    return () => unsubscribe()
  }, [spring, value, onAnimationStart, onAnimationComplete])
 
  return <motion.span>{display}</motion.span>
}

Update the import paths to match your project setup.

Usage

import { AnimatedNumber } from "@/components/ui/animated-number"
function BasicExample() {
  const [value, setValue] = useState(1000)
 
  return (
    <div>
      <AnimatedNumber value={value} />
      <Button
        size="sm"
        variant="ghost"
        className="border border-primary/10 rounded-full "
        onClick={() => setValue(value + 1000)}
      >
        <Plus className="h-4 w-4" />
      </Button>
    </div>
  )
}