feat(iOS, Stack): add support for toolbar items#4013
Conversation
Exposes UINavigationController's bottom toolbar to stack screens via a new `toolbarItems` prop on `ScreenStackHeaderConfig`. Toolbar items use the existing `RNSBarButtonItem` infrastructure and support buttons, menus, flexible space, and fixed spacing, matching the header bar button API. The react-navigation `native-stack` adapter in the submodule bridges this as `unstable_toolbarItems` on `NativeStackNavigationOptions`, with a `processToolbarItems` helper that mirrors `processBarButtonItems`. Key changes: - `src/types.tsx`: add `ToolbarItemFlexibleSpace` and `ToolbarItem` types; add `toolbarItems` prop to `ScreenStackHeaderConfigProps` - `src/fabric/ScreenStackHeaderConfigNativeComponent.ts`: add `toolbarItems`, `onPressToolbarItem`, `onPressToolbarMenuItem` props - `src/components/helpers/prepareHeaderBarButtonItems.ts`: extend to accept `'toolbar'` side and pass through `flexibleSpace` items - `src/components/ScreenStackHeaderConfig.tsx`: prepare and forward toolbar items; wire press handlers - `ios/RNSScreenStackHeaderConfig.h`: declare `toolbarItems` property - `ios/RNSScreenStackHeaderConfig.mm`: add `toolbarItemsFromConfigs:` instance method; map `toolbarItems` prop in `updateProps:oldProps:`; call `setToolbarItems:` / `setToolbarHidden:` in `updateViewController:withConfig:animated:` - `apps/`: add Toolbar playground with 7 demo screens Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds 'AdvancedMenus' demo screen to the Toolbar playground showing multi-level nested submenus, inline sections, and destructive actions across Format and View menu buttons. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Demonstrates labelStyle on toolbar button items: bold/italic font weight, small/large font size, and custom label colors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fontStyle was never read from the titleStyle config dict, and RCTFont was called with style:nil unconditionally. Read fontStyle from the dict and pass it through, and expand the condition to enter the RCTFont path whenever fontStyle is set (even without fontFamily/fontWeight). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reduce to three items and add a custom font family with italic style. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Hide toolbar (setToolbarItems:nil + setToolbarHidden:YES) in the shouldHide early-return branch so toolbar does not persist when navigating to a screen with headerShown: false - Extract duplicate findInMenu to module scope in ScreenStackHeaderConfig.tsx - Add JSDoc to ToolbarItemFlexibleSpace and ToolbarItem in types.tsx Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
UIBarButtonItemBadge is not rendered by UIKit when the item is in a UIToolbar. Exclude badge from ToolbarItem in types.tsx (explicit union over Omit<…, 'badge'> so the discriminated union is preserved) and update prepareHeaderBarButtonItems to use the badge-capable base type so header bar button items (left/right) retain badge support. Remove BadgeItemsScreen example and debug NSLog. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Hey @johankasperi, thank you for the contribution. We'll find time to review this, but FYI it's not a priority atm. We are currently focused on delivering next-major-related scope and we assign low priority to any new features targeted at currently stable major version. |
There was a problem hiding this comment.
Pull request overview
Adds iOS toolbar item support for stack headers, exposing a new toolbar item configuration path from TypeScript through Fabric/native iOS and adding documentation plus an example playground.
Changes:
- Adds
toolbarItemspublic types and native component props/events. - Builds and applies
UIBarButtonItemtoolbar items on iOS, including flexible/fixed spacing and menu/action callbacks. - Adds guide documentation and a new Toolbar example screen in the example app.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
src/types.tsx |
Adds toolbarItems and ToolbarItem typings. |
src/fabric/ScreenStackHeaderConfigNativeComponent.ts |
Adds native toolbar item prop and press events. |
src/components/ScreenStackHeaderConfig.tsx |
Prepares toolbar items and dispatches toolbar callbacks. |
src/components/helpers/prepareHeaderBarButtonItems.ts |
Extends item preparation for toolbar/flexible space support. |
ios/RNSScreenStackHeaderConfig.mm |
Applies toolbar items to the view controller and emits toolbar events. |
ios/RNSScreenStackHeaderConfig.h |
Declares stored toolbar item configs. |
ios/RNSBarButtonItem.mm |
Adds fontStyle support for bar button title styling. |
guides/GUIDE_FOR_LIBRARY_AUTHORS.md |
Documents the new toolbar items API. |
apps/src/screens/Toolbar.tsx |
Adds a playground for toolbar item scenarios. |
apps/Example.tsx |
Registers the Toolbar playground screen. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| NSString *fontFamily = titleStyle[@"fontFamily"]; | ||
| NSNumber *fontSize = titleStyle[@"fontSize"]; | ||
| NSString *fontWeight = titleStyle[@"fontWeight"]; | ||
| NSString *fontStyle = titleStyle[@"fontStyle"]; |
| ```typescript | ||
| <Stack.Screen | ||
| options={{ | ||
| toolbarItems: [ |
| useEffect(() => { | ||
| navigation.setOptions({ | ||
| title: `Dynamic Items (${count})`, | ||
| unstable_toolbarItems: () => [ |
Thank you! Totally understand that it isn't a priority. There is no hurry from my side either. |
Description
Inspired by the toolbar functionality in expo router this PR introduces a very similar API as
headerBarButtonItemsto the stack navigator but instead of creating UIBarButtonItem for the header, it creates UIBarButtonItem for the screen toolbar (bottom of the screen).Changes
Adds a new prop to ScreenStackHeaderConfigProps named
toolbarItems?: ToolbarItem[] | undefined;. Uses this config to generate an array of UIBarButtonItem and sets this array onto the current view controller withsetToolbarItems.Before & after - visual documentation
Before
N/A
After
Simulator.Screen.Recording.-.iPhone.17.Pro.-.2026-05-11.at.15.21.17.mov
Test plan
Run the example app and open the new example named "Toolbar"
Checklist