Teardown

Layouts

Configure Stack, Tab, and Drawer navigators.

Layouts define how screens are organized and navigated. Create a _layout.tsx file in any directory to configure its navigator.

Layout Types

Stack Navigator

The default navigator type. Screens stack on top of each other:

// src/_routes/_layout.tsx
import { defineLayout } from "@teardown/navigation";

export default defineLayout({
  type: "stack",
  screenOptions: {
    headerShown: true,
    animation: "slide_from_right",
  },
});

Stack Screen Options

OptionTypeDescription
headerShownbooleanShow/hide the header
titlestringHeader title
presentationstring"card", "modal", "transparentModal", "fullScreenModal", "formSheet"
animationstring"slide_from_right", "slide_from_left", "slide_from_bottom", "fade", "none"
gestureEnabledbooleanEnable swipe-to-go-back gesture
gestureDirectionstring"horizontal" or "vertical"
headerBackTitleVisiblebooleanShow back button title (iOS)

Tab Navigator

Display screens as tabs at the bottom of the screen:

// src/_routes/(tabs)/_layout.tsx
import { defineLayout } from "@teardown/navigation";
import { Home, Search, User } from "lucide-react-native";

export default defineLayout({
  type: "tabs",
  screenOptions: {
    headerShown: false,
    tabBarActiveTintColor: "#007AFF",
    tabBarInactiveTintColor: "#8E8E93",
  },
  screens: {
    home: {
      tabBarLabel: "Home",
      tabBarIcon: ({ color, size }) => <Home color={color} size={size} />,
    },
    search: {
      tabBarLabel: "Search",
      tabBarIcon: ({ color, size }) => <Search color={color} size={size} />,
    },
    profile: {
      tabBarLabel: "Profile",
      tabBarIcon: ({ color, size }) => <User color={color} size={size} />,
    },
  },
});

Tab Screen Options

OptionTypeDescription
tabBarActiveTintColorstringActive tab color
tabBarInactiveTintColorstringInactive tab color
tabBarStyleobjectTab bar container style
tabBarLabelStyleobjectTab label text style
tabBarShowLabelbooleanShow/hide tab labels
tabBarHideOnKeyboardbooleanHide tabs when keyboard is visible
lazybooleanLazy load tab screens

Per-Screen Tab Options

OptionTypeDescription
tabBarLabelstringTab label text
tabBarIconfunctionTab icon component
tabBarBadgestring | numberBadge on tab
tabBarButtonfunctionCustom tab button component

Drawer Navigator

Side menu navigation:

// src/_routes/_layout.tsx
import { defineLayout } from "@teardown/navigation";
import { Home, Settings, Info } from "lucide-react-native";

export default defineLayout({
  type: "drawer",
  screenOptions: {
    headerShown: true,
    drawerActiveTintColor: "#007AFF",
    drawerPosition: "left",
  },
  screens: {
    home: {
      drawerLabel: "Home",
      drawerIcon: ({ color, size }) => <Home color={color} size={size} />,
    },
    settings: {
      drawerLabel: "Settings",
      drawerIcon: ({ color, size }) => <Settings color={color} size={size} />,
    },
    about: {
      drawerLabel: "About",
      drawerIcon: ({ color, size }) => <Info color={color} size={size} />,
    },
  },
});

Drawer Screen Options

OptionTypeDescription
drawerActiveTintColorstringActive item color
drawerInactiveTintColorstringInactive item color
drawerStyleobjectDrawer container style
drawerPositionstring"left" or "right"
drawerTypestring"front", "back", "slide", "permanent"
swipeEnabledbooleanEnable swipe to open

Nested Navigators

Combine different navigator types for complex navigation structures.

Tabs Inside Stack

src/_routes/
├── _layout.tsx           # Stack (root)
├── index.tsx             # Landing screen
├── (main)/
│   ├── _layout.tsx       # Tabs
│   ├── home.tsx          # Tab 1
│   ├── search.tsx        # Tab 2
│   └── profile.tsx       # Tab 3
└── settings.tsx          # Modal (stacks over tabs)
// src/_routes/_layout.tsx (Stack)
export default defineLayout({
  type: "stack",
  screenOptions: { headerShown: false },
});

// src/_routes/(main)/_layout.tsx (Tabs)
export default defineLayout({
  type: "tabs",
  screenOptions: { tabBarActiveTintColor: "#007AFF" },
});

Stack Inside Tabs

Each tab can have its own stack:

src/_routes/
├── _layout.tsx           # Tabs (root)
├── (home)/
│   ├── _layout.tsx       # Stack for home tab
│   ├── index.tsx         # Home
│   └── details.tsx       # Details (pushes in home tab)
└── (profile)/
    ├── _layout.tsx       # Stack for profile tab
    ├── index.tsx         # Profile
    └── edit.tsx          # Edit profile

Initial Route

Set the initial route for a navigator:

export default defineLayout({
  type: "tabs",
  initialRouteName: "home", // Start on home tab
  screenOptions: { ... },
});

Custom Tab Bar

Provide a custom tab bar component:

import { defineLayout } from "@teardown/navigation";
import { CustomTabBar } from "../components/CustomTabBar";

export default defineLayout({
  type: "tabs",
  tabBar: CustomTabBar,
  screenOptions: { headerShown: false },
});

Custom Drawer Content

Provide custom drawer content:

import { defineLayout } from "@teardown/navigation";
import { CustomDrawer } from "../components/CustomDrawer";

export default defineLayout({
  type: "drawer",
  drawerContent: CustomDrawer,
  screenOptions: { headerShown: true },
});

Required Dependencies

Make sure to install the required packages for each navigator type:

# Stack (included by default)
bun add @react-navigation/native-stack

# Tabs
bun add @react-navigation/bottom-tabs

# Drawer
bun add @react-navigation/drawer react-native-gesture-handler react-native-reanimated

The library will throw a helpful error if you try to use a navigator without its dependencies installed.

Next Steps