Components

Transition Components

Transition primitives, boundary components, presets, and specs.

Package Surface

react-native-screen-transitions exposes four main API surfaces:

  • navigator creators from subpaths
  • adapter helpers for existing navigators
  • the default Transition export from the main package
  • named hooks, helpers, constants, and types from the main package

TSX

1import Transition, {
2 withScreenTransitions,
3 snapTo,
4 type ScreenStyleInterpolator,
5 type ScreenTransitionConfig,
6} from "react-native-screen-transitions";
7
8import { createBlankStackNavigator } from "react-native-screen-transitions/react-navigation";

Use the blank-stack subpath export to build the recommended navigator. Use withScreenTransitions() to adapt existing native-stack navigators. Use Transition for transition-aware primitives, boundary components, presets, and specs.

For hooks and factories such as useScreenAnimation(), useScreenGesture(), createTransitionAwareComponent(), and createBoundaryComponent(), see API.

createBlankStackNavigator()

TSX

1const Stack = createBlankStackNavigator();
2
3<Stack.Navigator>
4 <Stack.Screen name="Home" component={HomeScreen} />
5 <Stack.Screen
6 name="Detail"
7 component={DetailScreen}
8 options={{
9 ...Transition.Presets.SlideFromBottom(),
10 }}
11 />
12</Stack.Navigator>

All transition configuration still lives on screen options.

Related reading: Stack Types and Adapters.

Transition-Aware Primitives

The default Transition export wraps common React Native primitives so they can receive slot-driven styles and participate in bounds measurement.

Transition.View

Use this for non-pressable elements that need transition-aware styling.

TSX

1<Transition.View styleId="hero-title">
2 <Text>Title</Text>
3</Transition.View>

Transition.Pressable

Use this when the element is interactive.

TSX

1<Transition.Pressable styleId="cta" onPress={open}>
2 <Text>Open</Text>
3</Transition.Pressable>

Transition.ScrollView

This participates in the scroll registry, hands off gestures, and publishes scroll metadata to current.layouts.scroll.

TSX

1<Transition.ScrollView showsVerticalScrollIndicator={false}>
2 <Content />
3</Transition.ScrollView>

Transition.FlatList

This gives list content the same gesture-aware scroll behavior.

TSX

1<Transition.FlatList
2 data={items}
3 renderItem={renderItem}
4 keyExtractor={(item) => item.id}
5/>

Use transition-aware scrollables inside sheets and other gesture-driven screens whenever possible. Custom scrollables can opt into the same behavior with Transition.createTransitionAwareComponent(Component, { isScrollable: true }).

Common Primitive Props

  • styleId for element targeting from screenStyleInterpolator

Boundary Components

Transition.Boundary is the compound API for bounds-driven transitions.

  • Transition.Boundary
  • Transition.Boundary.Target
  • Transition.Boundary.Host

Transition.Boundary

Use this for both pressable and passive boundary registration.

When onPress is present, it renders as a pressable boundary. When onPress is omitted, it renders as a passive view boundary.

TSX

1// Passive boundary
2<Transition.Boundary id="hero">
3 <Image source={heroImage} style={styles.hero} />
4</Transition.Boundary>
5
6// Pressable boundary
7<Transition.Boundary
8 id="hero"
9 onPress={() => navigation.navigate("Detail")}
10>
11 <Image source={heroImage} style={styles.hero} />
12</Transition.Boundary>

This is the default recommendation for new code.

Transition.Boundary.Target

Use this when the measured element is nested inside the owner.

TSX

1<Transition.Boundary id={item.id} onPress={openItem} style={styles.row}>
2 <Transition.Boundary.Target style={styles.artTarget}>
3 <Image source={item.image} style={styles.artwork} />
4 </Transition.Boundary.Target>
5
6 <View style={styles.copy}>
7 <Text>{item.title}</Text>
8 </View>
9</Transition.Boundary>

It does not take its own id. It inherits the surrounding boundary owner and changes which descendant gets measured.

Transition.Boundary.Host

Use this to make handoff or clipping-escape placement explicit inside a scrollable or otherwise constrained coordinate space.

TSX

1<Transition.ScrollView>
2 <Transition.Boundary.Host />
3
4 <Transition.Boundary id="card" escapeClipping onPress={openCard}>
5 <Image source={image} style={styles.card} />
6 </Transition.Boundary>
7</Transition.ScrollView>

Most flows do not need an explicit host. Add one when escapeClipping or handoff content should be placed inside a specific local coordinate space.

Deprecated Aliases

Transition.Boundary.View and Transition.Boundary.Trigger are still exported for compatibility.

TSX

1// Deprecated. Use Transition.Boundary without onPress.
2<Transition.Boundary.View id="hero" />
3
4// Deprecated. Use Transition.Boundary with onPress.
5<Transition.Boundary.Trigger id="hero" onPress={openDetail} />

Boundary Config Props

Transition.Boundary, deprecated boundary aliases, and components created with createBoundaryComponent() share the same boundary config:

  • id
  • group
  • anchor
  • scaleMode
  • target
  • method
  • enabled
  • handoff
  • escapeClipping

They keep the wrapped component props as well. The root Transition.Boundary accepts onPress for pressable usage.

Presets and Specs

The default export also includes Transition.Presets and Transition.Specs.

Preset builders:

  • SlideFromTop()
  • SlideFromBottom()
  • ZoomIn()
  • DraggableCard()
  • ElasticCard()
  • SharedIGImage()
  • SharedAppleMusic()
  • SharedXImage()

Specs:

  • Transition.Specs.DefaultSpec
  • Transition.Specs.DefaultSnapSpec
  • Transition.Specs.FlingSpec
  • Transition.Specs.Zoom (paired open and close springs for navigation.zoom())

TSX

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

Transition Start Blocking

blockTransition() and unblockTransition() are named exports that hold a screen's pending lifecycle transition at its initial frame while the destination prepares work.

TSX

1import {
2 blockTransition,
3 unblockTransition,
4} from "react-native-screen-transitions";
5
6async function prepareForTransition(routeKey: string) {
7 blockTransition(routeKey);
8
9 try {
10 await prepareDestination();
11 } finally {
12 unblockTransition(routeKey);
13 }
14}

Blocking is reference-counted per route. Pair every call with one unblock for the same route. Passing a route key is the clearest option; when it is omitted, the most recently focused screen in navigation history is used.

These functions affect when the animation starts. They do not reduce JavaScript work, move rendering to another thread, or improve actual runtime performance. Use them when delaying the visual transition produces a cleaner result than animating while the destination is still preparing.

Hooks, Factories, and Helpers

See API for useScreenAnimation(), useScreenGesture(), useHistory(), createTransitionAwareComponent(), createBoundaryComponent(), snapTo(), and reserved mask ids.

Legacy Compatibility

Transition.MaskedView is still exported for legacy masked-view flows.

Prefer:

  • screen options on one of the stack creators
  • Transition.Boundary
  • navigationMaskEnabled
  • styleId targets and layer slots

Related reading: Stack Types, Custom Animations, Layers, and Bounds Transitions.