Data display

Animated numbers for counters and stats

Animated Number renders a value with motion. AnimatedNumber splits a number into digits and animates each one in with a staggered transition, while AnimatedNumberCounter tweens from zero up to the target value. Both share themeable --zui-animated-number-* colors and sizes.

Digit entrance

12345

Count up

0

Dashboard stats

Active users

0

Revenue

92750

Open issues

128

Animated Number variants examples

Use Show output / Show code on each row. Snippets start with a Variant line naming the axis and token.


Appearance: DEFAULT

12345

Appearance: SUCCESS

12345

Appearance: WARNING

12345

Appearance: ERROR

12345

Appearance: INFO

12345

Appearance: GHOST

12345

Appearance: PURPLE

12345

Appearance: PINK

12345

Appearance: ORANGE

12345

Appearance: YELLOW

12345

Appearance: TEAL

12345

Appearance: INDIGO

12345

Appearance: GRAY

12345

Appearance: VIOLET

12345

Appearance: GRADIENT-BLUE

12345

Appearance: GRADIENT-GREEN

12345

Appearance: GRADIENT-RED

12345

Appearance: GRADIENT-YELLOW

12345

Appearance: GRADIENT-PURPLE

12345

Appearance: GRADIENT-TEAL

12345

Appearance: GRADIENT-INDIGO

12345

Appearance: GRADIENT-PINK

12345

Appearance: GRADIENT-ORANGE

12345

Size: SM

12345

Size: MD

12345

Size: LG

12345

Animation: UP

12345

Animation: DOWN

12345

Animation: SCALEUP

12345

Animation: SCALEDOWN

12345

Animation: ROTATEX

12345

Animation: ROTATEY

12345

Animation: SKEWX

12345

Animation: SKEWY

12345

Animation: FADE

12345

Counter: COUNT UP

0

CSS variable overrides

Animated Number CSS variables

Override these animated number variables on :root, a theme selector, or a component wrapper. Solid appearances set the text color; gradient appearances drive the from/to gradient stops.

64 variables

Pattern: --zui-<component>-<slot?>-<variant?>-<property>-<state?>-dark?

:root {
  --zui-animated-number-default-fg: oklch(20.8% 0.042 265.755);
  --zui-animated-number-success-fg: oklch(62.7% 0.194 149.214);
  --zui-animated-number-warning-fg: oklch(66.6% 0.179 58.318);
  --zui-animated-number-error-fg: oklch(57.7% 0.245 27.325);
  --zui-animated-number-info-fg: oklch(58.8% 0.158 241.966);
  --zui-animated-number-ghost-fg: oklch(55.4% 0.046 257.417);
  --zui-animated-number-purple-fg: oklch(55.8% 0.288 302.321);
  --zui-animated-number-pink-fg: oklch(59.2% 0.249 0.584);
  --zui-animated-number-orange-fg: oklch(64.6% 0.222 41.116);
  --zui-animated-number-yellow-fg: oklch(68.1% 0.162 75.834);
  --zui-animated-number-teal-fg: oklch(60% 0.118 184.704);
  --zui-animated-number-indigo-fg: oklch(51.1% 0.262 276.966);
  --zui-animated-number-gray-fg: oklch(44.6% 0.03 256.802);
  --zui-animated-number-violet-fg: oklch(54.1% 0.281 293.009);
  --zui-animated-number-gradient-blue-from: oklch(42.4% 0.199 265.638);
  --zui-animated-number-gradient-blue-to: oklch(43.8% 0.218 303.724);
  --zui-animated-number-gradient-green-from: oklch(44.8% 0.119 151.328);
  --zui-animated-number-gradient-green-to: oklch(45.3% 0.124 130.933);
  --zui-animated-number-gradient-red-from: oklch(44.4% 0.177 26.899);
  --zui-animated-number-gradient-red-to: oklch(45.9% 0.187 3.815);
  --zui-animated-number-gradient-yellow-from: oklch(47.6% 0.114 61.907);
  --zui-animated-number-gradient-yellow-to: oklch(47% 0.157 37.304);
  --zui-animated-number-gradient-purple-from: oklch(43.8% 0.218 303.724);
  --zui-animated-number-gradient-purple-to: oklch(45.9% 0.187 3.815);
  --zui-animated-number-gradient-teal-from: oklch(43.7% 0.078 188.216);
  --zui-animated-number-gradient-teal-to: oklch(45% 0.085 224.283);
  --zui-animated-number-gradient-indigo-from: oklch(39.8% 0.195 277.366);
  --zui-animated-number-gradient-indigo-to: oklch(43.8% 0.218 303.724);
  --zui-animated-number-gradient-pink-from: oklch(45.9% 0.187 3.815);
  --zui-animated-number-gradient-pink-to: oklch(45.5% 0.188 13.697);
  --zui-animated-number-gradient-orange-from: oklch(47% 0.157 37.304);
  --zui-animated-number-gradient-orange-to: oklch(44.4% 0.177 26.899);
}

/* Dark theme variables follow the same names with -dark appended. */
.dark {
  --zui-animated-number-default-fg-dark: oklch(98.4% 0.003 247.858);
  --zui-animated-number-gradient-blue-from-dark: oklch(54.6% 0.245 262.881);
  /* ...same variables with -dark at the end */
}

Overview

Both components accept appearance and size variants. Appearances cover semantic tones (success, warning, error, info), a palette of named colors, and gradient text. Sizes scale the type from sm to lg. Animations are triggered on scroll into view, run once, and respect prefers-reduced-motion. framer-motion is an optional peer dependency.

Common use cases

  • Dashboard KPIs and live metrics.
  • Landing-page stat counters.
  • Pricing and revenue highlights.
  • Score and progress readouts.

FAQ

What is the difference between AnimatedNumber and AnimatedNumberCounter?

AnimatedNumber animates each digit into place using a motion preset (slide, scale, rotate, skew, or fade) and is best for revealing a fixed value. AnimatedNumberCounter tweens the displayed value from zero up to the target, which reads as a counting-up effect.

How do I choose the entrance animation?

Pass the type prop on AnimatedNumber: up, down, scaleUp, scaleDown, rotateX, rotateY, skewX, skewY, or fade. Tune timing with the transition and delayInSecond props.

How are the colors themed?

Every appearance maps to a --zui-animated-number-* CSS variable with a hardcoded fallback and a paired dark-mode value. Solid appearances set the text color; gradient appearances clip a linear gradient to the text.

When does the animation run?

Both components are viewport-aware: the digit entrance and the count-up only start once the element scrolls into view, and they run a single time. They also respect prefers-reduced-motion, falling back to the final value with no animation.