fix: react to prefers-reduced-motion changes in Video

The reduced-motion check ran once on mount, so toggling the OS setting
while the page was open either kept videos auto-playing or left them
permanently inert. Listen for MediaQueryList changes: pause and drop
the observer when reduced motion turns on, re-observe when it turns
off.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eduard Gert
2026-08-20 16:02:51 +02:00
parent a83e6d2ee1
commit 370efaa1dc

View File

@@ -19,20 +19,42 @@ export function Video({ src, label, className, ...props }) {
useEffect(() => {
const video = ref.current
if (!video) return
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
video.play().catch(() => {})
} else {
video.pause()
}
},
{ threshold: 0.25 }
)
observer.observe(video)
return () => observer.disconnect()
const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)')
let observer = null
const observe = () => {
observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
video.play().catch(() => {})
} else {
video.pause()
}
},
{ threshold: 0.25 }
)
observer.observe(video)
}
// React to the OS setting changing while the page is open.
const handleMotionChange = () => {
if (reducedMotion.matches) {
observer?.disconnect()
observer = null
video.pause()
} else if (!observer) {
observe()
}
}
if (!reducedMotion.matches) observe()
reducedMotion.addEventListener('change', handleMotionChange)
return () => {
reducedMotion.removeEventListener('change', handleMotionChange)
observer?.disconnect()
}
}, [])
return (