Motion
Motion components
The motion prop on every overlay, and the small components behind the patterns: swap, roll, reveal, dissolve, resize, stream and scroll progress.
import { TextSwap, NumberRoll, Reveal, Presence, AutoHeight, StreamingText, ScrollProgress } from '@alea/motion';
Examples
Swap and roll
Text crossfades with a blur when it changes; digits roll to the new number.
$1,290
Reveal and stagger
Content enters as it scrolls into view; with stagger, children come one after another. Server HTML stays visible.
Tokens
Components
Motion
Presence and resize
Removed things dissolve before they unmount; AutoHeight animates size changes.
Alea Motion animates what changed.
Stream
An answer that arrives in chunks: each chunk fades in, a caret shows while it streams, a shimmer while thinking.
Success, ripple, badge and fan
Patterns built into components: isSuccess, ripple, CountBadge and AvatarGroup fan.
The motion prop
Every overlay takes motion: a preset, false, or { enter, exit, duration, easing, delay }.
Morph, dots and reveal
A menu that grows from its trigger, the 16-dot loader, and a skeleton that crossfades into content.
Props
TextSwap props
Text or an icon that changes with a short blur crossfade (the swap pattern). Give it a key-able value.
| Prop | Type | Default | Description |
|---|---|---|---|
as | ElementType | 'span' | |
className | string | - | |
direction | "up" | "down" | 'up' | |
variant | "scale" | "blur" | 'blur' |
NumberRoll props
A number whose digits roll to the new value (the roll pattern). Screen readers get the formatted value once.
| Prop | Type | Default | Description |
|---|---|---|---|
valuerequired | number | - | |
className | string | - | |
format | NumberFormatOptions | - | |
locale | string | - |
Reveal props
Content that enters when it scrolls into view (once). Without JavaScript it is simply shown.
| Prop | Type | Default | Description |
|---|---|---|---|
as | ElementType | 'div' | |
className | string | - | |
delay | number | - | Delay in ms. |
motion | "fade" | "scale" | "pop" | "rise" | "drop" | "slide-up" | "slide-down" | "slide-left" | "slide-right" | "blur" | "zoom" | "flip" | "morph" | "none" | MotionO… | 'rise' | The enter preset. Default rise. |
once | boolean | true | |
stagger | boolean | - | Children enter one after another instead of the whole block. |
style | CSSProperties | - |
Presence props
Keeps a child mounted while it plays its exit (the dissolve preset by default), then unmounts it.
| Prop | Type | Default | Description |
|---|---|---|---|
showrequired | boolean | - | |
exitClassName | string | 'alea-dissolve-out' |
AutoHeight props
Animates its height when its content changes size (the resize pattern).
| Prop | Type | Default | Description |
|---|---|---|---|
as | ElementType | 'div' | |
className | string | - |
StreamingText props
Text that arrives in chunks (AI answers): new chunks fade in, a caret shows while streaming.
| Prop | Type | Default | Description |
|---|---|---|---|
chunksrequired | string[] | - | |
as | ElementType | 'p' | |
className | string | - | |
streaming | boolean | false |
ScrollProgress props
A thin bar at the top that fills as the page scrolls (CSS scroll timeline where supported).
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - |
Specs
Generated from the source: the variants in the types, the states and tokens in the CSS, and the motion patterns that apply. The grids render the real component in both themes; the numbers are measured from the page.
TextSwap
NumberRoll
- Motion
- roll
- Dark and light
- Every color comes from theme tokens, so it follows data-theme (and presets like Graphite) on the page or any wrapper. Contrast is checked in both themes.
- Styling hooks
.alea-roll.alea-roll-digit.alea-roll-strip
Presence
- Motion
- dissolve
- Dark and light
- Every color comes from theme tokens, so it follows data-theme (and presets like Graphite) on the page or any wrapper. Contrast is checked in both themes.
- Styling hooks
.alea-dissolve-out
AutoHeight
- Motion
- resize
- Dark and light
- Every color comes from theme tokens, so it follows data-theme (and presets like Graphite) on the page or any wrapper. Contrast is checked in both themes.
- Styling hooks
.alea-autoheight
StreamingText
ScrollProgress
- Motion
- scroll
- Dark and light
- Every color comes from theme tokens, so it follows data-theme (and presets like Graphite) on the page or any wrapper. Contrast is checked in both themes.
- Styling hooks
.alea-scroll-progress
Accessibility
- Everything follows prefers-reduced-motion: distances, scales and blur go to zero, loops stop, and fades stay so changes are still noticed.
- NumberRoll and TextSwap announce the new value once (politely), never each frame.
- Reveal only hides content that starts below the fold and only after JavaScript runs, so server HTML and search engines see everything.
- StreamingText sets aria-busy while it streams.
Do and don't
Do
- Pick a preset for what changed: pop for anchored things, rise for page-level, slide for panels.
- Change motion globally with ThemeProvider motion={{ mode, speed, intensity, components }} before reaching for per-instance props.
- Use isSuccess for a moment after an action worked, then go back.
Don't
- Don't animate layout properties (width, top); the presets use transform and opacity.
- Don't make people wait for an animation to act.
- Don't turn motion off for everyone; respect the OS setting, or offer your own switch with reduced="never".