Rolling Digits

Spring-animated digit counter with transform, opacity, and vertical motion.

Installation

npx shadcn@latest add @iconiq/rolling-digits

File Structure

Usage

"use client";

import { useEffect, useState } from "react";
import { RollingDigits } from "@/components/ui/rolling-digits";

export function RollingDigitsPreview() {
  const [days, setDays] = useState(12);

  useEffect(() => {
    const interval = window.setInterval(() => {
      setDays((current) => (current <= 0 ? 12 : current - 1));
    }, 2000);

    return () => window.clearInterval(interval);
  }, []);

  return (
    <div className="flex max-w-xl flex-wrap items-center justify-center gap-x-1.5 gap-y-2 text-balance text-center font-medium text-lg leading-snug dark:text-neutral-100">
      <span>Early access opens in</span>
      <span className="inline-flex translate-y-px items-center align-middle">
        <RollingDigits value={days} pad={2} startOnView={false} />
      </span>
      <span>days.</span>
    </div>
  );
}

Props

Props
Description

RollingDigits

value

Target number to display. The component rounds to the nearest integer before formatting.

Type number

pad

Minimum digit count. Applied with `padStart` for plain numbers, or through `minimumIntegerDigits` when `locale` is enabled.

Type number

animationDelay

Milliseconds between queued value steps when `value` changes faster than the animation can finish.

Type number·Default 80

stagger

Deprecated. Seconds between queued steps. Use `animationDelay` in milliseconds instead.

Type number

coalesceUpdates

When true, rapid `value` updates replace the pending queue with the latest value instead of stepping through every intermediate update.

Type boolean·Default false

onAnimationComplete

Called when the displayed value catches up to the latest `value` prop.

Type () => void

ariaLive

Controls `aria-live` on the screen-reader layer. `true` maps to `polite`; `false` and `off` disable announcements.

Type boolean | "polite" | "assertive" | "off"·Default true

startOnView

When true, playback waits until the component enters the viewport once before animating from zero.

Type boolean·Default true

locale

Locale formatting. `locale` uses the runtime default locale, a string sets the locale tag, and an object is passed to `Intl.NumberFormat`. When combined with `pad`, padding is applied through `minimumIntegerDigits`.

Type true | string | Intl.NumberFormatOptions

format

Custom formatter that runs after rounding. Overrides `locale` when both are provided.

Type (value: number) => string

gap

Pixel gap between rendered characters in the digit row.

Type number·Default 2

direction

Controls whether incoming digits slide up or down. `dynamic` compares the previous and next digit values.

Type "dynamic" | "up" | "down"·Default dynamic

enterStiffness

Spring stiffness for incoming digit motion.

Type number·Default 170

enterDamping

Spring damping for incoming digit motion.

Type number·Default 10

exitStiffness

Spring stiffness for outgoing digit motion.

Type number·Default 170

exitDamping

Spring damping for outgoing digit motion.

Type number·Default 15

enterY

Vertical offset in pixels used when a digit enters.

Type number·Default 32

enterBlur

Deprecated. Blur is no longer applied; digit motion uses transform and opacity for Safari-safe rendering.

Type number

enterScale

Starting scale applied when a digit enters.

Type number·Default 0.84

exitScale

Ending scale applied when a digit exits.

Type number·Default 0.84

className

Merged onto the outer inline-flex span that wraps the readable and visual layers.

Type string

digitClassName

Merged onto each animated digit cell wrapper for per-digit styling.

Type string

Registry bundle

Install the exact registry entry shown on the right when you want the component file and its declared runtime dependencies together.

Dependencies: motion.

Contact

Additionally, if you find any bug or issue, feel free to raise an issue.

Early access opens in12days.