Get Started

Introduction

Meet the experimental v4 Screen Transitions architecture for React Navigation and Expo Router.

react-native-screen-transitions is a transition toolkit for apps that need more control over navigation motion than the platform defaults.

Use it to build custom push and dismiss animations, gesture-driven screens, snap sheets, overlays, and bounds-driven transitions.

One navigator, two hosts

v4's Blank Stack is a Standard Navigator. The same transition navigator integrates with both React Navigation and Expo Router through host-specific package entry points.

Blank Stack is the default choice when Screen Transitions should drive the stack. withScreenTransitions remains available as an adapter for one-off animations inside an existing native stack.

v4 is experimental. Its navigation and bounds APIs may change before the stable release.

Continue to Installation, then connect your navigator in Getting Started.

Expo Router

Screen Transitions exports a BlankStack that is ready to use in an Expo Router layout. Replace the stack in the layout where you want Screen Transitions:

TSX

1// app/_layout.tsx
2import { GestureHandlerRootView } from "react-native-gesture-handler";
3import Transition from "react-native-screen-transitions";
4import { BlankStack } from "react-native-screen-transitions/expo-router";
5
6export default function RootLayout() {
7 return (
8 <GestureHandlerRootView style={{ flex: 1 }}>
9 <BlankStack>
10 <BlankStack.Screen name="index" />
11 <BlankStack.Screen
12 name="detail"
13 options={Transition.Presets.SlideFromBottom}
14 />
15 </BlankStack>
16 </GestureHandlerRootView>
17 );
18}

You can use BlankStack in the root layout or a nested _layout.tsx. Only the routes inside that layout participate in its transition stack.

Expo Router remains responsible for routing. Continue to navigate with router.push(), router.replace(), router.back(), or Link as usual.

React Navigation

Screen Transitions exports the same Blank Stack for React Navigation through its React Navigation entry point. Create it like any other React Navigation navigator:

TSX

1import { NavigationContainer } from "@react-navigation/native";
2import { GestureHandlerRootView } from "react-native-gesture-handler";
3import Transition from "react-native-screen-transitions";
4import { createBlankStackNavigator } from "react-native-screen-transitions/react-navigation";
5
6const Stack = createBlankStackNavigator();
7
8export default function App() {
9 return (
10 <GestureHandlerRootView style={{ flex: 1 }}>
11 <NavigationContainer>
12 <Stack.Navigator>
13 <Stack.Screen name="Home" component={HomeScreen} />
14 <Stack.Screen
15 name="Detail"
16 component={DetailScreen}
17 options={Transition.Presets.SlideFromBottom()}
18 />
19 </Stack.Navigator>
20 </NavigationContainer>
21 </GestureHandlerRootView>
22 );
23}

Blank Stack is implemented as a Standard Navigator, which lets the same navigator work with React Navigation and Expo Router. Your screens continue to navigate with navigation.navigate(), navigation.goBack(), and the rest of the standard React Navigation API.

Adapting a native stack

withScreenTransitions serves a different purpose. It wraps an existing native stack so you can opt individual screens into Screen Transitions animations while retaining native-stack behavior elsewhere:

TSX

1import { createNativeStackNavigator } from "@react-navigation/native-stack";
2import { withScreenTransitions } from "react-native-screen-transitions";
3
4const NativeStack = createNativeStackNavigator();
5const Stack = withScreenTransitions(NativeStack);

Use the adapter when you specifically need a native stack. For a stack driven entirely by Screen Transitions, use Blank Stack.