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 ReduceMotionConfig docs #6165

Merged
merged 13 commits into from
Jul 16, 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
2 changes: 1 addition & 1 deletion packages/docs-reanimated/docs/advanced/_category_.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"label": "Advanced APIs",
"position": 9,
"position": 110,
"link": {
"type": "generated-index"
}
Expand Down
2 changes: 1 addition & 1 deletion packages/docs-reanimated/docs/animations/_category_.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"label": "Animations",
"position": 2,
"position": 20,
"link": {
"type": "generated-index"
}
Expand Down
66 changes: 66 additions & 0 deletions packages/docs-reanimated/docs/components/ReduceMotionConfig.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
id: ReduceMotionConfig
title: ReduceMotionConfig
sidebar_label: ReduceMotionConfig
sidebar_position: 1
---

The `ReduceMotionConfig` component determines the default animation behavior in response to the device's reduced motion accessibility setting. It affects your application globally. The default behavior disables all animation if reduced motion is enabled on a device. You can utilize this component to override that behavior. If you wish to fine-tune it for your specific case, learn more about [Accessibility](../guides/accessibility) and [`useReducedMotion`](../device/useReducedMotion) in Reanimated.

## Reference

```javascript
import { ReduceMotionConfig, ReduceMotion } from 'react-native-reanimated';

function App() {
return (
// ...
// highlight-next-line
<ReduceMotionConfig mode={ReduceMotion.Never} />
// ...
);
}
```

<details>
<summary>Type definitions</summary>

```typescript
interface ReduceMotionConfigProps {
mode: ReduceMotion;
}

enum ReduceMotion {
System = 'system',
Always = 'always',
Never = 'never',
}
```

</details>

### Arguments

#### `mode`

A parameter that determines what should be the default animation responds to the device's reduced motion accessibility setting.

## Example

import ReduceMotionConfig from '@site/src/examples/ReduceMotionConfig';
import ReduceMotionConfigSrc from '!!raw-loader!@site/src/examples/ReduceMotionConfig';

<InteractiveExample
src={ReduceMotionConfigSrc}
component={ReduceMotionConfig}
/>

## Platform compatibility

<div className="platform-compatibility">

| Android | iOS | Web |
| ------- | --- | --- |
| ✅ | ✅ | ✅ |

</div>
7 changes: 7 additions & 0 deletions packages/docs-reanimated/docs/components/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"label": "Components",
"position": 60,
"link": {
"type": "generated-index"
}
}
2 changes: 1 addition & 1 deletion packages/docs-reanimated/docs/core/_category_.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"label": "Core",
"position": 3,
"position": 30,
"link": {
"type": "generated-index"
}
Expand Down
2 changes: 1 addition & 1 deletion packages/docs-reanimated/docs/device/_category_.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"label": "Device",
"position": 5,
"position": 50,
"link": {
"type": "generated-index"
}
Expand Down
2 changes: 1 addition & 1 deletion packages/docs-reanimated/docs/fundamentals/_category_.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"label": "Fundamentals",
"position": 1,
"position": 10,
"link": {
"type": "generated-index"
}
Expand Down
2 changes: 1 addition & 1 deletion packages/docs-reanimated/docs/guides/_category_.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"label": "Guides",
"position": 10,
"position": 120,
"link": {
"type": "generated-index"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"label": "Layout Animations",
"position": 5,
"position": 70,
"link": {
"type": "generated-index"
}
Expand Down
2 changes: 1 addition & 1 deletion packages/docs-reanimated/docs/scroll/_category_.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"label": "Scroll",
"position": 4,
"position": 40,
"link": {
"type": "generated-index"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"label": "Shared Element Transitions",
"position": 7,
"position": 80,
"link": {
"type": "generated-index"
}
Expand Down
2 changes: 1 addition & 1 deletion packages/docs-reanimated/docs/threading/_category_.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"label": "Threading",
"position": 7,
"position": 90,
"link": {
"type": "generated-index"
}
Expand Down
2 changes: 1 addition & 1 deletion packages/docs-reanimated/docs/utilities/_category_.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"label": "Utilities",
"position": 8,
"position": 100,
"link": {
"type": "generated-index"
}
Expand Down
42 changes: 42 additions & 0 deletions packages/docs-reanimated/src/examples/ReduceMotionConfig.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { useEffect } from 'react';
import { StyleSheet, View } from 'react-native';
import Animated, {
useAnimatedStyle,
useSharedValue,
withRepeat,
withTiming,
ReduceMotionConfig,
ReduceMotion,
} from 'react-native-reanimated';

export default function App() {
const sv = useSharedValue<number>(0);
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ rotate: `${sv.value}deg` }],
}));

useEffect(() => {
sv.value = withRepeat(withTiming(360, { duration: 2000 }), -1, true);
});

return (
<View style={styles.container}>
{/* I'll uncomment if after merge of ReduceMotionConfig to main and new nightly release, because now component is unavailable */}
{/* <ReduceMotionConfig mode={ReduceMotion.Never} /> */}
<Animated.View style={[styles.box, animatedStyle]} />
</View>
piaskowyk marked this conversation as resolved.
Show resolved Hide resolved
);
}

const styles = StyleSheet.create({
box: {
height: 100,
width: 100,
backgroundColor: '#b58df1',
borderRadius: 20,
},
container: {
flex: 1,
alignItems: 'center',
},
});
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}'.`
);
}

useEffect(() => {
const wasEnabled = IS_REDUCED_MOTION.value;
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