AnimateCounter
A number counted up to its value. The one animation in the library whose subject is the content rather than the box around it: a value being interpolated and formatted on every frame, which is not something a keyframe can do.
import { AnimateCounter, Statistic } from 'neba';
<Statistic label="Monthly active" value={<AnimateCounter value={128400} />} />;Props
| Prop | Type | Default | Description |
|---|---|---|---|
| value * | number | — | Where it lands |
| from | number | 0 | Where it starts |
| durationshared | number | 1200 | How long the count takes, in milliseconds |
| delayshared | number | 0 | How long before it starts, in milliseconds |
| format | Intl.NumberFormatOptions | — | How the number is written: Intl.NumberFormat options, so a currency, a percentage or a compact 1.2M is a prop rather than a callback |
| locale | string | — | Which language it is written in |
| triggershared | 'mount' | 'visible' | 'hover' | 'manual' | 'mount' | What starts the count. Before it does, the number sits at from |
| play | boolean | — | Runs it when trigger is manual |
| onceshared | boolean | true | With trigger="visible", whether it counts only the first time |
| thresholdshared | number | 0.2 | With trigger="visible", how much of it has to be on screen |
| render | useRender.RenderProp | — | Renders something other than a div (render={<strong />}). Base UI's own escape hatch |
Every other <div> attribute passes through to the root. It has no easing, repeat or alternate: a number may only ever approach its value from one side, so the curve is a fixed ease-out and there is no version of a count that loops.
It pairs with Statistic, whose value takes a node for exactly this. A dashboard that draws its numbers instantly and animates everything around them has the emphasis backwards.
Examples
format and locale
Intl.NumberFormat options, so a currency, a percentage or a compact 1.2M is a prop rather than a format callback: the same prop Statistic and the progress indicators take.
trigger
trigger="visible" is the one worth reaching for on a dashboard below the fold: a count that has already finished by the time it is scrolled to has not been seen. Before it starts, the number sits at from rather than at its answer.
<AnimateCounter value={128400} trigger="visible" />Accessibility
- The finished number is in the document from the first frame, in a clipped box for a screen reader; what counts is a visible copy that is
aria-hidden. A reader who cannot see the count is told the answer rather than a hundred intermediate ones. - A reduced-motion preference shows the answer straight away.