Skip to content
Sign in
EffectsNumber flowMenu

Number flowPro

A number that rolls each changed digit to its new value: credits, cost, tokens, queue positions. It never counts up from zero on mount, formats with Intl in any locale, and announces politely without flooding screen readers.

ProA usage panel: each run spends credits and adds tokens and cost, and only the digits that changed roll.

Installation

$ pnpm dlx shadcn@latest add @chatcn-pro/number-flow

Usage

tsx
import { NumberFlow } from "@/components/ui/chatcn/pro/number-flow"

<NumberFlow value={credits} />
<NumberFlow value={cost} format={{ style: "currency", currency: "USD" }} />
<NumberFlow value={tokens} format={{ notation: "compact" }} suffix=" tokens" />

Pass the real value whenever it changes. The first render shows the number as is: count-up animations are on the slop list, so only real changes move. Digits are matched by place value, so 999 to 1,000 rolls the ones, tens and hundreds and fades in the new thousands digit, and digits that did not change stay still.

Examples

Formats and locales

format and locales go straight to Intl.NumberFormat. Separators, currency symbols and the compact K or M are static glyphs that crossfade when they change. Digits roll in the locale's own numbering system, so Arabic digits roll too.

ProUS dollars, euros with German grouping, rupees with lakh grouping, compact tokens and percent.

Trend and sizes

With trend="auto" digits roll up when the value grows and down when it shrinks, wrapping through 9 to 0 like an odometer. Force up for counters that only grow. The roll scales with the font, from a 13 px table cell to a 56 px balance.

ProAuto trend, odometer trend, animation off, a static suffix and a display size number.

Props

PropTypeNotes
valuenumberRequired
formatIntl.NumberFormatOptionsCurrency, compact, percent, fraction digits
localesIntl.LocalesArgumentDefaults to the browser locale
prefix, suffixReactNodeStatic text around the number, not animated
trend"auto" | "up" | "down"Roll direction. Default auto
animatedbooleanDefault true. Off, the number swaps in place
durationnumberRoll duration in ms. Default 300
announceboolean | numberLive region updates, at most every 2 s by default. A number sets the interval
spoken(formatted) => stringWhat a screen reader hears

Accessibility

  • The rolling digits are hidden from assistive tech. A visually hidden copy holds the current value, and a polite live region repeats it at most once every 2 s, ending on the latest value. Nothing is announced on mount.
  • Turn announce off when a parent already announces in words, as queue-position does.
  • Selecting and copying the number copies the formatted value, not the digit strips.
  • Tabular figures keep every digit the same width, so the number never jitters sideways.

Motion

  • Each digit is a strip of three copies of 0 to 9 moved with transform over 300 ms on the kit's ease out, masked at the top and bottom edge. A run of fast updates interrupts smoothly from wherever the strip is.
  • Under reduced motion the new value replaces the old with a 150 ms opacity crossfade.