Skip to content

feat: add ignoreSystemBarsVisibility to SafeAreaProvider - #809

Draft
chocky335 wants to merge 5 commits into
appandflow:mainfrom
chocky335:feat/ignore-system-bars-visibility
Draft

chocky335 wants to merge 5 commits into
appandflow:mainfrom
chocky335:feat/ignore-system-bars-visibility

Conversation

@chocky335

Copy link
Copy Markdown

Summary

Closes #808.

When an app hides the status bar or the Android navigation bar for a moment (a photo viewer, a video player), the insets drop and every screen under it lays out again, then once more when the bars come back. This adds an opt-in ignoreSystemBarsVisibility prop on SafeAreaProvider that reports the insets as if the bars were visible. Nested providers inherit it. The default is false, so nothing changes for current apps.

  • Android 11+: getInsetsIgnoringVisibility with the same type mask, so the IME stays out. The feat: respect window insets a parent adjusts for its subtree on Android #791 max with the dispatched insets stays.
  • Android 6-10: each edge is the max of stableInset* and the display cutout safe inset.
  • iOS 13+: top is the max of the safe area top and the last visible status bar height for the window's vertical size class, minus the view's minY. The height is cached because a hidden status bar reports a zero frame. A compact-height window starts at 0, since iPhone landscape hides the status bar by default. Other edges stay as they are.
  • SafeAreaView on both platforms reads the flag from its provider, so it matches useSafeAreaInsets.
  • Web ignores the prop.

Test Plan

  • yarn validate:jest: 39 tests pass. New tests cover the default, the prop reaching the native provider, inheritance and an explicit false override.
  • yarn validate:typescript, yarn validate:eslint (0 errors) and yarn format:prettier:check pass. clang-format reports nothing on the changed iOS files.
  • Android: compiled in an RN 0.86 app (new architecture). On a Xiaomi Mi 11 Lite (Android 13), hiding and showing the status and navigation bars from a full-screen viewer no longer moves the screen under it. A frame diff of the header and the bottom bar shows a 0 px offset through the viewer close. The Android 6-10 path compiles but has not run on a device.
  • iOS: the pod compiles for the simulator SDK (Xcode 26.6) in the same app, with no warnings in the changed files. It has not run on a device without a notch yet.
  • Example: "Ignore System Bars Visibility" screen with a switch for the prop and a button that hides the status bar.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Nov 4, 2026

Copy link
Copy Markdown

@chocky335 is attempting to deploy a commit to the appandflow Team on Vercel.

A member of the Team first needs to authorize it.

@floco-af floco-af 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.

Thanks for the PR and the detailed write-up. Automated first-pass review from Floco, the App & Flow bot. A maintainer will take a look too.

What I checked

  • Jest on main: 32 passed, 2 skipped. On this branch: 37 passed, 2 skipped. The 5 new tests (default off, prop reaches the native provider, inheritance, explicit false override, stays off under a parent that doesn't set it) all pass.
  • tsc --noEmit is clean and prettier is clean. ESLint reports 0 errors. The 3 warnings are the existing react-native/Libraries/... deep-import warnings and none are in lines this PR adds.
  • I read the Android (new arch and paper delegate), iOS (Paper and Fabric) and JS changes.

Findings

  • The Android design looks right to me. getInsetsIgnoringVisibility never gets the IME type, which would throw. The max with the dispatched insets from #791 is kept. The API 23-29 fallback (stableInset* and cutout) matches what the issue describes. SafeAreaView picks the flag up from its provider and refreshes on the provider's pre-draw pass, so toggling the prop at runtime updates both.
  • The Paper RNCSafeAreaProviderManagerDelegate and Interface are updated by hand. That is correct because they are checked in, not generated.
  • iOS: RNCSafeAreaStatusBarTopInset is only declared and defined for TARGET_OS_IPHONE and returns 0 off iOS (tvOS, visionOS), so those platforms keep the current behaviour. The Fabric updateProps: handling and the reset in prepareForRecycle look right.
  • Minor, iOS: the status bar height cache is a function-level static array shared by every window and provider, and only written on the main thread. It works for the single-window case. If an app has two windows with different status bar heights (iPad multi-scene), they would overwrite each other. Keying the cache on the window scene would avoid this. It is not a blocker.
  • Minor, iOS: if the app starts with the status bar already hidden, nothing is cached yet. The top inset stays 0 until the bar is first shown. The PR already says this for iPhone landscape. It would help to say it for a cold start with a hidden bar too.
  • Minor: the prop is now always sent to native, so ignoreSystemBarsVisibility={false} shows up in downstream snapshot tests of the native tree (the 11 snapshots here changed). That is expected from codegen defaults, but it deserves a changelog line.

What I could not validate

  • I did not build or run on a device or simulator, so the Android 13 and frame-diff result in the test plan is the author's and I did not reproduce it.
  • Per the PR, the Android 6-10 path and iOS (no notch) have not run on a device. They are the riskiest paths, because iOS depends on UIStatusBarManager frame behaviour. A before/after recording on a non-notch iPhone or iPad simulator (status bar 20pt, hide then show) would be good to see.
  • clang-format and spotlessCheck were not run. No CI checks have run on the PR yet. Only Vercel reports, and it needs a team member to authorize it.

Verdict: looks good, with minor points. The remaining decision is whether maintainers want this opt-in prop in the SafeAreaProvider API.

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.

Keep insets stable while the system bars are hidden (opt-in ignoreSystemBarsVisibility)

2 participants