Skip to content

feat!: rewrite as a New Architecture turbo module (v3) - #71

Merged
kadiraydinli merged 1 commit into
mainfrom
v3
Jul 30, 2026
Merged

feat!: rewrite as a New Architecture turbo module (v3)#71
kadiraydinli merged 1 commit into
mainfrom
v3

Conversation

@kadiraydinli

Copy link
Copy Markdown
Owner

Summary

v3 is a full rewrite of the library as a New Architecture TurboModule. The Java module is replaced by Kotlin built on WindowInsetsControllerCompat, the public API is redesigned around a smaller and more consistent surface, and iOS gains real support instead of being a stub.

Why now: v2 was written against the legacy bridge and the pre-WindowInsetsController flag APIs. Those flags are deprecated, Android 15 enforces edge-to-edge, and the module could settle the same promise twice — none of which could be fixed without breaking the API.

API

hide · show · setImmersive · setBarStyle · setBarColor · getBarColor · setDividerColor · setContrastEnforced · setEdgeToEdge · isEdgeToEdgeEnabled · getNavigationMode

iOS-only: setHomeIndicatorAutoHidden · setSystemGesturesDeferred

Every v2 name still works as a deprecated alias with a one-time __DEV__ warning, and will be removed in v4. lowProfile is gone (the platform behavior it wrapped no longer exists) and getBarColor now always resolves { status, navigation }. The README has a migration table.

iOS

Previously the package shipped no iOS code. It now controls the two things iOS actually exposes — the home indicator and the bottom-edge system gesture — through isa-swizzling on the window's view-controller chain, so no AppDelegate or subclass setup is required. These are two separate methods on purpose: UIKit ignores gesture deferral while the indicator is auto-hidden, so a single combined API could not express both.

Issues addressed

Also in this change

Example app rebuilt around the new API, demo GIFs re-recorded, README rewritten with per-method platform notes and links to the Android/Apple docs, plus SECURITY.md, a PR template and Dependabot config.

Test plan

yarn lint, yarn typecheck and yarn test (44 tests, 2 suites) all pass. Beyond that, the release build of the example app was driven end to end on emulators and a simulator:

Android 14 (API 34) Android 16 (API 36) Android 17 (API 37)
Navigation mode three-button three-button gesture
hide / show
lean-back / immersive / sticky, enter and exit
Bar color applies fully opaque composited as a scrim ignored
Divider ✅ at the bar's top edge ignored ignored
translucent: true color ignored, platform scrim drawn
isEdgeToEdgeEnabled false → true → false true (enforced) true (enforced)
getNavigationMode three-button three-button gesture

The three different color outcomes are the documented Android 15+ behavior, not regressions.

iOS 26.5, iPhone 17 Pro. UIKit state read back with lldb:

  • setHomeIndicatorAutoHidden(true) → root view controller becomes UIViewController_RNSystemNavigationBar, prefersHomeIndicatorAutoHidden = YES; (false)NO
  • setSystemGesturesDeferred(true)preferredScreenEdgesDeferringSystemGestures = 15 (UIRectEdgeAll); (false)0
  • The two are independent
  • All Android-only methods resolve silently without throwing; getBarColor#00000000, isEdgeToEdgeEnabledtrue, getNavigationModegesture

No JS or native errors in logcat or the iOS unified log on any platform.

Checklist

  • yarn lint and yarn typecheck pass
  • yarn test passes
  • Tested in the example app (Android and/or iOS, whichever the change affects)
  • README updated if the public API changed

BREAKING CHANGE: requires React Native 0.76 or newer with the New Architecture.
@kadiraydinli
kadiraydinli merged commit 6eb7bd0 into main Jul 30, 2026
5 checks passed
@kadiraydinli
kadiraydinli deleted the v3 branch July 30, 2026 21:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment