Skip to content

feat(iOS): add axis behavior to v5 header items - #4692

Open
juliusmarminge wants to merge 1 commit into
software-mansion:mainfrom
juliusmarminge:feat/ios-v5-bar-button-axis-behavior
Open

juliusmarminge wants to merge 1 commit into
software-mansion:mainfrom
juliusmarminge:feat/ios-v5-bar-button-axis-behavior

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Sep 20, 2026 •

Copy link
Copy Markdown

Description

Proposes optional axisBehavior on v5 iOS leading/trailing native and custom header items, matching UIBarButtonItem.axisBehavior: automatic, horizontalOnly, and verticalPreferred. In a layout with horizontal and vertical bars, an app can keep an item horizontal or prefer vertical placement without detecting a device or controlling the bar layout.

API discussion: #4687.

Changes

  • Add consistent public, internal, and Fabric props, defaulting to automatic.
  • Read the current Fabric prop through the existing item provider and invalidate the existing native item when it changes. Removing an explicit value restores automatic.
  • Apply the preference to both native and custom UIBarButtonItem creation. Existing identifiers, shared backgrounds, and menu state mechanisms are retained.
  • Guard the UIKit API at SDK and runtime level. Older iOS, Android, tvOS, and visionOS ignore the option.

SDK evidence is limited to installed Xcode 27.1 build 27A9269. Its UIKit headers declare the enum/property at iOS 27.1, the two explicit cases unavailable on tvOS/visionOS, and automatic as the default. Apple's bar placement presentation demonstrates the preferences. Apple's axisBehavior API documentation page currently returns an error; this proposal does not assert availability or stability beyond the installed SDK evidence.

Adapted from Julius Marminge's frozen v5 patch delta onto current ios/stack/header sources. This independent PR only covers axis behavior.

Before & after - visual documentation

Actual base native revision 7db05401d0d25f37143d875488c7a5a1b1720248 and head 84743ae02302b7ad02513a429262e30d1024dd6b, using the same added scenario, viewport, initial values, and isolated test-app setup. The base ignores the new options and reports native axes 0/0; the head reports 1/2. The sun moves from the vertical bar to the horizontal bar, and the custom A moves into the vertical bar. Captures are unaltered; simulator clock time differs.

Before, UIKit automatic After, explicit item preferences
Before: custom A horizontal and sun vertical After: sun horizontal and custom A vertical

Test plan

Complete FabricExample scenario: apps/src/tests/single-feature-tests/stack-v5/test-stack-header-axis-behavior-ios/, registered in the existing scenario list.

  1. Build FabricExample with the iOS 27.1 SDK and scene delegate enabled, then open Stack Header Axis Behavior (iOS) on an iOS 27.1 configuration where UIKit shows both bar axes.
  2. Change both items through all three values; remove the options and compare with automatic.
  3. Remove/reinsert items, toggle the fixed spacer, press both items, push to the second screen with the same identifiers, update its preference, and pop.
  4. Repeat on an older iOS runtime to check that the options are ignored.

Local checks:

  • Library TypeScript, focused ESLint/Prettier, repository commit hooks, Bob CommonJS/module/declaration builds, and React Doctor passed.
  • Full iOS and Android schema/artifact generation passed. The iOS item spec stays excluded from Android.
  • Full FabricExample base and head simulator builds passed with isolated DerivedData and Metro port 18133.
  • Live iOS 27.1 native assertions passed for every value on both item types, explicit-to-omitted reset, removal/reinsertion, spacer changes, both callbacks, and settled identifier-matched push/pop behavior. Native values were read from real navigation items using temporary test-app diagnostics, excluded from this PR.
  • Live iOS 18.6 checks passed for explicit-to-automatic/omitted updates, item reinsertion, unchanged default horizontal placement, and both callbacks.
  • The full updated content-factory translation unit compiled against installed iOS 27.1, older iOS 27.0, tvOS 27.1, and visionOS 27.1 SDKs. These are compatibility syntax checks, not full app builds for every platform.
  • Example-app TypeScript has pre-existing failures. Base/head comparison produced no new diagnostic in the added scenario; the full example typecheck is not claimed to pass.

Verification receipts: summary, iOS 27.1 native navigation-item assertions, iOS 18.6 UI assertions.

React Navigation companion and remaining gates

React Navigation main has no v5 adapter. A prepared companion patch adds the option to button/menu/custom types and forwards it in the new adapter from adoption draft #13115, against revision 7b32fd92d335faf0ed3437032ccadff4a17e41c7. It passes git apply --check against that exact draft; full downstream typechecks and review have not run. Downstream v5 adoption/review and maintainer API/SDK acceptance remain integration gates. No companion PR against main is claimed.

