Stacks, Tabs, Drawers

Stacks, Tabs and Drawers in Expo Router

A layout file picks the navigator for its folder. Stack from expo-router 6,418 pushes screens with a header and Back, using react-native-screens 3,732 (a Fragment on Android, a UINavigationController on iOS). Tabs draws a bottom tab bar in JavaScript, and each tab keeps its state. Drawer from expo-router/drawer adds a side menu. BookNest's catalog and cart are tabs, and a badge on the cart tab counts the books in it:

src/app/(tabs)/_layout.tsx: the Catalog and Cart tabs (excerpt)Shell
export default function TabLayout() {
  const { cart } = useSession();
  return (
    <Tabs screenOptions={{ tabBarActiveTintColor: '#1565c0', freezeOnBlur: true }}>
      <Tabs.Screen name="index" options={{ title: 'Catalog',
        tabBarIcon: ({ color, size }) =>
          <Ionicons name="library-outline" color={color} size={size} /> }} />
      <Tabs.Screen name="cart" options={{ title: 'Cart',
        tabBarBadge: cart.length || undefined,         // no badge on an empty cart
        tabBarIcon: ({ color, size }) =>
          <Ionicons name="cart-outline" color={color} size={size} /> }} />
    </Tabs>
  );
}

name is the file name without its extension, and the order of the Tabs.Screen elements is the order of the tabs. Icons come from @expo/vector-icons (15.1.1 here), which bundles Ionicons, Material Icons and other icon fonts. freezeOnBlur is explained in Navigation Performance.

BookNest on Expo Router: the Catalog tab, and book 3 pushed onto the root stack
BookNest on Expo Router: the Catalog tab, and book 3 pushed onto the root stack

A drawer takes the same shape: its layout returns <Drawer> with a <Drawer.Screen name="(tabs)" /> per entry. Since SDK 56 the drawer navigator is bundled inside expo-router (it uses react-native-drawer-layout 4.2.10), so it needs only Reanimated 11,010 , react-native-worklets and Gesture Handler 6,788 , which BookNest has had since Reanimated and Gesture Handler. expo-router/unstable-native-tabs offers tabs drawn by the platform's own tab bar; as its name says, the API is not stable yet, so BookNest stays on Tabs.