Number Animation

Two ways a quantity changes. NumberTicker rolls each digit position like a geared odometer; AnimatedNumber interpolates one value into the next. Both keep the settled number in the accessible tree as plain text and mark the moving glyphs aria-hidden, so assistive tech is never handed a stack of ten digits or a hundred intermediate readings.

tsx
import { NumberTicker, AnimatedNumber } from "@pestoui/core"

Rolling ticker

Every digit position is a window one glyph tall clipping a column of all ten, and the column translates to bring the right one into frame. The stagger counts from the right, so the ones column leaves first and the leading digit lands last — the order a geared odometer actually moves in. Step 99 then 100 for the case worth watching: columns are keyed by PLACE VALUE, never by array index, so the ones and tens roll from 9 to 0 while a brand-new hundreds column mounts already showing its 1 and never animates at all. Keyed by index, gaining a digit would shift every position by one and re-roll the whole number — a value that flickers wholesale each time it crosses a boundary.

99

Currency and decimals

Sign, prefix, group separators and suffix are static cells sitting between the rolling columns, so only the digits that changed ever move. Decimal places are fixed rather than derived from the value: a width that varied with the number would re-key every column on each update and re-roll digits that had not changed. Add and remove seats to watch the cents roll while the leading digits hold.

$1,284.50 / mo

Count-up

One value interpolated into the next on a frame loop, eased out over a fixed duration rather than driven by a spring — and that is a correctness constraint, not a taste call. Every spring in the system bar the overdamped pair crosses its target before settling, and a counter that crosses its target briefly displays a number that was never true. Overshoot is free on a knob and simply wrong on a quantity, so this one approaches from a single side and lands on the exact target instead of on the last sampled frame. Randomise mid-count to see the re-aim: the next run starts from the frame actually on screen, not from zero.

48,291documents indexed

Props

PropTypeDefaultDescription
NumberTicker valuenumber—The number to display. Rolls to any new value it is given.
NumberTicker decimalsnumber0Fixed number of decimal places. Fixed on purpose — a width that varied with the value would re-key the columns on every update.
NumberTicker separatorstring","Thousands separator. Pass an empty string to group nothing.
NumberTicker prefixstring""Static cell before the digits. A minus sign leads it, so a negative currency reads as -$5 rather than $-5.
NumberTicker suffixstring""Static cell after the digits — a unit, a percent sign, a rate.
NumberTicker startOnViewbooleanfalseHold every column at zero until the ticker scrolls into view, then roll once. The box already holds the target's shape, so nothing reflows.
AnimatedNumber valuenumber—Target value. Changing it re-aims the count from the frame currently on screen rather than restarting.
AnimatedNumber durationnumber1200Count duration in milliseconds. Zero settles on the target immediately.
AnimatedNumber format(n: number) => stringrounded, localisedRenders the in-flight value and the announced target. Use it for units, currency or compact notation.
AnimatedNumber localestring—Locale for the default format's digit grouping; the browser's own when unset. Set it on a server-rendered page, so the server's markup and the browser's first render agree. Unused when format is given.
AnimatedNumber startOnViewbooleanfalseHold at zero until the number scrolls into view, then count once.

Pesto UI · 117 documented components