Skip to content

Commit f25fef1

Browse files
docs: add Shared Element Transitions docs (#1252)
* Draft SET docs * Add examples and video * rephrase alternatives * fix grammar * Add page to v7 * Remove unused variable * Rephrase explaination * Bring changes to v6 * docs: apply feedback
1 parent c7797c2 commit f25fef1

File tree

5 files changed

+266
-0
lines changed

5 files changed

+266
-0
lines changed
Binary file not shown.
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Animating elements between screens
2+
3+
This guide covers how to animate elements between screens. This feature is known as a [Shared Element Transition](https://docs.swmansion.com/react-native-reanimated/docs/api/sharedElementTransitions) and it's implemented in the [`@react-navigation/native-stack`](<(/docs/native-stack-navigator)>) with [React Native Reanimated](https://docs.swmansion.com/react-native-reanimated/).
4+
5+
> Note: As of writing this guide, Shared Element Transitions are considered an experimental feature not recommended for production use.
6+
7+
<div style={{ display: 'flex', margin: '16px 0' }}>
8+
<video playsInline autoPlay muted loop>
9+
<source src="/assets/shared-element-transitions/shared-element-transitions.mp4" />
10+
</video>
11+
</div>
12+
13+
## Pre-requisites
14+
15+
Before continuing this guide make sure your app meets these criteria:
16+
17+
- You are using [`@react-navigation/native-stack`](/docs/native-stack-navigator). The Shared Element Transitions feature isn't supported in JS-based [`@react-navigation/stack`](/docs/stack-navigator).
18+
- You have [`react-native-reanimated`](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/installation) **v3.0.0 or higher** installed and configured.
19+
20+
## Minimal example
21+
22+
To create a shared transition:
23+
24+
1. Use `Animated` components imported from `react-native-reanimated`.
25+
2. Assign the same `sharedTransitionTag` to elements on different screens.
26+
3. Navigate between screens. The transition will start automatically.
27+
28+
```jsx
29+
import * as React from 'react';
30+
import { View, Button, StyleSheet } from 'react-native';
31+
import { NavigationContainer } from '@react-navigation/native';
32+
import { createNativeStackNavigator } from '@react-navigation/native-stack';
33+
34+
import Animated from 'react-native-reanimated';
35+
36+
// highlight-next-line
37+
const Stack = createNativeStackNavigator();
38+
39+
function HomeScreen({ navigation }) {
40+
return (
41+
<View style={styles.container}>
42+
<Button
43+
title="Go to Details"
44+
onPress={() => navigation.navigate('Details')}
45+
/>
46+
<Animated.Image
47+
source={{ uri: 'https://picsum.photos/id/39/200' }}
48+
style={{ width: 300, height: 300 }}
49+
// highlight-next-line
50+
sharedTransitionTag="tag"
51+
/>
52+
</View>
53+
);
54+
}
55+
56+
function DetailsScreen({ navigation }) {
57+
return (
58+
<View style={styles.container}>
59+
<Button title="Go back" onPress={() => navigation.goBack()} />
60+
<Animated.Image
61+
source={{ uri: 'https://picsum.photos/id/39/200' }}
62+
style={{ width: 100, height: 100 }}
63+
// highlight-next-line
64+
sharedTransitionTag="tag"
65+
/>
66+
</View>
67+
);
68+
}
69+
70+
export default function App() {
71+
return (
72+
<NavigationContainer>
73+
<Stack.Navigator>
74+
<Stack.Screen name="Home" component={HomeScreen} />
75+
<Stack.Screen name="Details" component={DetailsScreen} />
76+
</Stack.Navigator>
77+
</NavigationContainer>
78+
);
79+
}
80+
81+
const styles = StyleSheet.create({
82+
container: {
83+
flex: 1,
84+
alignItems: 'center',
85+
},
86+
});
87+
```
88+
89+
`sharedTransitionTag` is a string that has to be unique in the context of a single screen, but has to match elements between screens. This prop allows Reanimated to identify and animate the elements, similarly to the [`key`](https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key) property, which tells React which element in the list is which.
90+
91+
## Customizing the transition
92+
93+
By default, the transition animates the `width`, `height`, `originX`, `originY` and `transform` properties using `withTiming` with a 500 ms duration. You can easily customize `width`, `height`, `originX`, and `originY` props. Customizing `transform` is also possible but it's far beyond the scope of this guide.
94+
95+
> Note: Custom SharedTransition API is not finalized and might change in a future release.
96+
97+
To customize the transition you need to pass all the properties besides `transform`.
98+
99+
```jsx
100+
import { SharedTransition } from 'react-native-reanimated';
101+
102+
const customTransition = SharedTransition.custom((values) => {
103+
'worklet';
104+
return {
105+
height: withSpring(values.targetHeight),
106+
width: withSpring(values.targetWidth),
107+
originX: withSpring(values.targetOriginX),
108+
originY: withSpring(values.targetOriginY),
109+
};
110+
});
111+
112+
function HomeScreen() {
113+
return (
114+
<Animated.Image
115+
style={{ width: 300, height: 300 }}
116+
sharedTransitionTag="tag"
117+
// highlight-next-line
118+
sharedTransitionStyle={customTransition} // add this to both elements on both screens
119+
/>
120+
);
121+
}
122+
```
123+
124+
## Reference
125+
126+
You can find a full Shared Element Transitions reference in the [React Native Reanimated documentation](https://docs.swmansion.com/react-native-reanimated/docs/api/sharedElementTransitions).
127+
128+
## Alternatives
129+
130+
Alternatively, you can use [`react-native-shared-element`](https://github.com/IjzerenHein/react-native-shared-element) library with a [React Navigation binding](https://github.com/IjzerenHein/react-navigation-shared-element) which implements Shared Element Transitions in a JS-based `@react-navigation/stack` navigator. This solution, however, isn't actively maintained.
131+
132+
The [`react-native-navigation`](https://github.com/wix/react-native-navigation) also comes with support for Shared Element Transitions. You can read more about it [here](https://wix.github.io/react-native-navigation/docs/style-animations#shared-element-transitions).
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Animating elements between screens
2+
3+
This guide covers how to animate elements between screens. This feature is known as a [Shared Element Transition](https://docs.swmansion.com/react-native-reanimated/docs/api/sharedElementTransitions) and it's implemented in the [`@react-navigation/native-stack`](<(/docs/native-stack-navigator)>) with [React Native Reanimated](https://docs.swmansion.com/react-native-reanimated/).
4+
5+
> Note: As of writing this guide, Shared Element Transitions are considered an experimental feature not recommended for production use.
6+
7+
<div style={{ display: 'flex', margin: '16px 0' }}>
8+
<video playsInline autoPlay muted loop>
9+
<source src="/assets/shared-element-transitions/shared-element-transitions.mp4" />
10+
</video>
11+
</div>
12+
13+
## Pre-requisites
14+
15+
Before continuing this guide make sure your app meets these criteria:
16+
17+
- You are using [`@react-navigation/native-stack`](/docs/native-stack-navigator). The Shared Element Transitions feature isn't supported in JS-based [`@react-navigation/stack`](/docs/stack-navigator).
18+
- You have [`react-native-reanimated`](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/installation) **v3.0.0 or higher** installed and configured.
19+
20+
## Minimal example
21+
22+
To create a shared transition:
23+
24+
1. Use `Animated` components imported from `react-native-reanimated`.
25+
2. Assign the same `sharedTransitionTag` to elements on different screens.
26+
3. Navigate between screens. The transition will start automatically.
27+
28+
```jsx
29+
import * as React from 'react';
30+
import { View, Button, StyleSheet } from 'react-native';
31+
import { NavigationContainer } from '@react-navigation/native';
32+
import { createNativeStackNavigator } from '@react-navigation/native-stack';
33+
34+
import Animated from 'react-native-reanimated';
35+
36+
// highlight-next-line
37+
const Stack = createNativeStackNavigator();
38+
39+
function HomeScreen({ navigation }) {
40+
return (
41+
<View style={styles.container}>
42+
<Button
43+
title="Go to Details"
44+
onPress={() => navigation.navigate('Details')}
45+
/>
46+
<Animated.Image
47+
source={{ uri: 'https://picsum.photos/id/39/200' }}
48+
style={{ width: 300, height: 300 }}
49+
// highlight-next-line
50+
sharedTransitionTag="tag"
51+
/>
52+
</View>
53+
);
54+
}
55+
56+
function DetailsScreen({ navigation }) {
57+
return (
58+
<View style={styles.container}>
59+
<Button title="Go back" onPress={() => navigation.goBack()} />
60+
<Animated.Image
61+
source={{ uri: 'https://picsum.photos/id/39/200' }}
62+
style={{ width: 100, height: 100 }}
63+
// highlight-next-line
64+
sharedTransitionTag="tag"
65+
/>
66+
</View>
67+
);
68+
}
69+
70+
export default function App() {
71+
return (
72+
<NavigationContainer>
73+
<Stack.Navigator>
74+
<Stack.Screen name="Home" component={HomeScreen} />
75+
<Stack.Screen name="Details" component={DetailsScreen} />
76+
</Stack.Navigator>
77+
</NavigationContainer>
78+
);
79+
}
80+
81+
const styles = StyleSheet.create({
82+
container: {
83+
flex: 1,
84+
alignItems: 'center',
85+
},
86+
});
87+
```
88+
89+
`sharedTransitionTag` is a string that has to be unique in the context of a single screen, but has to match elements between screens. This prop allows Reanimated to identify and animate the elements, similarly to the [`key`](https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key) property, which tells React which element in the list is which.
90+
91+
## Customizing the transition
92+
93+
By default, the transition animates the `width`, `height`, `originX`, `originY` and `transform` properties using `withTiming` with a 500 ms duration. You can easily customize `width`, `height`, `originX`, and `originY` props. Customizing `transform` is also possible but it's far beyond the scope of this guide.
94+
95+
> Note: Custom SharedTransition API is not finalized and might change in a future release.
96+
97+
To customize the transition you need to pass all the properties besides `transform`.
98+
99+
```jsx
100+
import { SharedTransition } from 'react-native-reanimated';
101+
102+
const customTransition = SharedTransition.custom((values) => {
103+
'worklet';
104+
return {
105+
height: withSpring(values.targetHeight),
106+
width: withSpring(values.targetWidth),
107+
originX: withSpring(values.targetOriginX),
108+
originY: withSpring(values.targetOriginY),
109+
};
110+
});
111+
112+
function HomeScreen() {
113+
return (
114+
<Animated.Image
115+
style={{ width: 300, height: 300 }}
116+
sharedTransitionTag="tag"
117+
// highlight-next-line
118+
sharedTransitionStyle={customTransition} // add this to both elements on both screens
119+
/>
120+
);
121+
}
122+
```
123+
124+
## Reference
125+
126+
You can find a full Shared Element Transitions reference in the [React Native Reanimated documentation](https://docs.swmansion.com/react-native-reanimated/docs/api/sharedElementTransitions).
127+
128+
## Alternatives
129+
130+
Alternatively, you can use [`react-native-shared-element`](https://github.com/IjzerenHein/react-native-shared-element) library with a [React Navigation binding](https://github.com/IjzerenHein/react-navigation-shared-element) which implements Shared Element Transitions in a JS-based `@react-navigation/stack` navigator. This solution, however, isn't actively maintained.
131+
132+
The [`react-native-navigation`](https://github.com/wix/react-native-navigation) also comes with support for Shared Element Transitions. You can read more about it [here](https://wix.github.io/react-native-navigation/docs/style-animations#shared-element-transitions).

versioned_sidebars/version-6.x-sidebars.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"version-6.x/multiple-drawers",
2626
"version-6.x/screen-options-resolution",
2727
"version-6.x/custom-android-back-button-handling",
28+
"version-6.x/shared-element-transitions",
2829
"version-6.x/preventing-going-back",
2930
"version-6.x/function-after-focusing-screen",
3031
"version-6.x/connecting-navigation-prop",

versioned_sidebars/version-7.x-sidebars.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"version-7.x/multiple-drawers",
2626
"version-7.x/screen-options-resolution",
2727
"version-7.x/custom-android-back-button-handling",
28+
"version-7.x/shared-element-transitions",
2829
"version-7.x/preventing-going-back",
2930
"version-7.x/function-after-focusing-screen",
3031
"version-7.x/connecting-navigation-prop",

0 commit comments

Comments
 (0)