Animated Counter
Text AnimationsA number that rolls to its value odometer-style — each digit column slides vertically to its target through the digits between, with tabular-nums so the width never jitters.
Inspired by Watermelon UI — animated number — independently built, not affiliated. Attribution policy
128,540
1,234visitors
98%uptime
Installation
npx shadcn@latest add https://parable-three.vercel.app/r/animated-counter.jsonRuns the shadcn CLI — the component source is copied intocomponents/parable/animated-counter.tsx. You own it from there.
Usage
The exact code rendering the preview above.
<div className="flex flex-col items-center gap-6 text-white">
<AnimatedCounter value={128540} startOnView={false} className="text-5xl font-semibold tracking-tight" />
<div className="flex gap-8 text-2xl font-medium text-white/70">
<div className="flex flex-col items-center gap-1">
<AnimatedCounter value={1234} startOnView={false} />
<span className="text-xs uppercase tracking-widest text-white/40">visitors</span>
</div>
<div className="flex flex-col items-center gap-1">
<AnimatedCounter value={98} startOnView={false} format={(n) => `${n}%`} />
<span className="text-xs uppercase tracking-widest text-white/40">uptime</span>
</div>
</div>
</div>Props
AnimatedCounterProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "children">
| Prop | Type | Default | Description |
|---|---|---|---|
| value* | number | — | The number to display. Changes animate — up or down — to the new value. |
| duration | number | 1100 | Roll duration in milliseconds. |
| format | (n: number) => string | defaultFormat | Format the number into its display string. Defaults to `en-US` grouping. |
| startOnView | boolean | true | Start the first roll only once the counter scrolls into view (via `IntersectionObserver`). When `false`, it rolls on mount. |