# Toolbars and headers Add native iOS toolbar items to Stack screens. Items can be placed in the header (left/right) or in a bottom toolbar area. **Important:** iOS only. Available in Expo SDK 55+. ## Notes app example ```tsx import { Stack } from "expo-router"; import { ScrollView } from "react-native"; export default function FoldersScreen() { return ( <> {/* ScrollView must be the first child of the screen */} {/* Screen content */} Folders {}} /> {/* Header toolbar - right side */} {}} /> {}}>Edit {/* Bottom toolbar */} {}} separateBackground /> ); } ``` ## Mail inbox example ```tsx import { Color, Stack } from "expo-router"; import { useState } from "react"; import { ScrollView, Text, View } from "react-native"; export default function InboxScreen() { const [isFilterOpen, setIsFilterOpen] = useState(false); return ( <> {/* Screen content */} Inbox {}} /> {/* Header toolbar - right side */} {}}>Select Categories List About categories Show Contact Photos {/* Bottom toolbar */} setIsFilterOpen((prev) => !prev)} /> {}} separateBackground /> ); } ``` ## Placement - `"left"` - Header left - `"right"` - Header right - `"bottom"` (default) - Bottom toolbar ## Components ### Button - Icon button: ` {}} />` - Text button: ` {}}>Done` **Props:** `icon`, `image`, `onPress`, `disabled`, `hidden`, `variant` (`"plain"` | `"done"` | `"prominent"`), `tintColor` ### Menu Dropdown menu for grouping actions. ```tsx Sort by Recently Added Sort by Date Captured All Items Favorites Photos Videos ``` **Menu Props:** All Button props plus `title`, `inline`, `palette`, `elementSize` (`"small"` | `"medium"` | `"large"`) **MenuAction Props:** `icon`, `onPress`, `isOn`, `destructive`, `disabled`, `subtitle` When creating a palette with dividers, use `inline` combined with `elementSize="small"`. `palette` will not apply dividers on iOS 26. ### Spacer ```tsx // Bottom toolbar - flexible // Header - requires explicit width ``` ### View Embed custom React Native components. When adding a custom view make sure that there is only a single child with **explicit width and height**. ```tsx Filter by ``` You can pass custom components to views as well: ```tsx function CustomFilterView() { return ( Filter by ); } ... ``` ## Recommendations - When creating more complex headers, extract them to a single component ```tsx export default function Page() { return ( <> {/* Screen content */} ); } function InboxHeader() { return ( <> Inbox {}} /> {/* Toolbar buttons */} ); } ``` - When using `Stack.Toolbar`, make sure that all `Stack.Toolbar.*` components are wrapped inside `Stack.Toolbar` component. This will **not work**: ```tsx function Buttons() { return ( <> {}} /> {}}>Done ); } function Page() { return ( <> {/* Screen content */} {/* ❌ This will NOT work */} ); } ``` This will work: ```tsx function ToolbarWithButtons() { return ( {}} /> {}}>Done ); } function Page() { return ( <> {/* Screen content */} {/* ✅ This will work */} ); } ``` ## Limitations - iOS only - `placement="bottom"` can only be used inside screen components (not in layout files) - `Stack.Toolbar.Badge` only works with `placement="left"` or `"right"` - Header Spacers require explicit `width` ## Reference Docs https://docs.expo.dev/versions/unversioned/sdk/router - read to see the full API.