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.
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
IntersectionObserveris 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
indexinside an{#each}; each item waitsindex × 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.8ptCredits
0
−320API
Reveal
| Prop | Type | Default | Description |
|---|---|---|---|
y / x | number | 12 / 0 | Travel distance in px. Keep it small — long travel lies about where content came from. |
index / stagger | number | 0 / 60 | Position in a group and the per-item delay in ms. |
delay / duration | number | 0 / 500 | Extra delay and the transition length, in ms. |
repeat | boolean | false | Re-animate on every entry. Off on purpose. |
threshold | number | 0.15 | Fraction visible before it fires. |
Counter
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | — | Target. Changing it animates from the current display. |
from | number | 0 | Where the first run starts. |
format | (value) => string | — | Full control of the rendered string — currency, compact, units. |
decimals / prefix / suffix | number / string | — | Shorthand when `format` is overkill. |
startOnView | boolean | true | Wait 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.