From 118c09d9ae15544c33907be18a9fa5b13cfd0486 Mon Sep 17 00:00:00 2001 From: Mathieu Acthernoene Date: Tue, 24 Feb 2026 10:52:26 +0100 Subject: [PATCH 1/9] Edge-to-edge cleanup (expo-status-bar, expo-navigation-bar) (#43276) # Why Android (and Expo) now enforces edge-to-edge, making several `StatusBar` / `NavigationBar` APIs obsolete. This PR deprecate and no-op those APIs. Those APIs are: - `StatusBar` [`setBackgroundColor`](https://reactnative.dev/docs/0.83/statusbar#setbackgroundcolor-android) - `StatusBar` [`setTranslucent`](https://reactnative.dev/docs/0.83/statusbar#settranslucent-android) - `NavigationBar` [`getBackgroundColorAsync`](https://docs.expo.dev/versions/v54.0.0/sdk/navigation-bar/#navigationbargetbackgroundcolorasync) / [`setBackgroundColorAsync`](https://docs.expo.dev/versions/v54.0.0/sdk/navigation-bar/#navigationbarsetbackgroundcolorasynccolor) - `NavigationBar` [`getBehaviorAsync`](https://docs.expo.dev/versions/v54.0.0/sdk/navigation-bar/#navigationbargetbehaviorasync) / [`setBehaviorAsync`](https://docs.expo.dev/versions/v54.0.0/sdk/navigation-bar/#navigationbarsetbehaviorasyncbehavior) - `NavigationBar` [`getBorderColorAsync`](https://docs.expo.dev/versions/v54.0.0/sdk/navigation-bar/#navigationbargetbordercolorasync) / [`setBorderColorAsync`](https://docs.expo.dev/versions/v54.0.0/sdk/navigation-bar/#navigationbarsetbordercolorasynccolor) - `NavigationBar` [`getButtonStyleAsync`](https://docs.expo.dev/versions/v54.0.0/sdk/navigation-bar/#navigationbargetbuttonstyleasync) But we can also includes some long-time deprecated functions and props, like `networkActivityIndicatorVisible` (deprecated since iOS 13 release) or `androidNavigationBar.visible` / `expo-navigation-bar` `legacyVisible` (deprecated 3 years ago) # How ### @expo/config-plugins - Deprecate and no-op `androidStatusBar.backgroundColor` and `androidStatusBar.translucent` and emit a warning in case of usage - Enforce `android:statusBarColor` to be `@android:color/transparent` ### @expo/config-types - Deprecate `androidStatusBar.backgroundColor`, `androidStatusBar.translucent` and `androidNavigationBar` ### @expo/prebuild-config - Remove `androidNavigationBar.enforceContrast` property handling in `withEdgeToEdge` (it has been moved to the `expo-navigation-bar` plugin config) - Remove `androidNavigationBar.visible` property handling / warning - Deprecate and no-op `androidNavigationBar.backgroundColor` property - Enforce `android:navigationBarColor` to be `@android:color/transparent` ## expo-navigation-bar - Deprecate and no-op `setBackgroundColorAsync`, `getBackgroundColorAsync`, `setBorderColorAsync`, `getBorderColorAsync`, `setBehaviorAsync`, `getBehaviorAsync`, `setPositionAsync`, `unstable_getPositionAsync` and `getButtonStyleAsync` functions. Remove their native Android implementations - Deprecate and no-op `borderColor`, `backgroundColor`, `behavior`, `position` plugin options - Add the `enforceContrast` plugin option. Fallback to `androidNavigationBar.enforceContrast` if `androidNavigationBar` is set - Remove `legacyVisible` property handling / warning - Remove the (now unnecessary) `@react-native/normalize-colors` dependency ## expo-status-bar - Deprecate and no-op the `backgroundColor`, `networkActivityIndicatorVisible`, and `translucent` `StatusBar` props - Deprecate and no-op the `setStatusBarBackgroundColor`, `setStatusBarNetworkActivityIndicatorVisible`, and `setStatusBarTranslucent` functions ## Other - Remove deprecated `NavigationBar` screen examples from the test app # Test Plan 1. Run `expo-navigation-bar`, `expo-status-bar `, `@expo/config-plugins` and `@expo/prebuild-config` packages and plugins unit tests 2. Run `npx expo prebuild` on a bare Android project with the following `app.json` and verify: - `android:statusBarColor` is `@android:color/transparent` in `styles.xml` - `android:navigationBarColor` is `@android:color/transparent` in `styles.xml` - Build warnings are emitted for each deprecated property used # Checklist - [x] I added a `changelog.md` entry and rebuilt the package sources according to [this short guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting) - [x] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). - [ ] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md) --- .../src/screens/NavigationBarScreen.tsx | 108 +----- .../unversioned/sdk/navigation-bar.mdx | 76 +--- .../data/unversioned/expo-navigation-bar.json | 2 +- .../data/unversioned/expo-status-bar.json | 2 +- packages/@expo/config-plugins/CHANGELOG.md | 2 + .../build/android/StatusBar.d.ts | 10 - .../config-plugins/build/android/StatusBar.js | 78 ++--- .../build/android/StatusBar.js.map | 2 +- .../config-plugins/src/android/StatusBar.ts | 72 ++-- .../src/android/__tests__/StatusBar-test.ts | 51 +-- .../@expo/config-types/build/ExpoConfig.d.ts | 3 + packages/@expo/config-types/src/ExpoConfig.ts | 3 + packages/@expo/prebuild-config/CHANGELOG.md | 4 + .../edge-to-edge/withEdgeToEdge.js | 8 - .../edge-to-edge/withEdgeToEdge.js.map | 2 +- .../withEnforceNavigationBarContrast.d.ts | 4 - .../withEnforceNavigationBarContrast.js | 54 --- .../withEnforceNavigationBarContrast.js.map | 1 - .../withAndroidNavigationBar.d.ts | 3 - .../withAndroidNavigationBar.js | 39 +-- .../withAndroidNavigationBar.js.map | 2 +- .../withDefaultPlugins-test.ts.snap | 35 +- .../__tests__/withEdgeToEdge-test.ts | 207 ----------- .../edge-to-edge/withEdgeToEdge.ts | 6 - .../withEnforceNavigationBarContrast.ts | 48 --- .../withAndroidNavigationBar-test.ts | 39 +-- .../withAndroidNavigationBar.ts | 51 +-- packages/expo-navigation-bar/CHANGELOG.md | 6 + .../navigationbar/NavigationBarModule.kt | 59 ---- ...gationBarReactActivityLifecycleListener.kt | 41 --- .../navigationbar/singletons/NavigationBar.kt | 121 ------- .../android/src/main/res/values/strings.xml | 8 - .../build/ExpoNavigationBar.d.ts | 12 +- .../build/ExpoNavigationBar.d.ts.map | 2 +- .../build/ExpoNavigationBar.js.map | 2 +- .../build/NavigationBar.android.d.ts.map | 2 +- .../build/NavigationBar.android.js | 27 +- .../build/NavigationBar.android.js.map | 2 +- .../build/NavigationBar.d.ts | 56 +-- .../build/NavigationBar.d.ts.map | 2 +- .../build/NavigationBar.js | 56 +-- .../build/NavigationBar.js.map | 2 +- .../build/NavigationBar.types.d.ts | 2 + .../build/NavigationBar.types.d.ts.map | 2 +- .../build/NavigationBar.types.js.map | 2 +- packages/expo-navigation-bar/package.json | 5 +- .../plugin/build/withNavigationBar.d.ts | 31 +- .../plugin/build/withNavigationBar.js | 156 ++++----- .../src/__tests__/withNavigationBar-test.ts | 328 ++++++++++++------ .../plugin/src/withNavigationBar.ts | 242 +++++++------ .../src/ExpoNavigationBar.ts | 16 - .../src/NavigationBar.android.ts | 31 +- .../expo-navigation-bar/src/NavigationBar.ts | 56 +-- .../src/NavigationBar.types.ts | 2 + packages/expo-router/CHANGELOG.md | 1 + packages/expo-router/package.json | 2 +- packages/expo-status-bar/CHANGELOG.md | 2 + .../build/NativeStatusBarWrapper.d.ts | 5 +- .../build/NativeStatusBarWrapper.d.ts.map | 2 +- .../build/StatusBar.android.d.ts.map | 2 +- packages/expo-status-bar/build/types.d.ts | 3 + packages/expo-status-bar/build/types.d.ts.map | 2 +- .../src/NativeStatusBarWrapper.tsx | 35 +- .../expo-status-bar/src/StatusBar.android.tsx | 12 - .../src/__tests__/StatusBar-test.android.tsx | 50 --- packages/expo-status-bar/src/types.ts | 3 + yarn.lock | 29 +- 67 files changed, 673 insertions(+), 1658 deletions(-) delete mode 100644 packages/@expo/prebuild-config/build/plugins/unversioned/edge-to-edge/withEnforceNavigationBarContrast.d.ts delete mode 100644 packages/@expo/prebuild-config/build/plugins/unversioned/edge-to-edge/withEnforceNavigationBarContrast.js delete mode 100644 packages/@expo/prebuild-config/build/plugins/unversioned/edge-to-edge/withEnforceNavigationBarContrast.js.map delete mode 100644 packages/@expo/prebuild-config/src/plugins/unversioned/edge-to-edge/withEnforceNavigationBarContrast.ts delete mode 100644 packages/expo-status-bar/src/__tests__/StatusBar-test.android.tsx diff --git a/apps/native-component-list/src/screens/NavigationBarScreen.tsx b/apps/native-component-list/src/screens/NavigationBarScreen.tsx index 54f4b8bbe9ab77..efd985c38a8640 100644 --- a/apps/native-component-list/src/screens/NavigationBarScreen.tsx +++ b/apps/native-component-list/src/screens/NavigationBarScreen.tsx @@ -1,41 +1,9 @@ import * as NavigationBar from 'expo-navigation-bar'; import * as React from 'react'; import { Platform, ScrollView, Text } from 'react-native'; -import { useSafeAreaFrame, useSafeAreaInsets } from 'react-native-safe-area-context'; import Button from '../components/Button'; import { Page, Section } from '../components/Page'; -import { getRandomColor } from '../utilities/getRandomColor'; - -function usePosition(): [ - NavigationBar.NavigationBarPosition | null, - (position: NavigationBar.NavigationBarPosition) => void, -] { - const [position, setPosition] = React.useState(null); - - React.useEffect(() => { - let isMounted = true; - NavigationBar.unstable_getPositionAsync().then((position) => { - if (isMounted) { - setPosition(position); - } - }); - - return () => { - isMounted = false; - }; - }, []); - - const setNewPosition = React.useCallback( - (position: NavigationBar.NavigationBarPosition) => { - NavigationBar.setPositionAsync(position); - setPosition(position); - }, - [setPosition] - ); - - return [position, setNewPosition]; -} export default function NavigationBarScreen() { return ( @@ -50,18 +18,6 @@ export default function NavigationBarScreen() {
-
- -
-
- -
-
- -
-
- -
); @@ -84,76 +40,16 @@ function VisibilityExample() { ); } -function BackgroundColorExample() { - return ( -