Animated Number
Smooth count-up/down number animation with formatting options.
<arc-animated-number> Overview
AnimatedNumber smoothly transitions between numeric values using requestAnimationFrame with an ease-out-expo curve, creating the classic "counting up" effect seen in dashboards, stat cards, and hero metrics. When the value attribute changes, the component interpolates from the current displayed number to the new target over the specified duration.
The ease-out-expo easing produces a fast start that decelerates toward the target, which feels natural and draws attention to the final number. Duration defaults to 1000ms but can be adjusted for different contexts — 500ms for small increments in real-time dashboards, 2000ms for dramatic hero reveals on landing pages.
Formatting is built in: prefix and suffix strings wrap the number (e.g. "$" and "K"), and decimals controls fixed decimal places. The format property switches between number, currency, and percent modes, each powered by Intl.NumberFormat for locale-aware formatting — thousands separators, decimal marks, and grouping all adapt to the configured locale. The default locale is en-US, but you can pass any BCP 47 tag (e.g. de-DE, ja-JP) for international formatting. The animation respects prefers-reduced-motion by snapping directly to the target value without animation.
Guidelines
When to use
- Use in dashboard stat cards and hero metrics for visual impact
- Set decimals="2" for currency values and decimals="0" for counts
- Use prefix="$" or suffix="%" for contextual formatting
- Keep duration under 2000ms — longer animations feel sluggish
- Combine with ValueCard or Stat for complete metric displays
When not to use
- Do not animate more than 4-5 numbers simultaneously — it becomes distracting
- Do not use for rapidly changing real-time values — the animations will queue and feel laggy
- Do not set duration below 200ms — the animation becomes imperceptible
- Do not animate between extremely different magnitudes (1 to 1,000,000) — the counting is meaningless
- Do not use for static numbers that never change — add animation only when values update
Features
- Smooth count-up/down animation using requestAnimationFrame
- Ease-out-expo easing for natural deceleration
- Configurable duration from quick updates to dramatic reveals
- Prefix and suffix strings for currency, units, and labels
- Fixed decimal place control via decimals attribute
- Intl.NumberFormat-powered formatting with currency, percent, and number modes
- Configurable locale for international number formatting
- Respects `prefers-reduced-motion` by snapping to final value
Preview
Usage
<!-- Revenue counter -->
<arc-animated-number value="12847" prefix="$" duration="1500"></arc-animated-number>
<!-- Percentage with decimals -->
<arc-animated-number value="94.7" suffix="%" decimals="1"></arc-animated-number>
<!-- User count -->
<arc-animated-number value="3200" suffix=" users"></arc-animated-number> import { AnimatedNumber } from '@arclux/arc-ui-react';
function Dashboard({ revenue, percentage, users }) {
return (
<div>
<AnimatedNumber value={revenue} prefix="$" duration={1500} />
<AnimatedNumber value={percentage} suffix="%" decimals={1} />
<AnimatedNumber value={users} suffix=" users" />
</div>
);
} <script setup>
import { ref, onMounted } from 'vue';
import { AnimatedNumber } from '@arclux/arc-ui-vue';
const revenue = ref(0);
onMounted(() => { revenue.value = 12847; });
</script>
<template>
<AnimatedNumber :value="revenue" prefix="$" :duration="1500" />
</template> <script>
import { AnimatedNumber } from '@arclux/arc-ui-svelte';
import { onMount } from 'svelte';
let value = 0;
onMount(() => { value = 12847; });
</script>
<AnimatedNumber {value} prefix="$" duration={1500} /> import { Component, OnInit } from '@angular/core';
import { AnimatedNumber } from '@arclux/arc-ui-angular';
@Component({
imports: [AnimatedNumber],
template: `<arc-animated-number [value]="revenue" prefix="$" [duration]="1500" />`,
})
export class DashboardComponent implements OnInit {
revenue = 0;
ngOnInit() { this.revenue = 12847; }
} import { AnimatedNumber } from '@arclux/arc-ui-solid';
import { createSignal, onMount } from 'solid-js';
const [revenue, setRevenue] = createSignal(0);
onMount(() => setRevenue(12847));
<AnimatedNumber value={revenue()} prefix="$" duration={1500} /> import { AnimatedNumber } from '@arclux/arc-ui-preact';
import { useState, useEffect } from 'preact/hooks';
const [revenue, setRevenue] = useState(0);
useEffect(() => { setRevenue(12847); }, []);
<AnimatedNumber value={revenue} prefix="$" duration={1500} /> <!-- Auto-generated by @arclux/prism — do not edit manually -->
<!-- arc-animated-number — requires animated-number.css + tokens.css (or arc-ui.css) -->
<span class="arc-animated-number">
<span class="value"
role="status"
aria-live="polite"
>_format Value</span>
</span> <!-- Auto-generated by @arclux/prism — do not edit manually -->
<!-- arc-animated-number — self-contained, no external CSS needed -->
<span class="arc-animated-number" style="display: inline-block; font-family: 'JetBrains Mono', ui-monospace, monospace; font-variant-numeric: tabular-nums">
<span style="white-space: nowrap"
role="status"
aria-live="polite"
>_format Value</span>
</span> API
-
valuenumber0 - Target number to animate to
-
prefixstring'' - String prepended before the number (e.g., "$")
-
suffixstring'' - String appended after the number (e.g., "%")
-
decimalsnumber0 - Number of fixed decimal places
-
localestring'en-US' - BCP 47 locale tag passed to Intl.NumberFormat for locale-aware number formatting (thousands separators, decimal marks).
-
durationnumber1000 - Animation duration in milliseconds
-
format'number' | 'currency' | 'percent''number' - Controls how the number is formatted using Intl.NumberFormat. Use currency with a prefix like $ or percent with a suffix like %.