Skip to content

Motion

Reveal & Counter

Entrance animation on scroll, and numbers that animate to their value — both decorative, both able to be switched off without losing content.

Reveal Counter
import { Reveal, Counter } from '@anomalia/ui';

Notes

  • Reveal fires once by default. Content that re-animates every time it scrolls back into view turns reading into a slideshow.
  • If IntersectionObserver is missing or JS never runs, the content renders visible rather than invisible-forever — entrance motion must never be able to hide a page.
  • Stagger a group by passing index inside an {#each}; each item waits index × stagger.
  • Counter animates from its current value when the value changes, not from zero, and holds a real formatted number in the DOM on every frame.
  • Both render their final state instantly under prefers-reduced-motion.

Examples

Entrance

Scroll it out of view and back to see it fire. `index` staggers a group, so a list is dealt rather than dropped — and it runs once, because content that re-animates on every scroll turns reading into a slideshow.

How it runs

Three steps, one afternoon

Editorial plan

Twelve posts for week 34.

Production

Captions, carousels and cuts.

Autopilot

Approve once, or keep every post in review.

Counter

The count decelerates into its final digits, which is the part worth reading. Change the value and it animates from where it is, not from zero — a metric that restarts from 0 on every update is a slot machine.

Impressions

0.0k

+12.4%

Engagement

0.00%

+0.8pt

Credits

0

−320

API

Reveal

PropTypeDefaultDescription
y / xnumber12 / 0Travel distance in px. Keep it small — long travel lies about where content came from.
index / staggernumber0 / 60Position in a group and the per-item delay in ms.
delay / durationnumber0 / 500Extra delay and the transition length, in ms.
repeatbooleanfalseRe-animate on every entry. Off on purpose.
thresholdnumber0.15Fraction visible before it fires.

Counter

PropTypeDefaultDescription
valuenumberTarget. Changing it animates from the current display.
fromnumber0Where the first run starts.
format(value) => stringFull control of the rendered string — currency, compact, units.
decimals / prefix / suffixnumber / stringShorthand when `format` is overkill.
startOnViewbooleantrueWait until it scrolls into view.

Every component also forwards the native attributes of its root element, plus class, so anything not listed here still works.