-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add useReducedMotion hook & export useIsomorphicLayout hook (#1886
- Loading branch information
1 parent
35da18b
commit 3365cea
Showing
20 changed files
with
214 additions
and
46 deletions.
There are no files selected for viewing
Binary file removed
BIN
-856 KB
.yarn/cache/@testing-library-react-npm-13.0.0-b12618437f-75c2348cff.zip
Binary file not shown.
Binary file added
BIN
+865 KB
.yarn/cache/@testing-library-react-npm-13.2.0-a1a70b5e81-29f4a97c93.zip
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
packages/shared/src/hooks/useIsomorphicLayoutEffect.native.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { useLayoutEffect } from 'react' | ||
|
||
export { useLayoutEffect as useIsomorphicLayoutEffect } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { useEffect, useLayoutEffect } from 'react' | ||
|
||
import { isSSR } from '../helpers' | ||
|
||
/** | ||
* Use this to read layout from the DOM and synchronously | ||
* re-render if the isSSR returns true. Updates scheduled | ||
* inside `useIsomorphicLayoutEffect` will be flushed | ||
* synchronously in the browser, before the browser has | ||
* a chance to paint. | ||
*/ | ||
export const useIsomorphicLayoutEffect = isSSR() ? useEffect : useLayoutEffect |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { useState } from 'react' | ||
import { AccessibilityInfo } from 'react-native' | ||
|
||
import { assign } from '../globals' | ||
|
||
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect.native' | ||
|
||
/** | ||
* Returns `boolean` or `null`, used to automatically | ||
* set skipAnimations to the value of the user's | ||
* `prefers-reduced-motion` query. | ||
* | ||
* The return value, post-effect, is the value of their prefered setting | ||
*/ | ||
export const useReducedMotion = () => { | ||
const [reducedMotion, setReducedMotion] = useState<boolean | null>(null) | ||
|
||
useIsomorphicLayoutEffect(() => { | ||
const handleMediaChange = (isReducedMotion: boolean) => { | ||
setReducedMotion(isReducedMotion) | ||
|
||
assign({ | ||
skipAnimation: isReducedMotion, | ||
}) | ||
} | ||
|
||
AccessibilityInfo.isReduceMotionEnabled().then(handleMediaChange) | ||
|
||
const motionSubscription = AccessibilityInfo.addEventListener( | ||
'reduceMotionChanged', | ||
handleMediaChange | ||
) | ||
|
||
return () => { | ||
motionSubscription.remove() | ||
} | ||
}, []) | ||
|
||
return reducedMotion | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import { act, renderHook } from '@testing-library/react' | ||
|
||
import { useReducedMotion } from './useReducedMotion' | ||
|
||
describe('useReducedMotion', () => { | ||
let EVENTS: Record<string, MediaQueryHandler> = {} | ||
|
||
const removeEventListenerMock = jest.fn() | ||
|
||
type MediaQueryHandler = (mediaQuery: typeof mqDefaults) => void | ||
|
||
const mqDefaults = { | ||
matches: false, | ||
onchange: null, | ||
addEventListener: (name: string, handle: MediaQueryHandler) => { | ||
EVENTS[name] = handle | ||
}, | ||
removeEventListener: removeEventListenerMock, | ||
} | ||
|
||
afterEach(() => { | ||
// reset events | ||
EVENTS = {} | ||
|
||
jest.clearAllMocks() | ||
}) | ||
|
||
it('returns true if "Reduce motion" is enabled', async () => { | ||
window.matchMedia = jest.fn().mockImplementation(query => { | ||
return { | ||
...mqDefaults, | ||
matches: true, | ||
media: query, | ||
} | ||
}) | ||
|
||
const { result } = renderHook(useReducedMotion) | ||
|
||
expect(result.current).toBe(true) | ||
}) | ||
|
||
it('returns false if "Reduce motion" is disabled', async () => { | ||
window.matchMedia = jest.fn().mockImplementation(query => { | ||
return { | ||
...mqDefaults, | ||
media: query, | ||
} | ||
}) | ||
|
||
const { result } = renderHook(useReducedMotion) | ||
|
||
expect(result.current).toBe(false) | ||
}) | ||
|
||
it('handles change of "prefers-reduce-motion" media query value', async () => { | ||
window.matchMedia = jest.fn().mockImplementation(query => { | ||
return { | ||
...mqDefaults, | ||
media: query, | ||
} | ||
}) | ||
|
||
const { result } = renderHook(useReducedMotion) | ||
|
||
expect(result.current).toBe(false) | ||
|
||
act(() => { | ||
EVENTS.change({ | ||
...mqDefaults, | ||
matches: true, | ||
}) | ||
}) | ||
|
||
expect(result.current).toBe(true) | ||
}) | ||
|
||
it('successfully removes listener on unmount', () => { | ||
window.matchMedia = jest.fn().mockImplementation(query => { | ||
return { | ||
...mqDefaults, | ||
media: query, | ||
} | ||
}) | ||
|
||
const { unmount } = renderHook(useReducedMotion) | ||
|
||
unmount() | ||
|
||
expect(removeEventListenerMock).toHaveBeenCalled() | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { useState } from 'react' | ||
|
||
import { assign } from '../globals' | ||
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect' | ||
|
||
/** | ||
* Returns `boolean` or `null`, used to automatically | ||
* set skipAnimations to the value of the user's | ||
* `prefers-reduced-motion` query. | ||
* | ||
* The return value, post-effect, is the value of their prefered setting | ||
*/ | ||
export const useReducedMotion = () => { | ||
const [reducedMotion, setReducedMotion] = useState<boolean | null>(null) | ||
|
||
useIsomorphicLayoutEffect(() => { | ||
const mql = window.matchMedia('(prefers-reduced-motion)') | ||
|
||
const handleMediaChange = (e: MediaQueryListEvent | MediaQueryList) => { | ||
setReducedMotion(e.matches) | ||
|
||
assign({ | ||
skipAnimation: e.matches, | ||
}) | ||
} | ||
|
||
handleMediaChange(mql) | ||
|
||
mql.addEventListener('change', handleMediaChange) | ||
|
||
return () => { | ||
mql.removeEventListener('change', handleMediaChange) | ||
} | ||
}, []) | ||
|
||
return reducedMotion | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
3365cea
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
react-spring-io – ./
react-spring-io.vercel.app
react-spring.dev
react-spring-io-git-master-pmndrs.vercel.app
react-spring-io-pmndrs.vercel.app
www.react-spring.io
www.react-spring.dev
react-spring.io