All seven GitHub Actions workflows currently conclude action_required and await maintainer approval for the fork. No CI pass is claimed. CodeRabbit completed with no actionable comments. Its native-method docstring coverage warning was reviewed; the public option documents the values, default, reset, and platform support. No merge is requested.

Checklist

  • Included complete code example.
  • Included actual base/head screenshots.
  • Updated relevant public types.
  • Ensured that CI passes.

@coderabbitai

coderabbitai Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 7eb4c609-7ea6-487b-938b-8744bc1492e3

📥 Commits

Reviewing files that changed from the base of the PR and between 7db0540 and 84743ae.

📒 Files selected for processing (13)
  • apps/src/tests/single-feature-tests/stack-v5/index.ts
  • apps/src/tests/single-feature-tests/stack-v5/test-stack-header-axis-behavior-ios/index.tsx
  • apps/src/tests/single-feature-tests/stack-v5/test-stack-header-axis-behavior-ios/scenario-description.ts
  • apps/src/tests/single-feature-tests/stack-v5/test-stack-header-axis-behavior-ios/scenario.md
  • ios/stack/header/RNSHeaderItemAxisBehavior.h
  • ios/stack/header/RNSStackHeaderContentFactory.mm
  • ios/stack/header/RNSStackHeaderItemComponentView.h
  • ios/stack/header/RNSStackHeaderItemComponentView.mm
  • ios/stack/header/RNSStackHeaderItemDataProviding.h
  • src/components/stack/header/StackHeaderConfig.ios.types.ts
  • src/components/stack/header/ios/StackHeaderItem.ios.types.ts
  • src/components/stack/index.ts
  • src/fabric/stack/StackHeaderItemIOSNativeComponent.ts

Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review.


📝 Walkthrough

Walkthrough

Adds iOS stack header axis behavior types and native handling for automatic, horizontalOnly, and verticalPreferred. Registers an interactive iOS 27.1 scenario that tests native and custom header items.

Changes

iOS stack header axis behavior

Layer / File(s) Summary
Axis behavior contracts
src/components/stack/header/..., src/components/stack/index.ts, src/fabric/stack/StackHeaderItemIOSNativeComponent.ts
Adds the StackHeaderItemAxisBehaviorIOS type and optional axisBehavior properties. Exports the type publicly and adds the Fabric native prop with an automatic default.
Native axis mapping
ios/stack/header/*
Maps React axis values to native enums and UIKit UIBarButtonItemAxisBehavior values on supported iOS versions. Header items invalidate when the value changes.
Scenario registration and validation
apps/src/tests/single-feature-tests/stack-v5/...
Adds a two-screen interactive scenario with native and custom trailing items, controls for axis behavior and visibility, scenario metadata, manual test steps, and stack-v5 registration.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant Scenario
  participant StackHeaderItemIOSNativeComponent
  participant RNSStackHeaderItemComponentView
  participant RNSStackHeaderContentFactory
  participant UIKit
  Scenario->>StackHeaderItemIOSNativeComponent: Set axisBehavior
  StackHeaderItemIOSNativeComponent->>RNSStackHeaderItemComponentView: Pass axisBehavior
  RNSStackHeaderItemComponentView->>RNSStackHeaderContentFactory: Provide mapped behavior
  RNSStackHeaderContentFactory->>UIKit: Apply UIBarButtonItemAxisBehavior
Loading

Suggested reviewers: kmichalikk

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 10 files. (3 skipped: 3… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the main change: adding iOS axis behavior support to v5 header items.
Description check ✅ Passed The description directly explains the axisBehavior API, implementation changes, compatibility guards, tests, and remaining integration gates.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 10 files. (3 skipped: 3 unsupported.)

  • Fix all pre-merge checks with AI

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@juliusmarminge

Copy link
Copy Markdown
Author

CodeRabbit completed against 84743ae02302b7ad02513a429262e30d1024dd6b with no actionable comments. I checked its docstring coverage warning: the two touched native methods follow the existing factory/getter style, and SupportsAxisBehaviorIOS documents every value, the default, explicit-to-omitted reset, and SDK/platform limits. No missing public API documentation was identified.

All seven Actions workflows still await fork approval with action_required; no CI pass or merge readiness is claimed. The PR body now includes successful iOS 18.6 fallback checks alongside the iOS 27.1 native regression receipts. API/SDK acceptance and the React Navigation v5 companion remain review/integration gates.

This branch has not been deployed

No deployments
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.

1 participant