Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ReducedMotionConfig component #6164

Merged
merged 16 commits into from
Jul 15, 2024
12 changes: 11 additions & 1 deletion apps/common-app/src/examples/ReducedMotionExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Animated, {
withSpring,
withSequence,
ReduceMotion,
ReduceMotionConfig,
} from 'react-native-reanimated';
import {
Gesture,
Expand Down Expand Up @@ -126,18 +127,27 @@ const EXAMPLES = [

export default function ReducedMotionExample() {
const [currentExample, setCurrentExample] = useState(0);

const [reduceMotion, setReduceMotion] = useState(ReduceMotion.Never);
const { component, exampleList } = EXAMPLES[currentExample];

function handleReduceMotionModeChange() {
setReduceMotion(reduceMotion === ReduceMotion.System ? ReduceMotion.Never : ReduceMotion.System);
}

return (
<View style={styles.container}>
<Button
onPress={handleReduceMotionModeChange}
title={`Overwrite reduce motion: ${reduceMotion}`}
/>
{EXAMPLES.map((example, i) => (
<Button
key={i}
onPress={() => setCurrentExample(i)}
title={example.title}
/>
))}
<ReduceMotionConfig mode={reduceMotion} />
{component}
<View key={currentExample}>
{exampleList.map((example, i) => {
Expand Down
8 changes: 4 additions & 4 deletions packages/react-native-reanimated/src/animation/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ import {
subtractMatrices,
getRotationMatrix,
} from './transformationMatrix/matrixUtils';
import { isReducedMotion, shouldBeUseWeb } from '../PlatformChecker';
import { shouldBeUseWeb } from '../PlatformChecker';
import type { EasingFunction, EasingFunctionFactory } from '../Easing';
import { IS_REDUCED_MOTION } from '../hook/useReducedMotion';

let IN_STYLE_UPDATER = false;
const IS_REDUCED_MOTION = isReducedMotion();
const SHOULD_BE_USE_WEB = shouldBeUseWeb();

if (__DEV__ && IS_REDUCED_MOTION) {
if (__DEV__ && IS_REDUCED_MOTION.value) {
console.warn(
`[Reanimated] Reduced motion setting is enabled on this device. This warning is visible only in the development mode. Some animations will be disabled by default. You can override the behavior for individual animations, see https://docs.swmansion.com/react-native-reanimated/docs/guides/troubleshooting#reduced-motion-setting-is-enabled-on-this-device.`
);
Expand Down Expand Up @@ -111,7 +111,7 @@ export function recognizePrefixSuffix(
export function getReduceMotionFromConfig(config?: ReduceMotion) {
'worklet';
return !config || config === ReduceMotion.System
? IS_REDUCED_MOTION
? IS_REDUCED_MOTION.value
: config === ReduceMotion.Always;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict';
import { useEffect, useRef } from 'react';
import { ReduceMotion } from '../commonTypes';
import { IS_REDUCED_MOTION } from '../hook/useReducedMotion';

/**
* A component that lets you overwrite default reduce motion behavior globally in your application.
*
* @param mode - Determines default reduce motion behavior globally in your application. Configured with {@link ReduceMotion} enum.
* @see https://docs.swmansion.com/react-native-reanimated/docs/components/ReduceMotionConfig
*/
export function ReduceMotionConfig({ mode }: { mode: ReduceMotion }) {
const firstRender = useRef(true);
if (__DEV__ && firstRender.current) {
firstRender.current = false;
console.warn(
`[Reanimated] Reduced motion setting is overwritten with mode '${mode}'.`
);
}
szydlovsky marked this conversation as resolved.
Show resolved Hide resolved

useEffect(() => {
const wasEnabled = IS_REDUCED_MOTION.value;
piaskowyk marked this conversation as resolved.
Show resolved Hide resolved
if (mode === ReduceMotion.Never) {
IS_REDUCED_MOTION.value = false;
}
return () => {
IS_REDUCED_MOTION.value = wasEnabled;
};
}, [mode]);

return null;
}
5 changes: 3 additions & 2 deletions packages/react-native-reanimated/src/hook/useReducedMotion.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use strict';
import { isReducedMotion } from '../PlatformChecker';
import { makeMutable } from '../core';

const IS_REDUCED_MOTION = isReducedMotion();
export const IS_REDUCED_MOTION = makeMutable(isReducedMotion());

/**
* Lets you query the reduced motion system setting.
Expand All @@ -12,5 +13,5 @@ const IS_REDUCED_MOTION = isReducedMotion();
* @see https://docs.swmansion.com/react-native-reanimated/docs/device/useReducedMotion
*/
export function useReducedMotion() {
return IS_REDUCED_MOTION;
return IS_REDUCED_MOTION.value;
}
1 change: 1 addition & 0 deletions packages/react-native-reanimated/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ export {
} from './jestUtils';
export { LayoutAnimationConfig } from './component/LayoutAnimationConfig';
export { PerformanceMonitor } from './component/PerformanceMonitor';
export { ReduceMotionConfig } from './component/ReduceMotionConfig';
export type {
Adaptable,
AdaptTransforms,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import { scheduleAnimationCleanup } from './domUtils';
import { _updatePropsJS } from '../../js-reanimated';
import type { ReanimatedHTMLElement } from '../../js-reanimated';
import { ReduceMotion } from '../../commonTypes';
import { isReducedMotion } from '../../PlatformChecker';
import { LayoutAnimationType } from '../animationBuilder/commonTypes';
import type { ReanimatedSnapshot, ScrollOffsets } from './componentStyle';
import { setDummyPosition, snapshots } from './componentStyle';
import { IS_REDUCED_MOTION } from '../../hook/useReducedMotion';

function getEasingFromConfig(config: CustomConfig): string {
const easingName =
Expand Down Expand Up @@ -48,7 +48,7 @@ function getDelayFromConfig(config: CustomConfig): number {

export function getReducedMotionFromConfig(config: CustomConfig) {
if (!config.reduceMotionV) {
return isReducedMotion();
return IS_REDUCED_MOTION.value;
}

switch (config.reduceMotionV) {
Expand All @@ -57,7 +57,7 @@ export function getReducedMotionFromConfig(config: CustomConfig) {
case ReduceMotion.Always:
return true;
default:
return isReducedMotion();
return IS_REDUCED_MOTION.value;
}
}

Expand Down