# 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)}
/>
Filter by
Unread
{}}
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.