AnimatedNumber

A number that rolls to its new value, so a change made elsewhere is noticed.

StableSince 1.0.0
On this page

Import

import { AnimatedNumber } from '@envsemble/envui';

Usage

AnimatedNumber shows its value as text inside a sentence or a label; when value changes, the new number rolls in, up as it grows and down as it shrinks, and with reduced motion it only fades in. Keep the words beside it in the same element, and match them to the number; in a Button's label, the words and the number stay one line of text.

ShowResults.tsx
import { useState } from 'react';
import { AnimatedNumber, Button, Checkbox, Column, Row } from '@envsemble/envui';

const statuses = [
  { value: 'open', label: 'Open', count: 24 },
  { value: 'review', label: 'In review', count: 9 },
  { value: 'done', label: 'Done', count: 95 },
];

export default function ShowResults() {
  const [chosen, setChosen] = useState(['open', 'review']);
  const total = statuses
    .filter(({ value }) => chosen.includes(value))
    .reduce((sum, { count }) => sum + count, 0);
  return (
    <Column gap={4}>
      <Column gap={2} role="group" aria-label="Status">
        {statuses.map(({ value, label }) => (
          <Checkbox
            key={value}
            label={label}
            checked={chosen.includes(value)}
            onCheckedChange={(checked) =>
              setChosen((current) =>
                checked ? [...current, value] : current.filter((item) => item !== value),
              )
            }
          />
        ))}
      </Column>
      <Row wrap align="center" gap={4}>
        <Button disabled={total === 0}>
          Show <AnimatedNumber value={total} /> {total === 1 ? 'task' : 'tasks'}
        </Button>
      </Row>
    </Column>
  );
}

A formatted value

formatValue writes the value as text, such as a currency through Intl.NumberFormat, as CustomFormat does. Without it, AnimatedNumber uses the number format of EnvUIProvider's locale, or else the browser's.

const euros = new Intl.NumberFormat('en-IE', { style: 'currency', currency: 'EUR' });

<AnimatedNumber value={price} formatValue={(value) => euros.format(value)} />;

Composition

AnimatedNumber is the root, env-animated-number, around the value, env-animated-number-value.

Accessibility

You provide

  • A status region where the change must be announced; AnimatedNumber isn't one.
  • A formatValue in the reader's language.

envUI provides

  • The current value as the text at every moment, so names and copied text never hold a number on its way.
  • A fade instead of the roll with reduced motion.

Props

AnimatedNumber

A number within text that rolls to its new value when it changes: up when it grows and down when it shrinks, so a count updated by other controls is noticed. The text is always the current value.

PropTypeDescription
valuerequired
number
The number to show; when it changes, the new value rolls in, up as it grows, down as it shrinks.
formatValueDefault the number format of EnvUIProvider's locale, or else the browser's
(value: number) => string
Writes the value as text, such as a currency.

Also accepts the native props of <span>, such as ref, className and aria-* attributes.

Part names

Each part's class and state attributes are public and versioned, for an application's CSS to style.

env-animated-number
The number, which animates when its value changes.
env-animated-number-previous
The value it changed from, while it leaves; hidden from assistive technology, its text drawn from data-value.
env-animated-number-value
The digits as they change.
data-direction
down · up on env-animated-number-previous, env-animated-number-value
data-value
Any value, or present on env-animated-number-previous

Changelog

1.0.0

The default format follows EnvUIProvider's locale. format is formatValue, as on Slider and CalendarHeatmap.

1.0.0-prerelease.6

The value it changed from rolls out quickly, env-animated-number-previous, and the new one rolls in at once, a whole line inside the number's box, so the number never blinks out and the two never read over each other; with reduced motion they cross-fade. Where the new value is wider or narrower, the box eases to its width.