Skip to main content
Creates a blank stack navigator with complete control over screen transitions. This is the recommended stack type for most applications.

Function Signature

function createBlankStackNavigator<
  ParamList extends ParamListBase = ParamListBase,
  NavigatorID extends string | undefined = undefined
>(config?: StaticConfig): TypedNavigator<TypeBag, Config>

Type Parameters

ParamList
ParamListBase
default:"ParamListBase"
The parameter list for the navigator, defining route names and their parameters
NavigatorID
string | undefined
default:"undefined"
Optional unique identifier for the navigator instance

Parameters

config
StaticConfig
Optional static configuration for the navigator (rarely needed)

Return Value

TypedNavigator
TypedNavigator<TypeBag, Config>
Returns a typed navigator object containing:
  • Navigator: The navigator component
  • Screen: The screen component for defining routes
  • Group: Component for grouping screens with shared options

Import

import { createBlankStackNavigator } from "react-native-screen-transitions/blank-stack";

Usage

Basic Setup

import { createBlankStackNavigator } from "react-native-screen-transitions/blank-stack";
import Transition from "react-native-screen-transitions";

const Stack = createBlankStackNavigator();

function App() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Home" component={HomeScreen} />
      <Stack.Screen
        name="Detail"
        component={DetailScreen}
        options={{
          ...Transition.Presets.SlideFromBottom(),
        }}
      />
    </Stack.Navigator>
  );
}

With TypeScript

import { createBlankStackNavigator } from "react-native-screen-transitions/blank-stack";
import type { BlankStackNavigationProp } from "react-native-screen-transitions/blank-stack";

type RootStackParamList = {
  Home: undefined;
  Detail: { id: string };
  Profile: { userId: string };
};

const Stack = createBlankStackNavigator<RootStackParamList>();

// Type-safe navigation prop
type HomeScreenProps = {
  navigation: BlankStackNavigationProp<RootStackParamList, 'Home'>;
};

function HomeScreen({ navigation }: HomeScreenProps) {
  return (
    <Button
      title="Go to Detail"
      onPress={() => navigation.navigate('Detail', { id: '123' })}
    />
  );
}

With Expo Router

import { withLayoutContext } from "expo-router";
import {
  createBlankStackNavigator,
  type BlankStackNavigationOptions,
} from "react-native-screen-transitions/blank-stack";

const { Navigator } = createBlankStackNavigator();

export const Stack = withLayoutContext<
  BlankStackNavigationOptions,
  typeof Navigator
>(Navigator);

Features

Full Animation Control

The Blank Stack provides complete control over screen transitions:
<Stack.Screen
  name="Detail"
  component={DetailScreen}
  options={{
    screenStyleInterpolator: ({ progress, layouts: { screen } }) => {
      "worklet";
      return {
        contentStyle: {
          opacity: interpolate(progress, [0, 1, 2], [0, 1, 0]),
          transform: [{
            translateY: interpolate(
              progress,
              [0, 1],
              [screen.height, 0]
            ),
          }],
        },
      };
    },
  }}
/>

Shared Elements

Supports the full Bounds API for shared element transitions:
<Stack.Screen
  name="Detail"
  options={{
    ...Transition.Presets.SharedAppleMusic({
      sharedBoundTag: "album-art"
    }),
  }}
/>

Snap Points

Create multi-stop sheets with any gesture direction:
<Stack.Screen
  name="Sheet"
  options={{
    gestureEnabled: true,
    gestureDirection: "vertical",
    snapPoints: [0.5, 1],
    initialSnapIndex: 0,
    backdropBehavior: "dismiss",
    ...Transition.Presets.SlideFromBottom(),
  }}
/>

Gestures

Full gesture support with customizable activation:
<Stack.Screen
  name="Modal"
  options={{
    gestureEnabled: true,
    gestureDirection: "vertical",
    gestureActivationArea: "screen",
    gestureResponseDistance: 50,
    ...Transition.Presets.DraggableCard(),
  }}
/>

Overlays

Persistent UI that animates with the stack:
const TabBar = ({ progress }) => {
  const style = useAnimatedStyle(() => ({
    transform: [{ translateY: interpolate(progress.value, [0, 1], [100, 0]) }],
  }));
  return <Animated.View style={[styles.tabBar, style]} />;
};

<Stack.Screen
  name="Home"
  options={{
    overlay: TabBar,
    overlayShown: true,
  }}
/>

When to Use

Blank Stack is the recommended choice for most applications. It provides full animation control while maintaining excellent performance.
Use Blank Stack WhenConsider Alternatives
Custom transitions neededPlatform defaults are sufficient
Shared element transitionsN/A (Blank Stack is best choice)
Gesture-driven animationsN/A (Blank Stack is best choice)
Multi-stop sheets/drawersN/A (Blank Stack is best choice)
Full control requiredMaximum raw performance critical

Architecture

  • Screen Container: Uses react-native-screens for native screen primitives
  • Animation Engine: Powered by Reanimated worklets running on the UI thread
  • Gesture Handling: Uses react-native-gesture-handler for native gestures
  • Performance: Animations run at 60fps+ on the UI thread, not the JS thread

Exported Types

import type {
  BlankStackNavigationOptions,
  BlankStackNavigationProp,
  BlankStackScreenProps,
  BlankStackNavigatorProps,
  BlankStackNavigationEventMap,
  BlankStackOverlayProps,
  BlankStackOptionsArgs,
} from "react-native-screen-transitions/blank-stack";