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
| Option | Type | Description |
|---|---|---|
headerShown | boolean | Show/hide the header |
title | string | Header title |
presentation | string | "card", "modal", "transparentModal", "fullScreenModal", "formSheet" |
animation | string | "slide_from_right", "slide_from_left", "slide_from_bottom", "fade", "none" |
gestureEnabled | boolean | Enable swipe-to-go-back gesture |
gestureDirection | string | "horizontal" or "vertical" |
headerBackTitleVisible | boolean | Show 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
| Option | Type | Description |
|---|---|---|
tabBarActiveTintColor | string | Active tab color |
tabBarInactiveTintColor | string | Inactive tab color |
tabBarStyle | object | Tab bar container style |
tabBarLabelStyle | object | Tab label text style |
tabBarShowLabel | boolean | Show/hide tab labels |
tabBarHideOnKeyboard | boolean | Hide tabs when keyboard is visible |
lazy | boolean | Lazy load tab screens |
Per-Screen Tab Options
| Option | Type | Description |
|---|---|---|
tabBarLabel | string | Tab label text |
tabBarIcon | function | Tab icon component |
tabBarBadge | string | number | Badge on tab |
tabBarButton | function | Custom 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
| Option | Type | Description |
|---|---|---|
drawerActiveTintColor | string | Active item color |
drawerInactiveTintColor | string | Inactive item color |
drawerStyle | object | Drawer container style |
drawerPosition | string | "left" or "right" |
drawerType | string | "front", "back", "slide", "permanent" |
swipeEnabled | boolean | Enable 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 profileInitial 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-reanimatedThe library will throw a helpful error if you try to use a navigator without its dependencies installed.
Next Steps
- Deep Linking - Configure URL handling
- API Reference - Full API documentation