diff --git a/.changeset/reduced-motion.md b/.changeset/reduced-motion.md new file mode 100644 index 0000000000..0ce1a65ad0 --- /dev/null +++ b/.changeset/reduced-motion.md @@ -0,0 +1,10 @@ +--- +"@executor-js/react": patch +--- + +fix: honor prefers-reduced-motion in the shared stylesheet + +Adds a `prefers-reduced-motion: reduce` block to the global stylesheet that +caps transition/animation durations to 0.01ms and disables smooth scrolling, +so motion-sensitive users get a stable UI. The loading spinner renders +statically under reduced motion (its meaning is preserved via `role="status"`). diff --git a/packages/react/src/styles/globals.css b/packages/react/src/styles/globals.css index edd97f3378..f6b2410037 100644 --- a/packages/react/src/styles/globals.css +++ b/packages/react/src/styles/globals.css @@ -294,3 +294,24 @@ opacity: 0.25; } } + +/* --------------------------------------------------------------------------- + * Reduced motion — WCAG 2.2 (motion-sensitive users). + * + * Neutralizes transitions/animations/scroll-behavior when the OS requests + * reduced motion, per the standard modern-CSS-reset pattern. The spinner + * (ios-spinner-fade) is capped to a single 0.01ms iteration — effectively + * static — which is the standard behavior: its meaning is preserved by + * `role="status"` (announced by assistive tech), and an opacity pulse would + * be a non-motion affordance but is not required for reduced-motion users. + * ------------------------------------------------------------------------- */ +@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; + } +}