Skip to content

Commit

Permalink
feat: create useReducedMotion and apply to useMotion to skip all moti…
Browse files Browse the repository at this point in the history
…on calculations
  • Loading branch information
marcosmoura committed Aug 25, 2023
1 parent 03a806a commit d2dca9d
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@fluentui/react-jsx-runtime": "^9.0.1",
"@fluentui/react-theme": "^9.1.11",
"@fluentui/react-utilities": "^9.11.2",
"@fluentui/react-shared-contexts": "^9.7.2",
"@griffel/react": "^1.5.14",
"@swc/helpers": "^0.4.14"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import { useAnimationFrame, useTimeout, usePrevious, useFirstMount } from '@fluentui/react-utilities';

import { useReducedMotion } from './useReducedMotion';
import { getMotionDuration } from '../utils/dom-style';
import type { HTMLElementWithStyledMap } from '../utils/dom-style';

Expand Down Expand Up @@ -92,10 +93,11 @@ function useMotionPresence<Element extends HTMLElement>(

const [currentElement, setCurrentElement] = React.useState<HTMLElementWithStyledMap<Element> | null>(null);

const isReducedMotion = useReducedMotion();
const isFirstReactRender = useFirstMount();
const isFirstDOMRender = useFirstMountCondition(!!currentElement);
const isInitiallyPresent = React.useRef<boolean>(presence).current;
const disableAnimation = isFirstDOMRender && isInitiallyPresent && !animateOnFirstMount;
const disableAnimation = isReducedMotion || (isFirstDOMRender && isInitiallyPresent && !animateOnFirstMount);

const ref: React.RefCallback<HTMLElementWithStyledMap<Element>> = React.useCallback(node => {
if (!node) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as React from 'react';
import { canUseDOM, useIsomorphicLayoutEffect } from '@fluentui/react-utilities';
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';

/**
* @internal
*
* Returns whether the user has requested reduced motion based on the current media query.
*/
export const useReducedMotion = (): boolean => {
const fluent = useFluent();
const reducedMotion = React.useRef(false);
const targetWindow = canUseDOM() && fluent.targetDocument?.defaultView;

const onMediaQueryChange = React.useCallback((e: MediaQueryListEvent) => {
reducedMotion.current = e.matches;
}, []);

useIsomorphicLayoutEffect(() => {
if (!targetWindow || !targetWindow.matchMedia) {
return;
}

const match = targetWindow.matchMedia('screen and (prefers-reduced-motion: reduce)');

if (match.matches) {
reducedMotion.current = true;
}

match.addEventListener('change', onMediaQueryChange);

return () => match.removeEventListener('change', onMediaQueryChange);
}, [onMediaQueryChange, targetWindow]);

return reducedMotion.current;
};

0 comments on commit d2dca9d

Please sign in to comment.