Skip to content
WunderUI

useAnimatedNumber

Pro

A number that counts from its previous value to the new one, for chart headlines and KPI values.

import { useAnimatedNumber } from "@wunderui/react/charts"

Playground

Monthly revenue

$48,200

value: 48200

Click again while it counts: the number turns towards the new value.

Installation

useAnimatedNumber comes with WunderUI Core and Pro, in the entry of the package from your plan. See the plans. Then import it:

tsx
import { useAnimatedNumber } from "@wunderui/react/charts"

When to use

Use useAnimatedNumber for

  • A headline number that changes while the person watches: a KPI that follows the hovered point, a total after a refresh.
  • A figure where seeing the change helps more than a sudden swap: revenue, seats, a score.
  • A value that can change again mid-count. The count turns towards the new target.

Use something else for

  • AnimatedNumber for the same count with a function and the screen reader text built in, when you do not need the raw number. The Chart Card and the chart tooltips use it.
  • Metric Card for a finished KPI tile with trend, sparkline and the other variants.
  • useLoadSequence for the digit-by-digit roll that plays when a dashboard loads. This hook counts later changes, not the first appearance.
  • Plain text for numbers in a table or a long list. Counting every row makes the eye wait and re-renders each one on every frame.

Signature

Returns the value to show while it counts. The count runs on the token and the entrance curve by default; pass another duration token as the second argument. When the value changes mid-count, for example while a pointer slides across a chart, it turns towards the new target instead of starting over. The component wraps the hook with a formatter and the screen reader text.

ts
useAnimatedNumber(value: number | null | undefined, token?: string): number | null

Parameters

ParameterTypeDefaultDescription
valuenumber | null | undefined—The number to show. Change it and the shown number counts to it. , (returned as ) and values that are not finite are passed through and shown at once.
token optionalstring"--duration-slow"The name of a duration token, including the dashes, such as . It is read from the root element when a count starts. A token that is missing falls back to 350 ms. The default is .

Returns

The number to put on screen right now: the previous value on the way to the new one, the new value when the count is over, or when there is no value. The first render returns itself, so nothing counts on mount.

Behavior and motion

The hook runs a small animation loop in JavaScript and returns the number of the current frame.

State
The hook keeps the shown number in state and re-renders its component on every animation frame while a count runs. Keep the call in a small component, such as the number itself. The first render returns without counting; only a later change counts, from the number on screen to the new one, along the curve.
Retargeting
A new while a count runs cancels the running frame and starts a new count from the number currently on screen, over the full duration again. Sliding across a chart therefore follows the pointer smoothly instead of jumping or restarting at the old start.
Missing values
, (returned as ), and infinite values are returned at once. The step from a missing value to a number, and the step back, is not counted either; only a change between two finite numbers is. Show your own placeholder for .
Server rendering
Nothing touches or during render. The server and the first client render both return , and the count starts in an effect after a change, so there is no hydration mismatch.
Cleanup
The pending animation frame is cancelled when the value changes again and when the component unmounts, so nothing updates an unmounted component.
Motion
The duration comes from the CSS token (, 350 ms, unless you pass another) at the moment a count starts, and falls back to 350 ms when it cannot be read. The digits are text: nothing moves or resizes, as long as you use tabular figures () so the width does not change.
Reduced motion
Under there is no count: the number changes at once to the new value. The preference is checked every time the value changes.
Screen readers
The counting digits would be read out every frame. Hide them with and add the final value as visually hidden text, as does.

Best practices

  • Do

    Use tabular figures () for the number, so the digits do not change the width of the line while they count.

  • Do

    Hide the counting digits from assistive technology and give screen readers the final value only.

  • Do

    Round inside your formatter. The hook returns fractions in between, so would flash by without it.

  • Do

    Pass for a small tile or a tooltip. The default suits a headline.

  • Don’t

    Do not count every cell of a table or a long list. Each hook re-renders its component on every frame.

  • Don’t

    Do not use it for the first appearance of a number on a page. It does not count on mount; use a load sequence for that.

  • Don’t

    Do not rely on the count to carry meaning. Under reduced motion the new number appears at once, so the figure must make sense without it.

Notes for AI

Give your coding assistant the page or the MCP call instead of screenshots.

MCPget_component("useAnimatedNumber")
Importimport { useAnimatedNumber } from "@wunderui/react/charts"

The full library index for assistants is at /llms.txt.