All components
Number Ticker
data-displayAnimate numbers to count up or down to a target number
responsive · 400px
Install
Same command in any shadcn project — React (Vite/CRA), Next.js, Remix, Astro, and more:
$
npx shadcn@latest add https://your-domain/r/number-ticker.jsonUsage
import { NumberTicker } from "@/registry/magic-ui/number-ticker";
export default function Demo() {
return (
<div className="flex flex-col items-center justify-center gap-6 p-10">
<div className="flex flex-col items-center gap-1">
<span className="text-6xl font-bold tabular-nums text-foreground">
<NumberTicker value={12500} />
</span>
<span className="text-sm text-muted-foreground">Active Users</span>
</div>
<div className="flex flex-col items-center gap-1">
<span className="text-5xl font-semibold tabular-nums text-foreground">
<NumberTicker value={99} decimalPlaces={1} />
<span className="text-3xl">%</span>
</span>
<span className="text-sm text-muted-foreground">Uptime</span>
</div>
<div className="flex flex-col items-center gap-1">
<span className="text-4xl font-semibold tabular-nums text-foreground">
$<NumberTicker value={4820000} />
</span>
<span className="text-sm text-muted-foreground">Revenue</span>
</div>
</div>
);
}Component source
"use client"
import { useEffect, useRef, type ComponentPropsWithoutRef } from "react"
import { useInView, useMotionValue, useSpring } from "motion/react"
import { cn } from "@/lib/utils"
interface NumberTickerProps extends ComponentPropsWithoutRef<"span"> {
value: number
startValue?: number
direction?: "up" | "down"
delay?: number
decimalPlaces?: number
}
export function NumberTicker({
value,
startValue = 0,
direction = "up",
delay = 0,
className,
decimalPlaces = 0,
...props
}: NumberTickerProps) {
const ref = useRef<HTMLSpanElement>(null)
const motionValue = useMotionValue(direction === "down" ? value : startValue)
const springValue = useSpring(motionValue, {
damping: 60,
stiffness: 100,
})
const isInView = useInView(ref, { once: true, margin: "0px" })
useEffect(() => {
let timer: ReturnType<typeof setTimeout> | null = null
if (isInView) {
timer = setTimeout(() => {
motionValue.set(direction === "down" ? startValue : value)
}, delay * 1000)
}
return () => {
if (timer !== null) {
clearTimeout(timer)
}
}
}, [motionValue, isInView, delay, value, direction, startValue])
useEffect(
() =>
springValue.on("change", (latest) => {
if (ref.current) {
ref.current.textContent = Intl.NumberFormat("en-US", {
minimumFractionDigits: decimalPlaces,
maximumFractionDigits: decimalPlaces,
}).format(Number(latest.toFixed(decimalPlaces)))
}
}),
[springValue, decimalPlaces]
)
return (
<span
ref={ref}
className={cn(
"inline-block tracking-wider text-black tabular-nums dark:text-white",
className
)}
{...props}
>
{startValue}
</span>
)
}Dependencies
motion
Source: Magic UI