# `react-doctor/require-reduced-motion`

Project ships a motion library but never gates animation on the user's reduced-motion preference — add `useReducedMotion()` / `<MotionConfig reducedMotion="user">` or a `@media (prefers-reduced-motion: reduce)` query

- **Category:** Accessibility
- **Severity:** error
- **Source:** react-doctor-core
- **Framework:** global
- **Enabled when:** always (project depends on a known motion library)
- **Documentation:** <https://www.w3.org/WAI/WCAG21/Understanding/animation-from-interactions>

## Validation prompt

Use this to decide whether a fired diagnostic is real or a false positive.

Project-level heuristic that fires ONCE (on package.json) when a dependency or devDependency is a known motion library (framer-motion / motion, react-spring, gsap, @react-spring/*, react-native-reanimated, etc.) AND a repo-wide text scan of *.ts/*.tsx/*.js/*.jsx/*.css/*.scss finds none of `prefers-reduced-motion`, `useReducedMotion`, `MotionConfig`, or `reducedMotion`. CONFIRM when the app actually animates (page/route transitions, parallax, auto-playing or looping motion, spring physics) and nothing in the codebase respects the OS "reduce motion" setting — this is a WCAG 2.3.3 failure. SUPPRESS when reduced-motion handling exists but the grep can't see it: it lives in a file type outside the scanned globs (MDX, a `.styl`/`.less` sheet, a templated or build-generated stylesheet, an inline `<style>` in HTML), the motion dependency is present only for non-animating utilities (easing math, a `useInView` observer, layout measurement) so no real animation ships, or animation is delegated to a component library/design system that already honors the preference globally. Do not flag a library listed but unused.

## Fix prompt

Use this once validation confirms the diagnostic is real.

Honor the user's OS "reduce motion" setting for every non-essential animation rather than deleting motion outright (WCAG 2.3.3). For Framer Motion / `motion`: read `const shouldReduceMotion = useReducedMotion()` and drop or shorten transforms/opacity/transition when it's true, or wrap the app once in `<MotionConfig reducedMotion="user">` so transform/layout animations are auto-reduced. For react-spring use the `useReducedMotion` hook to swap to immediate/zero-duration springs; for Reanimated check `AccessibilityInfo.isReduceMotionEnabled()` / `useReducedMotion`. For CSS-driven or other animation, add a global guard: `@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; } }`, then pare back parallax and auto-playing motion. Keep essential, information-carrying motion but make it calm. See https://www.w3.org/WAI/WCAG21/Understanding/animation-from-interactions
