Declarative Stack.Toolbar items plus the ToolbarHost, BarButtonItem, and MenuAction primitives on iOS
Declarative native toolbar items through Stack.Toolbar, in the same compound
style as Stack.Header. One toolbar declares one placement: left and
right compile to native header items while bottom, the default, renders a
native UIToolbar at the bottom of the screen. This is the UIKit toolbar,
distinct from the SwiftUI toolbar in
iOS Navigation and Toolbar.
For explicit item identifiers or native item props the declarative API does not
forward, drop to the lower-level primitives: One.iOS.ToolbarHost with
One.iOS.BarButtonItem children, each a UIBarButtonItem, and
One.iOS.MenuAction for UIMenu and UIAction elements.
import { Stack } from 'one'
function IndexToolbar({ edit, share }: { edit: () => void; share: () => void }) { return ( <Stack.Screen name="index"> <Stack.Toolbar placement="left"> <Stack.Toolbar.Button icon="pencil" onPress={edit}> Edit </Stack.Toolbar.Button> </Stack.Toolbar> <Stack.Toolbar placement="right"> <Stack.Toolbar.Menu title="More" icon="ellipsis.circle"> <Stack.Toolbar.MenuAction icon="square.and.arrow.up" onPress={share}> Share </Stack.Toolbar.MenuAction> </Stack.Toolbar.Menu> </Stack.Toolbar> </Stack.Screen> )}Each toolbar maps to header items on its side. Buttons take their label as text
children, an icon SF Symbol name, and onPress; menus nest MenuAction
children and Menu submenus.
Stack.Toolbar children are descriptors, never rendered views: the converters
read them into native items. left maps to unstable_headerLeftItems and
right to unstable_headerRightItems, the iOS header-item path in
react-navigation, and forces the header visible. bottom renders through a
toolbar host inside the screen’s view controller, with each button or menu
becoming a UIBarButtonItem and menu actions becoming UIMenu and UIAction
elements.
Options are route-local and dynamic. A toolbar rendered in route content
applies through the screen’s navigation options, so screen state can drive
items with no new API; asChild renders children as a custom header element
instead of header items. An explicit toolbar always wins over incoming options
on its own side: hidden items convert to nothing, so a toolbar whose items are
all hidden writes an empty array and clears inherited items, while an absent
toolbar preserves them.
left and right toolbars live in layout config or route content and set
header items through navigation options. Children are Button, Menu, and
Spacer descriptors; anything else warns in dev and is skipped. Spacer
needs a fixed width here; the flexible form is bottom only.
import { Stack } from 'one'
function EditToolbar({ edit }: { edit: () => void }) { return ( <Stack.Toolbar placement="left"> <Stack.Toolbar.Button icon="pencil" onPress={edit}> Edit </Stack.Toolbar.Button> <Stack.Toolbar.Spacer width={12} /> </Stack.Toolbar> )}Buttons take text children or a Label child, icon as an SF Symbol name or
image source, tintColor including dynamic iOS values, variant, disabled,
hidden, selected, and onPress. separateBackground opts out of the
shared background and hidesSharedBackground hides it behind the item for iOS
26 Liquid Glass. Badge is left and right only; bottom throws in dev.
bottom renders the navigation-controller toolbar in place and must mount in
screen content, where the responder chain reaches the screen view controller.
In layout config it warns and is ignored. Bottom items take the same props;
the bottom bar takes SF Symbol strings for icons. Hide the bar by unmounting
the toolbar or by setting hidden on its items.
import { Stack } from 'one'
function ComposerToolbar({ add, hidden }: { add: () => void; hidden: boolean }) { return ( <Stack.Toolbar> <Stack.Toolbar.Button icon="plus" hidden={hidden} onPress={add}> Add </Stack.Toolbar.Button> <Stack.Toolbar.Spacer /> <Stack.Toolbar.SearchBarSlot /> </Stack.Toolbar> )}Spacer without a width is flexible here, and SearchBarSlot embeds the
screen search bar. The bottom toolbar renders nothing off iOS.
One.iOS.ToolbarHost is the lower-level bottom-UIToolbar renderer that a
bottom Stack.Toolbar builds on. Reach for it directly only when you need
explicit item identifiers or native item props the declarative API does not
forward.
import { One } from 'one'
function BottomBar({ edit }: { edit: () => void }) { return ( <One.iOS.ToolbarHost> <One.iOS.BarButtonItem identifier="edit" title="Edit" systemImageName="pencil" onSelected={edit} /> </One.iOS.ToolbarHost> )}| ToolbarHost | Type | Description |
|---|---|---|
childrenReact.ReactNodeBarButtonItem children. | React.ReactNode | BarButtonItem children. |
hiddenbooleanHides the navigation controller toolbar. | boolean | Hides the navigation controller toolbar. |
animatedbooleanAnimate show and hide. Defaults to true. | boolean | Animate show and hide. Defaults to true. |
| BarButtonItem | Type | Description |
|---|---|---|
childrenReact.ReactNodeLabel content. | React.ReactNode | Label content. |
identifier (required)stringUnique ID. | string | Unique ID. |
titlestringButton title. | string | Button title. |
systemImageNamestringSF Symbol name. | string | SF Symbol name. |
xcassetNamestringXcode asset catalog image name. | string | Xcode asset catalog image name. |
imageImageSourcePropTypeCustom image source. | ImageSourcePropType | Custom image source. |
imageRenderingMode'template' | 'original'How the image draws. | 'template' | 'original' | How the image draws. |
type'normal' | 'fixedSpacer' | 'fluidSpacer' | 'searchBar'Item kind. | 'normal' | 'fixedSpacer' | 'fluidSpacer' | 'searchBar' | Item kind. |
tintColorColorValueItem tint, including dynamic iOS values. | ColorValue | Item tint, including dynamic iOS values. |
hidesSharedBackgroundbooleanHides the shared background behind the item. | boolean | Hides the shared background behind the item. |
sharesBackgroundbooleanJoins the shared glass background. | boolean | Joins the shared glass background. |
barButtonItemStyle'plain' | 'done' | 'prominent'Button style. | 'plain' | 'done' | 'prominent' | Button style. |
widthnumberFixed width for spacers. | number | Fixed width for spacers. |
hiddenbooleanHides the item. | boolean | Hides the item. |
selectedbooleanSelected state. | boolean | Selected state. |
badgeConfiguration{ value?: string backgroundColor?: ColorValue } & BasicTextStyleBadge value, color, and text style. iOS 26 or later. | { value?: string backgroundColor?: ColorValue } & BasicTextStyle | Badge value, color, and text style. iOS 26 or later. |
titleStyleBasicTextStyleFont family, size, weight, and color of the title. | BasicTextStyle | Font family, size, weight, and color of the title. |
accessibilityLabelstringAccessibility label. | string | Accessibility label. |
accessibilityHintstringAccessibility hint. | string | Accessibility hint. |
disabledbooleanDisables the item. | boolean | Disables the item. |
onSelected() => voidTap handler. | () => void | Tap handler. |
One.iOS.MenuAction is a native iOS UIMenu and UIAction element for
context menus in toolbars. icon takes an SF Symbol name.
import { One } from 'one'
function RowActions() { return ( <> <One.iOS.MenuAction identifier="edit" title="Edit" icon="pencil" onSelected={() => console.log('edit')} /> <One.iOS.MenuAction identifier="delete" title="Delete" icon="trash" destructive onSelected={() => console.log('delete')} /> </> )}| MenuAction | Type | Description |
|---|---|---|
identifier (required)stringUnique ID. | string | Unique ID. |
title (required)stringAction title. | string | Action title. |
labelstringLabel override. | string | Label override. |
iconstringSF Symbol name. | string | SF Symbol name. |
xcassetNamestringXcode asset catalog image name. | string | Xcode asset catalog image name. |
imageImageSourcePropTypeCustom image source. | ImageSourcePropType | Custom image source. |
imageRenderingMode'template' | 'original'How the image draws. | 'template' | 'original' | How the image draws. |
childrenReact.ReactNodeNested menu content. | React.ReactNode | Nested menu content. |
disabledbooleanDisables the action. | boolean | Disables the action. |
destructivebooleanDestructive styling. | boolean | Destructive styling. |
discoverabilityLabelstringDiscoverability hint. | string | Discoverability hint. |
subtitlestringSubtitle under the title. | string | Subtitle under the title. |
accessibilityLabelstringAccessibility label. | string | Accessibility label. |
accessibilityHintstringAccessibility hint. | string | Accessibility hint. |
displayAsPalettebooleanShows children as a palette. | boolean | Shows children as a palette. |
displayInlinebooleanShows children inline. | boolean | Shows children inline. |
preferredElementSize'auto' | 'small' | 'medium' | 'large'Preferred size of menu elements. | 'auto' | 'small' | 'medium' | 'large' | Preferred size of menu elements. |
isOnbooleanOn state for toggle actions. | boolean | On state for toggle actions. |
keepPresentedbooleanKeeps the menu open after the tap. | boolean | Keeps the menu open after the tap. |
hiddenbooleanHides the action. | boolean | Hides the action. |
tintColorColorValueAction tint. | ColorValue | Action tint. |
barButtonItemStyle'plain' | 'done' | 'prominent'Button style. | 'plain' | 'done' | 'prominent' | Button style. |
sharesBackgroundbooleanJoins the shared glass background. | boolean | Joins the shared glass background. |
hidesSharedBackgroundbooleanHides the shared background behind the item. | boolean | Hides the shared background behind the item. |
onSelected() => voidTap handler. | () => void | Tap handler. |
singleSelectionbooleanSingle selection among siblings. | boolean | Single selection among siblings. |
titleStyleBasicTextStyleFont family, size, weight, and color of the title. | BasicTextStyle | Font family, size, weight, and color of the title. |
| iOS | Android | Web | |
|---|---|---|---|
| Header items | Native items | None | None |
| Bottom bar | UIToolbar | Renders null | Renders null |
| Primitives | Native views | Renders null | Renders null |
The native toolbar, menu action, and font helpers are adapted from Expo Router.
Edit this page on GitHub.