-
-
Notifications
You must be signed in to change notification settings - Fork 527
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: detect edge-to-edge and bypass some props #2464
base: main
Are you sure you want to change the base?
Conversation
Hey @zoontek I took first glance & I want to reiterate to make sure I get this right: the goal here is to extract status bar / navigation bar management in terms of its visibility from all packages beside Note that changes you suggest are breaking. Haven't read your package code, but it assumes that either we're in in edge-to-edge or not, e.g. without possibility of navigation bar being solid (not edge-to-edge) and status bar being edge-to-edge. I like the direction in general, assuming that we get broader adoption this might be a good thing. Do yo have a list of packages that need to undergo these changes prepared? If so, please share it. I'm asking for it, because it is related to my another point below 👇🏻 I'm reluctant to introduce any third party dependency, especially one with native code. PS: if we were able to rely on information from PS 2: the ideal situation would be, that such "centralized solution" would be upstreamed directly to |
afaik it's a JS only and lightweight dep that checks if the |
As Android 15+ (targetting SDK 15) doesn't allow opaque system bars and enforces apps to draw under, the library enforces edge-to-edge and actually don't allow switching back to opaque bars anymore (because it will be impossible in the future - same for setting bars background color) - it doesn't want to handle their visibility, it aligns with (future) Android enforced behaviour.
Not at all, this has no impact if
I understand, but there's currently no native code involved in the PR, it just detect if another package is installed. Note that as there's no way to properly detect if If in the future, edge-to-edge is officially part of RN core,
Currently: react-native-bootsplash (it's mine, so it's a bit easy). For splash screen, edge-to-edge wide support is really important, because since Android 12 and SplashScreen API the system shows your splash screen before app start, and this one is edge-to-edge, so if your app isn't, a jump happen. Bootsplash solves this with expo-splash-screen is adopting this API too to finally get rid of these irritating issues - for that the app needs to be edge-to-edge too. react-native-keyboard-controller, a widely used replacement for As you can see, there's multiple good indications that Google wants edge-to-edge by default (enforced on Android 12+, enforced on splash screen, requires to use modern APIs…) Note that a few other libraries are currently in the work ( On the framework side, and as I've been commissioned by Expo to work on this, I think it's a matter of time until this is available directly in it (at first, opt-in, then opt-out) Finally, we are also bringing edge-to-edge to RN core Modal. Meta team is aware of this, they actually asked me to open the PR (and they already recommend the library to deal with the issue). Let me know if you have further questions! |
I see, makes even more sense now.
Yeah, I've missed the difference between
It would be good to upstream it to core at some point, definitely. I see your point though. Thank you for detailed explanation! I'm leaning towards accepting this change, but need some more time to think this through (maybe we want to go more radically and get rid of some future-scope from this library entirely). |
@kkafar If it helps take a decision, a new library added support: react-native-bottom-tabs (which plays nice with |
@kkafar FYI, we continue pushing for edge-to-edge support. The react native team just merged edge-to-edge for Modal into core. |
@zoontek I'm curious whether these also apply to React Native's |
@zoontek the other thing you mentioned here is that user needs to manually add these options until this PR is merged zoontek/react-native-edge-to-edge#45 (comment) But by default these values are |
@satya164 Yes, there's no need to set them, only to avoid that those are set to If those stay type Props = {
statusBarTranslucent?: boolean
}
// Here, defaulting to `false` breaks edge-to-edge, it's vicious
const MyComponent = ({ statusBarTranslucent = false }: Props) => {
return <Screen statusBarTranslucent={statusBarTranslucent} />
} This kind of issues are super hard to debug if you don't understand the topic perfectly, so a nightmare for users that only want to enable edge-to-edge and stop thinking about it. If
But there's still in the module some code that breaks edge-to-edge: we saw it with the To tackle the edge-to-edge issue, Meta team asked me for a proposal, it started here (very WIP). The idea is similar:
And of course, this PR takes care of fixing the StatusBar module behavior. Libraries relying on Fortunately, the list of libraries that are preparing themselves is growing fast:
I still need to open a PR on reanimated too (to set |
I think if edge-to-edge will be part of core, in addition to these, it'll be better to mark these props as deprecated as well so they can be removed entirely in the future. |
Note: List of resources is for future me 😅 I've familiarised myself with pretty much all the resources you guys linked:
Conclusions:the arguments made here are compelling. We'll proceed with merging this PR, after I'm done with testing (should be able to do this by the end of the week). My only concerns right now are Fabric-related, as there is no such thing as Another thing I want to address is handling of Summary for future me:Android enforces edge-to-edge for all apps with Having above ☝🏻 in mind we end up in following situation:
|
ec7e931
to
75467f4
Compare
@kkafar We could also update the code to be something like this: let {
// Filter out active prop in this case because it is unused and
// can cause problems depending on react-native version:
// https://github.com/react-navigation/react-navigation/issues/4886
active,
activityState,
children,
isNativeStack,
gestureResponseDistance,
onGestureCancel,
style,
...props
} = rest;
const {
// Filter out edge-to-edge related props
navigationBarColor,
navigationBarTranslucent,
statusBarColor,
statusBarTranslucent,
...edgeToEdgeCompatProps
} = props;
const transformedProps = EDGE_TO_EDGE
? {
...edgeToEdgeCompatProps,
statusBarTranslucent: true,
navigationBarTranslucent: true,
}
: props;
if (__DEV__) {
controlEdgeToEdgeValues({
navigationBarColor,
navigationBarTranslucent,
statusBarColor,
statusBarTranslucent,
});
}
// …
return (
<DelayedFreeze freeze={freezeOnBlur && activityState === 0}>
<AnimatedScreen
{...transformedProps} |
75467f4
to
7255d82
Compare
@kkafar @satya164 I rebased against main and updated the PR to avoid passing EDIT: After discussion with @satya164, he prefers enforcing them to |
Description
This follow a discussion started on the react-navigation repository.
Motivation
The future of Android is edge-to-edge, and to make the React Native developer experience seamless in this regard, the ecosystem needs to transition from “opaque system bars by default” to “edge-to-edge by default.”
To prevent library authors from implementing their own edge-to-edge solutions—which could interfere with other libraries—and because it’s not possible to reliably detect if edge-to-edge is already enabled on Android, we have collaborated with Expo to create a library that handles this functionality and is detectable using a simple helper:
react-native-is-edge-to-edge
.This approach allows you to bypass certain options and props (in this case,
Screen
statusBarTranslucent
,navigationBarTranslucent
,statusBarColor
andnavigationBarColor
- setting background color is deprecated). All are Android only props and are now obsolete / deprecated (at least, when running in edge-to-edge mode)Changes
react-native-is-edge-to-edge
to bypassstatusBarTranslucent
,navigationBarTranslucent
,statusBarColor
andnavigationBarColor
valuesTest code and steps to reproduce
react-navigation
to use local version ofreact-native-screens
.Warning
For the
StatusBar
example,react-native
headerTopInsetEnabled
might interfere whenstatusBarTranslucent
is explicitely set tofalse
, but the user will receive a warning inviting him to remove the option / prop, so that's acceptable.More
If you want to bypass some Kotlin code directly, consider this util:
Checklist