Skip to content

feat: Add toggling items with managed flow to menu#4194

Open
kmichalikk wants to merge 5 commits into
@kmichalikk/stack-v5-header-menu-onpressfrom
@kmichalikk/stack-v5-header-menu-selected-view-command
Open

feat: Add toggling items with managed flow to menu#4194
kmichalikk wants to merge 5 commits into
@kmichalikk/stack-v5-header-menu-onpressfrom
@kmichalikk/stack-v5-header-menu-selected-view-command

Conversation

@kmichalikk

@kmichalikk kmichalikk commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Closes https://github.com/software-mansion/react-native-screens-labs/issues/1187
Closes https://github.com/software-mansion/react-native-screens-labs/issues/1137

Description

This PR adds support for toggleable items with optional singleSelection flag.

  • by default, items are actions that can be passed an onPress callback
  • when itemType is set to 'toggle', then it doesn't react to onPress but rather its parent menu sends an onSelectionChanged callback for all child items of toggle type (this means that menu can contain both actions and toggles, and onSelectionChanged sends only the ids of toggles)
  • when menu is set to singleSelection, then the whole hierarchy below acts as a one big radio group
    • each child is toggle by default and cannot be set to action (issues a warning)
    • only one child in one nested menu can be selected at any point in time
    • only one child can have initialToggleState set to true
    • onSelectionChanged is triggered only when selected value changes, clicking on the same item does nothing

Changes

  • added itemType: 'action' | 'toggle' | 'inherit' | undefined prop, inherit by default, which gives toggle for singleSelection menus and action otherwise
  • added initialToggleState for toggles (for singleSelection, user is warned for setting it to true for multiple items, only first is applied)
  • added onSelectionChanged callback to menu

Before & after - visual documentation

image

Test plan

See test-stack-header-menu-ios SFT

Checklist

  • Included code example that can be used to test this change.
  • For visual changes, included screenshots / GIFs / recordings documenting the change.
  • For API changes, updated relevant public types.
  • Ensured that CI passes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds toggleable (multi-select) and singleSelection (radio-group) behavior to iOS stack header menus in the gamma API, including a new native-to-JS selection-change event and state tracking to keep checkmarks in sync.

Changes:

  • Added onMenuSelectionChanged as a new iOS Fabric event and JS-side wiring to dispatch selection changes to the correct menu callback.
  • Extended menu JS types (itemType, initialToggleState, singleSelection, onSelectionChanged) and implemented iOS-side parsing + toggle/radio state tracking + menu rebuilding.
  • Updated the iOS SFT scenario and app screen to exercise action/toggle/singleSelection behavior.

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
src/fabric/gamma/stack/StackHeaderConfigIOSNativeComponent.ts Adds the onMenuSelectionChanged native event type/prop for iOS Fabric.
src/components/gamma/stack/header/utils.ts Adds JS-side menu tree validation (warnings for unsupported callback configurations).
src/components/gamma/stack/header/StackHeaderConfig.ios.tsx Wires the new native selection-change event to menu.onSelectionChanged and runs callback validation.
src/components/gamma/stack/header/ios/StackHeaderMenu.ios.types.ts Extends public JS menu types with toggle/radio props and selection callback.
ios/gamma/stack/header/RNSStackHeaderMenuToggleStateTracker.mm Implements native toggle/radio state storage for menu items.
ios/gamma/stack/header/RNSStackHeaderMenuToggleStateTracker.h Declares the toggle/radio state tracker interface.
ios/gamma/stack/header/RNSStackHeaderMenuMapper.mm Parses singleSelection, itemType, and initialToggleState from the menu prop dictionary.
ios/gamma/stack/header/RNSStackHeaderMenuEventsDelegate.h Adds delegate method for selection-change events.
ios/gamma/stack/header/RNSStackHeaderMenuData.mm Stores parsed menu/menuItem fields for toggle/radio behavior.
ios/gamma/stack/header/RNSStackHeaderMenuData.h Defines RNSMenuItemType and new data fields (singleSelection, initialToggleState, etc.).
ios/gamma/stack/header/RNSStackHeaderMenuCoordinator.mm Builds UIMenu/UIAction elements with toggle/radio behavior and emits selection changes.
ios/gamma/stack/header/RNSStackHeaderMenuCoordinator.h Updates coordinator API to accept a toggle state tracker.
ios/gamma/stack/header/RNSStackHeaderItemDataProviding.h Exposes the toggle state tracker from header items to the menu builder.
ios/gamma/stack/header/RNSStackHeaderItemComponentView.mm Instantiates a tracker when a menu is set/changed.
ios/gamma/stack/header/RNSStackHeaderItemComponentView.h Exposes the tracker as a property.
ios/gamma/stack/header/RNSStackHeaderContentFactory.mm Passes the tracker into menu construction when creating bar button items.
ios/gamma/stack/header/RNSStackHeaderConfigEventEmitter.mm Emits the new selection-change event to JS (via Fabric event emitter).
ios/gamma/stack/header/RNSStackHeaderConfigEventEmitter.h Declares the new selection-change emission method.
ios/gamma/stack/header/RNSStackHeaderConfigComponentView.mm Implements selection-change delegate method and forces menu rebuild to refresh checkmarks.
apps/src/tests/single-feature-tests/stack-v5/test-stack-header-menu-ios/scenario.md Updates the manual test scenario for action/toggle/singleSelection.
apps/src/tests/single-feature-tests/stack-v5/test-stack-header-menu-ios/scenario-description.ts Updates scenario description text to reflect new coverage.
apps/src/tests/single-feature-tests/stack-v5/test-stack-header-menu-ios/index.tsx Updates the scenario screen to demonstrate toggles and singleSelection menus.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ios/gamma/stack/header/RNSStackHeaderConfigEventEmitter.mm
Comment thread ios/gamma/stack/header/RNSStackHeaderMenuCoordinator.mm
Comment thread ios/gamma/stack/header/RNSStackHeaderMenuCoordinator.mm
Comment thread ios/gamma/stack/header/RNSStackHeaderMenuCoordinator.mm Outdated
Comment thread src/components/gamma/stack/header/utils.ts
Comment thread ios/gamma/stack/header/RNSStackHeaderContentFactory.mm
@kmichalikk kmichalikk marked this pull request as draft June 19, 2026 11:24
@kmichalikk kmichalikk marked this pull request as ready for review June 19, 2026 13:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants