use-reduced-motion.mjs 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. import { warnOnce } from 'motion-utils';
  2. import { useState } from 'react';
  3. import { initPrefersReducedMotion } from './index.mjs';
  4. import { hasReducedMotionListener, prefersReducedMotion } from './state.mjs';
  5. /**
  6. * A hook that returns `true` if we should be using reduced motion based on the current device's Reduced Motion setting.
  7. *
  8. * This can be used to implement changes to your UI based on Reduced Motion. For instance, replacing motion-sickness inducing
  9. * `x`/`y` animations with `opacity`, disabling the autoplay of background videos, or turning off parallax motion.
  10. *
  11. * It will actively respond to changes and re-render your components with the latest setting.
  12. *
  13. * ```jsx
  14. * export function Sidebar({ isOpen }) {
  15. * const shouldReduceMotion = useReducedMotion()
  16. * const closedX = shouldReduceMotion ? 0 : "-100%"
  17. *
  18. * return (
  19. * <motion.div animate={{
  20. * opacity: isOpen ? 1 : 0,
  21. * x: isOpen ? 0 : closedX
  22. * }} />
  23. * )
  24. * }
  25. * ```
  26. *
  27. * @return boolean
  28. *
  29. * @public
  30. */
  31. function useReducedMotion() {
  32. /**
  33. * Lazy initialisation of prefersReducedMotion
  34. */
  35. !hasReducedMotionListener.current && initPrefersReducedMotion();
  36. const [shouldReduceMotion] = useState(prefersReducedMotion.current);
  37. if (process.env.NODE_ENV !== "production") {
  38. warnOnce(shouldReduceMotion !== true, "You have Reduced Motion enabled on your device. Animations may not appear as expected.");
  39. }
  40. /**
  41. * TODO See if people miss automatically updating shouldReduceMotion setting
  42. */
  43. return shouldReduceMotion;
  44. }
  45. export { useReducedMotion };