-
-
Notifications
You must be signed in to change notification settings - Fork 880
/
Copy pathuse-reduced-motion.ts
66 lines (55 loc) · 1.91 KB
/
use-reduced-motion.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { useState } from "react"
import { motionValue, MotionValue } from "../value"
import { useOnChange } from "../value/use-on-change"
// Does this device prefer reduced motion? Returns `null` server-side.
let prefersReducedMotion: MotionValue<boolean | null>
function initPrefersReducedMotion() {
prefersReducedMotion = motionValue(null)
if (typeof window === "undefined") return
if (window.matchMedia) {
const motionMediaQuery = window.matchMedia("(prefers-reduced-motion)")
const setReducedMotionPreferences = () =>
prefersReducedMotion.set(motionMediaQuery.matches)
motionMediaQuery.addListener(setReducedMotionPreferences)
setReducedMotionPreferences()
} else {
prefersReducedMotion.set(false)
}
}
/**
* A hook that returns `true` if we should be using reduced motion based on the current device's Reduced Motion setting.
*
* This can be used to implement changes to your UI based on Reduced Motion. For instance, replacing motion-sickness inducing
* `x`/`y` animations with `opacity`, disabling the autoplay of background videos, or turning off parallax motion.
*
* It will actively respond to changes and re-render your components with the latest setting.
*
* ```jsx
* export function Sidebar({ isOpen }) {
* const shouldReduceMotion = useReducedMotion()
* const closedX = shouldReduceMotion ? 0 : "-100%"
*
* return (
* <motion.div animate={{
* opacity: isOpen ? 1 : 0,
* x: isOpen ? 0 : closedX
* }} />
* )
* }
* ```
*
* @return boolean
*
* @public
*/
export function useReducedMotion() {
/**
* Lazy initialisation of prefersReducedMotion
*/
!prefersReducedMotion && initPrefersReducedMotion()
const [shouldReduceMotion, setShouldReduceMotion] = useState(
prefersReducedMotion.get()
)
useOnChange(prefersReducedMotion, setShouldReduceMotion)
return shouldReduceMotion
}