<Stack />

This component should only be rendered inside a _layout.tsx file, where it will serve as the location that children will render for routes below the layout.

Stack is simply a React Navigation Native Stack view and accepts the same props as React Navigation.

import { Stack } from 'one'
import { Button } from 'react-native'
export default function Layout() {
return (
<Stack
screenOptions={{
headerRight() {
return (
<Button label="Settings" />
)
},
}}
/>
)
}

Stack.Screen

You can customize the children of the Stack in your layout by passing a children prop to Stack has Stack.Screen elements, like so:

import { Stack } from 'one'
export default function Layout() {
return (
<Stack>
<Stack.Screen name="index" options={{ title: 'Feed' }} />
<Stack.Screen name="[id]" options={{ title: 'Post' }} />
<Stack.Screen
name="sheet"
options={{
presentation: 'formSheet',
gestureDirection: 'vertical',
animation: 'slide_from_bottom',
headerShown: false,
}}
/>
</Stack>
)
}

The name must match the full name of the file inside app, without the extension but including groups.

In this example we are setting index, [id], and sheet screens, which would correspond to index.tsx and [id].tsx and sheet.tsx pages in the same directory.

This is a convenient way to configure settings for each page up front, but you could also render Stack.Screen inside each individual page so you can access data loaded inside that page. The upside of doing it in the layout is that it will configure things before any stack animation runs on enter, with the downside being that you can’t access page-level data.

The options property passes to the React Navigation NativeStack, and so takes the same options.

Stack.Toolbar

new

Stack.Toolbar adds native iOS toolbar items to either side of the navigation header or to the bottom of a page. It uses UIBarButtonItem and UIToolbar, including SF Symbols, native menus, badges, and Liquid Glass appearance on iOS 26.

The API is always available from one, but rendering a native toolbar requires @vxrn/native. Install it in your app so React Native autolinking includes its native view managers:

Terminal window
npm install @vxrn/native

Then import it from your native setup file:

setup.native.ts
import '@vxrn/native'

Configure that file with One’s setupFile option if your app does not already have a native setup file. Installing @vxrn/native directly in the app is required. The package owns the native toolbar implementation and declares its React Navigation and React Native dependencies. Importing it during native setup registers that implementation before the app renders. Without the setup import, Stack.Toolbar remains a no-op on native.

import { Stack } from 'one'
export default function Inbox() {
return (
<>
<Stack.Toolbar placement="right">
<Stack.Toolbar.Button icon="square.and.arrow.up" onPress={share}>
Share
</Stack.Toolbar.Button>
<Stack.Toolbar.Menu icon="ellipsis.circle" title="Actions">
<Stack.Toolbar.MenuAction icon="archivebox" onPress={archive}>
Archive
</Stack.Toolbar.MenuAction>
<Stack.Toolbar.MenuAction icon="trash" destructive onPress={remove}>
Delete
</Stack.Toolbar.MenuAction>
</Stack.Toolbar.Menu>
</Stack.Toolbar>
<Stack.Toolbar>
<Stack.Toolbar.Button icon="photo.on.rectangle" onPress={selectPhotos}>
Select
</Stack.Toolbar.Button>
<Stack.Toolbar.Spacer />
<Stack.Toolbar.Button icon="plus" onPress={addPhoto}>
Add
</Stack.Toolbar.Button>
</Stack.Toolbar>
<InboxContent />
</>
)
}

The default placement is bottom. Render Stack.Toolbar in a page component so it can configure that page’s native screen. Set placement="left" or placement="right" for header items:

<Stack.Toolbar placement="left">
<Stack.Toolbar.Button icon="sidebar.left" onPress={openSidebar} />
</Stack.Toolbar>

Toolbar components:

  • Stack.Toolbar.Button renders a native action. Use an SF Symbol name in icon, or compose Icon, Label, and Badge children.
  • Stack.Toolbar.Menu renders a native menu and supports nested or inline submenus.
  • Stack.Toolbar.MenuAction supports selected, disabled, destructive, hidden, and keep-presented states.
  • Stack.Toolbar.Spacer renders flexible bottom spacing when width is omitted, or fixed spacing when it is set.
  • Stack.Toolbar.View embeds a custom React Native view.
  • Stack.Toolbar.SearchBarSlot places a configured native search bar in the bottom toolbar on iOS 26 or newer.

