Reduced motion
What happens under prefers-reduced-motion: reduce
The engine receives reducedMotion: true in its state and takes a separate branch for every
preset — nothing keeps moving. Concretely:
- Entry / exit presets (
appear,disappear,drawOn,drawOff) become a short crossfade to the final visibility. The crossfade length isconfig.reducedMotion.crossfadeDuration. - One-shots (
bounce,wiggle,rotate,scale,metaphorical) rest on the settled pose. - Loops (
pulse,breathe) rest on the settled pose. - Value-driven presets keep their datum without a sweep:
variableColorlights the steps up tovaluesolid and dims the rest to the configured floor;progressshows the static position.
The per-preset scorecard checks this on the corpus: reducedMotionRests holds for every preset.
Controlling it
| Where | How |
| --- | --- |
| Per icon | reducedMotion="system" \| "always" \| "never" prop (default system). |
| Per app | Wrap in <SymbolProvider config={{ reducedMotion: { crossfadeDuration } }}> to tune the crossfade. |
| In your own code | useReducedMotion() returns the effective boolean and tracks OS changes live. |
"never" opts an icon out of the OS setting. Use it only where the motion itself carries the
information (a progress sweep on a loading screen, for instance) and the settled frame would not.
Reduced transparency
useReducedTransparency() tracks prefers-reduced-transparency: reduce for apps that layer their own
translucency over an icon. It does not change what an icon paints: monochrome — the only rendering
mode at 0.x — is unaffected by the setting.
On this site
The library inspector has a Reduce motion switch. Off follows your system setting; on forces
reducedMotion="always" for the preview and is remembered in this browser (localStorage). The
switch never overrides an OS setting that already asks for reduced motion.