PParable
All components

Animated Counter

Text Animations

A 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.json

Runs 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">

PropTypeDefaultDescription
value*numberThe number to display. Changes animate — up or down — to the new value.
durationnumber1100Roll duration in milliseconds.
format(n: number) => stringdefaultFormatFormat the number into its display string. Defaults to `en-US` grouping.
startOnViewbooleantrueStart the first roll only once the counter scrolls into view (via `IntersectionObserver`). When `false`, it rolls on mount.