This API is alpha and currently renders on iOS when @vxrn/native is installed and imported by the native setup file. It renders no toolbar on web, Android, or native apps without that setup import. Headless stack implementations still receive every placement through useStack().focused.options.toolbar, so a web layout can render the same configuration itself. Use separateBackground, hidesSharedBackground, and badges to control the native iOS 26 grouping and appearance without recreating the toolbar in JavaScript.

Header Composition API

new

For more declarative header configuration, use the compositional API with Stack.Header and its child components:

import { Stack } from 'one'
export default function Layout() {
return (
<Stack>
<Stack.Screen name="index">
<Stack.Header blurEffect="regular">
<Stack.Header.Title large>Articles</Stack.Header.Title>
<Stack.Header.SearchBar placeholder="Search..." />
</Stack.Header>
</Stack.Screen>
<Stack.Screen name="[id]">
<Stack.Header>
<Stack.Header.Title>Post</Stack.Header.Title>
<Stack.Header.Right asChild>
<ShareButton />
</Stack.Header.Right>
</Stack.Header>
</Stack.Screen>
</Stack>
)
}

Stack.Header

The container for header configuration. Props:

  • hidden - Hide the header entirely
  • blurEffect - iOS blur effect ('regular', 'prominent', 'systemMaterial', etc.)
  • asChild - Render a completely custom header component
  • style - Style with backgroundColor, shadowColor (set to 'transparent' to hide)
  • largeStyle - Style for large title mode

Stack.Header.Title

Configure the header title:

<Stack.Header.Title large>My Title</Stack.Header.Title>

Props:

  • children - The title text
  • large - Enable iOS large title mode
  • style - Text style (fontWeight, fontSize, color, textAlign)

Stack.Header.BackButton

Configure the back button:

<Stack.Header.BackButton hidden />
<Stack.Header.BackButton displayMode="minimal">Back</Stack.Header.BackButton>

Props:

  • children - Custom back button text
  • hidden - Hide the back button
  • displayMode - 'default', 'generic', or 'minimal'
  • withMenu - Enable long-press menu on iOS

Stack.Header.Left / Stack.Header.Right

Add custom components to the header:

<Stack.Header.Left asChild>
<MenuButton />
</Stack.Header.Left>
<Stack.Header.Right asChild>
<SettingsButton />
</Stack.Header.Right>

Props:

  • asChild - Required to render custom children
  • children - Your custom component

Stack.Header.SearchBar

Add an iOS-style search bar:

<Stack.Header.SearchBar
placeholder="Search articles..."
autoCapitalize="none"
placement="stacked"
/>

Props:

  • placeholder - Placeholder text
  • autoCapitalize - 'none', 'words', 'sentences', 'characters'
  • placement - 'automatic' or 'stacked'
  • hideWhenScrolling - Hide when scrolling
  • obscureBackground - Obscure background when active

Default Header for All Screens

You can set a default header for all screens by placing Stack.Header directly inside Stack:

<Stack>
<Stack.Header blurEffect="regular">
<Stack.Header.BackButton displayMode="minimal" />
</Stack.Header>
<Stack.Screen name="index" options={{ title: 'Home' }} />
<Stack.Screen name="profile" options={{ title: 'Profile' }} />
</Stack>

On web

new

On web, <Stack> renders headless: only the focused screen’s element, no header, no chrome. Screens with a presentation (sheet, modal, formSheet, etc.) render as overlays above the base screen - by default inline with no floating chrome, or with real chrome once you mount Presentations.

Set keepMounted: true on a screen’s options to keep it mounted (hidden via React 19.2’s <Activity>) instead of unmounting it when it loses focus:

<Stack.Screen name="settings" options={{ keepMounted: true }} />

To build your own web layout entirely (a custom header, transitions, anything), place a component as a child of <Stack> - it replaces the headless default on web and is ignored on native. Use useStack to get the full stack state.

See the headless web navigators guide for the full story, including how Presentations maps sheets and modals to real chrome.

Edit this page on GitHub.