fix(iOS, Stack v4+): reapply header config once the navigation bar has a window - #4588
Conversation
…s a window A bar button item assigned to a navigation bar that is not part of any window misses the styling UIKit resolves against that window. On iOS 26 a `prominent` item then renders without its background until the items are assigned again. A stack nested in tabs hits this on every tab re-selection that follows its view being detached: `willShowViewController:` applies the config while the bar is still window-less, and nothing reassigns the items afterwards, so the button stays background-less for the whole visit. The config now records an application that landed on a window-less bar, and `RNSScreenStackView` asks it to repeat that application when the stack enters a window. The repeat is dispatched one main queue turn later, because the hierarchy insertion that brought the bar into the window is still in progress when `didMoveToWindow` runs, and applying synchronously leaves the styling unrealized exactly as before.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (5)
Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review. 📝 WalkthroughWalkthroughThe iOS stack now reapplies header configuration after a navigation bar attaches to a window. A new issue test reproduces the prominent toolbar button scenario across tabs and appearance changes. ChangesProminent header styling restoration
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to This localized iOS fix reapplies existing header styling when the navigation bar becomes attached, preventing prominent buttons from losing their background during tab switches. No actionable merge-blocking risk remains beyond normal checks and review. Sequence Diagram(s)sequenceDiagram
participant TabTwo
participant Appearance
participant RNSScreenStack
participant RNSScreenStackHeaderConfig
participant UINavigationBar
TabTwo->>Appearance: Toggle color scheme
Appearance->>RNSScreenStack: Update tab appearance
RNSScreenStack->>RNSScreenStackHeaderConfig: Apply header configuration
RNSScreenStackHeaderConfig->>UINavigationBar: Detect bar outside a window
RNSScreenStack->>RNSScreenStackHeaderConfig: Retry after window attachment
RNSScreenStackHeaderConfig->>UINavigationBar: Reapply prominent button styling
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Linked Issues checkExplanation The changes satisfy issue Full details: Docstring CoverageExplanation 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 4 functions across 3 files. (2 skipped: 2 unsupported.)
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. Comment Warning |
Description
Closes #4479.
A
UIBarButtonItemassigned to a navigation bar that is not part of any window misses the styling UIKit resolves against that window. On iOS 26 avariant: 'prominent'item then renders as a bare glyph — no background — until the items are assigned again.A stack nested in tabs reaches that state on every tab re-selection that follows its view being detached, which is what
Appearance.setColorScheme()on another tab triggers.-[RNSScreenStackView navigationController:willShowViewController:animated:]applies the header config while the bar is still window-less, and nothing reassigns the items afterwards, so the button stays background-less for the whole visit. Switching tabs once more assigns the items again, this time into an attached bar, which is why the button "repairs itself" on the second visit.Instrumented
RNSScreenStackHeaderConfigto confirm this. RNS does identical work in the broken and the self-repairing pass — same view controller, onewillShowViewController:, a freshRNSBarButtonItemwithvariant=prominentresolved toUIBarButtonItemStyleProminent— and the only difference is the bar's window:Reusing the previous
UIBarButtonIteminstances instead of building new ones does not help, so this is not item churn — it is the window the bar is missing when the items land on it.Changes
RNSScreenStackHeaderConfigrecords when an application landed on a window-less navigation bar, and exposes-updateViewControllerIfAppliedOutsideWindowto repeat exactly that application.RNSScreenStackView -didMoveToWindowasks the top screen's header config to repeat it once the stack is in a window.didMoveToWindowruns, and applying synchronously there leaves the styling unrealized exactly as before — verified on device before settling on the async hop.Test4479to the issue tests, based on the MRE @t0maboro attached to the issue.Two notes on scope:
didMoveToWindowfollows and the flag simply stays set until the next attach — the same behaviour as today, no regression.Before & after - visual documentation
Test4479on iPhone 17 Pro, iOS 26.5, after: tab One → tab Two → toggle appearance → back to tab One.Test plan
apps/src/tests/issue-tests/Test4479.tsx(new), run throughFabricExampleon an iPhone 17 Pro / iOS 26.5 simulator.Test4479. Tab One shows a prominent+in the header.Before the change the
+has lost its background and keeps it lost for the whole visit; after the change it keeps the background. Repeated toggles and tab switches were also checked in both directions.Regression checks on the same build:
yarn check-typespasses; the touched Objective-C files are unchanged under the repository.clang-format, and the new test file is Prettier-clean.Checklist
Written by an agent (Claude Code, claude-opus-5) on behalf of @LizunovSergey; the diagnosis above was verified on a simulator rather than inferred.