Get Started

Quick Start

Create a blank stack, add a custom interpolator, and wire up a bounds-driven detail transition.

  1. 1

    Create A Blank Stack

    Blank stack is the default starting point for new v3 work:

    App.tsx

    1import Transition from "react-native-screen-transitions";
    2import { createBlankStackNavigator } from "react-native-screen-transitions/react-navigation";
    3
    4const Stack = createBlankStackNavigator();
    5
    6export function RootNavigator() {
    7return (
    8 <Stack.Navigator>
    9 <Stack.Screen name="Home" component={HomeScreen} />
    10 <Stack.Screen
    11 name="Detail"
    12 component={DetailScreen}
    13 options={{
    14 ...Transition.Presets.SlideFromBottom(),
    15 }}
    16 />
    17 </Stack.Navigator>
    18);
    19}

    That gives you a working stack immediately, with the detail screen using a built-in preset.

  2. 2

    Replace The Preset With Your Own Interpolator

    When you want full control, move the animation into `screenStyleInterpolator`:

    detail-screen.tsx

    1import { interpolate } from "react-native-reanimated";
    2
    3<Stack.Screen
    4name="Detail"
    5component={DetailScreen}
    6options={{
    7 gestureEnabled: true,
    8 gestureDirection: "vertical",
    9 transitionSpec: {
    10 open: Transition.Specs.DefaultSpec,
    11 close: Transition.Specs.DefaultSpec,
    12 },
    13 screenStyleInterpolator: ({
    14 progress,
    15 layouts: {
    16 screen: { height },
    17 },
    18 }) => {
    19 "worklet";
    20 return {
    21 content: {
    22 style: {
    23 opacity: interpolate(progress, [0, 1, 2], [0, 1, 0]),
    24 transform: [
    25 {
    26 translateY: interpolate(progress, [0, 1, 2], [height, 0, -height * 0.2]),
    27 },
    28 ],
    29 },
    30 },
    31 backdrop: {
    32 style: {
    33 opacity: interpolate(progress, [0, 1, 2], [0, 0.45, 0]),
    34 },
    35 },
    36 };
    37 },
    38}}
    39/>

    The interpolator returns layer output. The most common slots are:

    • content
    • backdrop
    • surface
    • any styleId you attach to Transition.View or Transition.Pressable
  3. 3

    Add A Bounds-Driven Detail Transition

    Use the boundary API to connect a source element to its destination:

    bounds-link.tsx

    1// Home screen
    2<Transition.Boundary
    3id="hero"
    4onPress={() => navigation.navigate("Detail")}
    5>
    6<Image source={heroImage} style={{ width: 120, height: 160 }} />
    7</Transition.Boundary>
    8
    9// Detail screen
    10<Transition.Boundary id="hero">
    11<Image source={heroImage} style={{ width: "100%", height: 360 }} />
    12</Transition.Boundary>

    Then let the detail screen read that bounds link:

    detail-options.tsx

    1<Stack.Screen
    2name="Detail"
    3component={DetailScreen}
    4options={{
    5 navigationMaskEnabled: true,
    6 transitionSpec: Transition.Specs.Zoom,
    7 screenStyleInterpolator: ({ bounds }) => {
    8 "worklet";
    9 return bounds("hero").navigation.zoom();
    10 },
    11}}
    12/>

    navigationMaskEnabled is what lets the library manage the reveal mask for navigation zoom. It requires @react-native-masked-view/masked-view, which is covered in Installation.

  4. 4

    Keep Going

    From here, the next pages depend on what you want to build.