@@ -3,6 +3,7 @@ import AnimationManager from "./AnimationManager";
33import useGetImageHeight from "./hooks/useGetImageHeight" ;
44import useGetTransitionValue from "./hooks/useGetTransitionValue" ;
55import useIntersectionObserver from "./hooks/useIntersectionObserver" ;
6+ import useReducedMotion from "./hooks/useReduceMotion" ;
67import { SimpleParallaxProps } from "./types" ;
78
89const SimpleParallax : React . FunctionComponent < SimpleParallaxProps > = ( {
@@ -26,7 +27,8 @@ const SimpleParallax: React.FunctionComponent<SimpleParallaxProps> = ({
2627 const [ transformCSS , setTransformCSS ] = useState ( "" ) ;
2728 const [ transitionCSS , setTransitionCSS ] = useState ( "" ) ;
2829 const [ shouldApplyTransition , setShouldApplyTransition ] = useState ( false ) ;
29-
30+
31+ const prefersReducedMotion = useReducedMotion ( ) ;
3032 const [ imageRef , imageHeight , isLoaded ] = useGetImageHeight ( src ) ;
3133 const [ elementRef , isVisible ] = useIntersectionObserver < HTMLDivElement > ( {
3234 root : null ,
@@ -43,7 +45,7 @@ const SimpleParallax: React.FunctionComponent<SimpleParallaxProps> = ({
4345 } ) ;
4446
4547 const updateParallax = useCallback ( ( ) => {
46- if ( ! isVisible && isInit ) return ;
48+ if ( ( ! isVisible && isInit ) || prefersReducedMotion ) return ;
4749
4850 if ( window . scrollY !== viewportTop || ! isInit ) {
4951 const boundingClientRect = imageRef . current ?. getBoundingClientRect ( ) ;
@@ -52,43 +54,53 @@ const SimpleParallax: React.FunctionComponent<SimpleParallaxProps> = ({
5254 }
5355 if ( ! isInit ) {
5456 setIsInit ( true ) ;
57+ // We'll enable transitions after the first calculation
5558 setTimeout ( ( ) => {
5659 setShouldApplyTransition ( true ) ;
5760 } , 50 ) ;
5861 }
5962 setViewportTop ( window . scrollY ) ;
6063 }
61- } , [ viewportTop , isVisible , imageRef , isInit ] ) ;
64+ } , [ viewportTop , isVisible , imageRef , isInit , prefersReducedMotion ] ) ;
6265
6366 useEffect ( ( ) => {
67+ if ( prefersReducedMotion ) {
68+ setTransformCSS ( "" ) ;
69+ return ;
70+ }
71+
6472 let transform = `translate3d(${ transitionValue } )` ;
6573 if ( ! overflow ) {
6674 transform += ` scale(${ scale } )` ;
6775 }
6876 setTransformCSS ( transform ) ;
69- } , [ transitionValue , scale , overflow ] ) ;
77+ } , [ transitionValue , scale , overflow , prefersReducedMotion ] ) ;
7078
7179 useEffect ( ( ) => {
72- if ( ! transition || ! delay || ! shouldApplyTransition ) {
80+ if ( ! transition || ! delay || ! shouldApplyTransition || prefersReducedMotion ) {
7381 setTransitionCSS ( "" ) ;
7482 return ;
7583 }
7684 setTransitionCSS ( `transform ${ delay } s ${ transition } ` ) ;
77- } , [ transition , delay , shouldApplyTransition ] ) ;
85+ } , [ transition , delay , shouldApplyTransition , prefersReducedMotion ] ) ;
7886
7987 useEffect ( ( ) => {
80- AnimationManager . register ( updateParallax ) ;
88+ // Only register for animation if reduced motion is not preferred
89+ if ( ! prefersReducedMotion ) {
90+ AnimationManager . register ( updateParallax ) ;
91+ }
92+
8193 return ( ) => {
8294 AnimationManager . unregister ( updateParallax ) ;
8395 } ;
84- } , [ updateParallax ] ) ;
96+ } , [ updateParallax , prefersReducedMotion ] ) ;
8597
8698 const clonedChild = React . isValidElement ( children )
8799 ? React . cloneElement ( children as React . ReactElement , {
88100 style : {
89101 ...( ( children as React . ReactElement ) . props . style ?? { } ) ,
90102 transform : transformCSS ,
91- willChange : "transform" ,
103+ willChange : prefersReducedMotion ? "auto" : "transform" ,
92104 transition : transitionCSS ,
93105 } ,
94106 ref : imageRef ,
0 commit comments