Skip to content

feat: JS-only implementation on top of core safe area primitives - #752

Draft
janicduplessis wants to merge 3 commits into
mainfrom
core-safe-area-insets-prop
Draft

feat: JS-only implementation on top of core safe area primitives#752
janicduplessis wants to merge 3 commits into
mainfrom
core-safe-area-insets-prop

Conversation

@janicduplessis

@janicduplessis janicduplessis commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

Prototype of what the library looks like on top of the core safe area primitives proposed in react/react-native#57967 — opened for discussion, not for landing: it gates on a placeholder version (RN ≥ 0.88) and can only run against a React Native checkout that includes that PR.

With core reporting insets itself, the library needs no native code:

  • SafeAreaProvider renders a plain View with the core onSafeAreaInsetsChange prop. The payload is identical to our onInsetsChange, so nothing else changes. Also covers SafeAreaListener.
  • SafeAreaView promotes the existing web implementation to every platform: insets come from the provider context and are applied per-edge as padding or margin in JS, with the same edges/mode semantics as before.
  • initialWindowMetrics reads Dimensions.get('window').safeAreaInsets, which the core PR exposes using the same native inset computation as the view prop, so the RNCSafeAreaContext module is not needed either.

The part that makes the JS implementations viable is that core dispatches the inset event synchronously: the padding derived from the insets is mounted in the frame the insets changed in, so the JS SafeAreaView keeps the no-flicker behavior that previously required the native shadow node.

On React Native versions before the core prop exists, everything falls back to the current native path — SUPPORTS_CORE_SAFE_AREA_INSETS in src/coreSafeAreaInsets.ts is the single gate.

Test Plan

  • yarn validate:jest — 22 tests pass. The jest environment reports RN 1000.0.0, so the suite exercises the new JS path (snapshots updated accordingly); the legacy native path is covered by mocking the gate.
  • yarn validate:typescript passes.
  • Not run against a real app: that requires a React Native build containing Add an onSafeAreaInsetsChange view prop react/react-native#57967. End-to-end behavior of the underlying primitive — including frame-by-frame validation of no-flicker sync rendering on both platforms — is in that PR.

When core reports safe area insets through the onSafeAreaInsetsChange
view prop (react/react-native#57967), the library needs no native
code:

- SafeAreaProvider renders a plain View with the prop; the payload is
  identical to onInsetsChange.
- SafeAreaView promotes the existing web implementation to every
  platform: insets come from the provider context and are applied
  per-edge as padding or margin, preserving the native shadow node
  semantics (off/additive/maximum). Core's synchronous event dispatch
  keeps both same-frame.

Gated on the RN version so older versions keep the native path. The
jest environment reports RN 1000.0.0, so the test suite exercises the
new path.
Core reports window safe area insets through Dimensions (same native
code as the onSafeAreaInsetsChange view prop), which removes the need
for the RNCSafeAreaContext native module.
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