mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Summary: The future of Android is [edge-to-edge](https://github.com/react-native-community/discussions-and-proposals/discussions/827) 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.” Currently, there's no easy way to have edge-to-edge modals, as they are implemented using `Dialog` instances (a separate `Window`) and only provide a `statusBarTranslucent` prop. I tried to implement it in [`react-native-edge-to-edge`](https://github.com/zoontek/react-native-edge-to-edge) by listening to the `topShow` `UIManager` event. But if it works well when there's a defined animation, we can see a quick jump when there's none, because there's too much delay before the event, and edge-to-edge cannot be applied quick enough to the dialog window. ### react-native-edge-to-edge implem with animation (no jump) https://github.com/user-attachments/assets/4933a102-87a5-40e4-98d9-47f8c0817592 ### react-native-edge-to-edge implem without animation (jump) https://github.com/user-attachments/assets/e4675589-08fe-44fe-b9d8-0a6b3552b461 --- For this reason, and because listening to event feels a bit hacky, I think it will be better to go for a new prop directly on RN Modal component: `navigationBarTranslucent` > [!NOTE] > `navigationBarTranslucent` cannot be used without `statusBarTranslucent`, as setting both enable edge-to-edge, like [AndroidX would do](https://github.com/androidx/androidx/blob/androidx-main/activity/activity/src/main/java/androidx/activity/EdgeToEdge.kt) and it would requires extra (and unecessary, given the direction Android is taking) work to find a way to keep the status bar opaque but the navigation bar transparent that work on Android 6 to 15+ ### Additional infos - Colors used for the buttons navigation bar in the PR are the default Android ones ([light](https://github.com/androidx/androidx/blob/androidx-main/activity/activity/src/main/java/androidx/activity/EdgeToEdge.kt#L37) and [dark](https://github.com/androidx/androidx/blob/androidx-main/activity/activity/src/main/java/androidx/activity/EdgeToEdge.kt#L42)) - Compared to the Google implementation, the light scrim is applied from `O_MR1` to `Q` (and not `O` to `Q`) as the [`android:windowLightNavigationBar`](https://developer.android.com/reference/android/R.attr#windowLightNavigationBar) style attribute is not available on `O` (it can only be applied programmatically on API 26). ## Changelog: [ANDROID] [ADDED] - Add navigationBarTranslucent prop to Modal component Pull Request resolved: https://github.com/facebook/react-native/pull/47254 Test Plan: Run the tester app, toggle `navigationBarTranslucent`: https://github.com/user-attachments/assets/286d173b-35a5-4951-9105-f9f7562d6764 ----- did some additional testing with RNTester using different justification |flex-start|flex-end| |https://pxl.cl/5Rd20|https://pxl.cl/5Rd21| Reviewed By: javache Differential Revision: D65103501 Pulled By: alanleedev fbshipit-source-id: ef6473ecd785976d3e26c77bbc212222ec96c9f2
117 lines
3.5 KiB
TypeScript
117 lines
3.5 KiB
TypeScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @format
|
|
*/
|
|
|
|
import type * as React from 'react';
|
|
import {ViewProps} from '../Components/View/ViewPropTypes';
|
|
import {NativeSyntheticEvent} from '../Types/CoreEventTypes';
|
|
import {ColorValue} from '../StyleSheet/StyleSheet';
|
|
|
|
export interface ModalBaseProps {
|
|
/**
|
|
* @deprecated Use animationType instead
|
|
*/
|
|
animated?: boolean | undefined;
|
|
/**
|
|
* The `animationType` prop controls how the modal animates.
|
|
*
|
|
* - `slide` slides in from the bottom
|
|
* - `fade` fades into view
|
|
* - `none` appears without an animation
|
|
*/
|
|
animationType?: 'none' | 'slide' | 'fade' | undefined;
|
|
/**
|
|
* The `transparent` prop determines whether your modal will fill the entire view.
|
|
* Setting this to `true` will render the modal over a transparent background.
|
|
*/
|
|
transparent?: boolean | undefined;
|
|
/**
|
|
* The `visible` prop determines whether your modal is visible.
|
|
*/
|
|
visible?: boolean | undefined;
|
|
/**
|
|
* The `onRequestClose` callback is called when the user taps the hardware back button on Android or the menu button on Apple TV.
|
|
*
|
|
* This is required on Apple TV and Android.
|
|
*/
|
|
onRequestClose?: ((event: NativeSyntheticEvent<any>) => void) | undefined;
|
|
/**
|
|
* The `onShow` prop allows passing a function that will be called once the modal has been shown.
|
|
*/
|
|
onShow?: ((event: NativeSyntheticEvent<any>) => void) | undefined;
|
|
|
|
/**
|
|
* The `backdropColor` props sets the background color of the modal's container.
|
|
* Defaults to `white` if not provided and transparent is `false`. Ignored if `transparent` is `true`.
|
|
*/
|
|
backdropColor?: ColorValue | undefined;
|
|
}
|
|
|
|
export interface ModalPropsIOS {
|
|
/**
|
|
* The `presentationStyle` determines the style of modal to show
|
|
*/
|
|
presentationStyle?:
|
|
| 'fullScreen'
|
|
| 'pageSheet'
|
|
| 'formSheet'
|
|
| 'overFullScreen'
|
|
| undefined;
|
|
|
|
/**
|
|
* The `supportedOrientations` prop allows the modal to be rotated to any of the specified orientations.
|
|
* On iOS, the modal is still restricted by what's specified in your app's Info.plist's UISupportedInterfaceOrientations field.
|
|
*/
|
|
supportedOrientations?:
|
|
| Array<
|
|
| 'portrait'
|
|
| 'portrait-upside-down'
|
|
| 'landscape'
|
|
| 'landscape-left'
|
|
| 'landscape-right'
|
|
>
|
|
| undefined;
|
|
|
|
/**
|
|
* The `onDismiss` prop allows passing a function that will be called once the modal has been dismissed.
|
|
*/
|
|
onDismiss?: (() => void) | undefined;
|
|
|
|
/**
|
|
* The `onOrientationChange` callback is called when the orientation changes while the modal is being displayed.
|
|
* The orientation provided is only 'portrait' or 'landscape'. This callback is also called on initial render, regardless of the current orientation.
|
|
*/
|
|
onOrientationChange?:
|
|
| ((event: NativeSyntheticEvent<any>) => void)
|
|
| undefined;
|
|
}
|
|
|
|
export interface ModalPropsAndroid {
|
|
/**
|
|
* Controls whether to force hardware acceleration for the underlying window.
|
|
*/
|
|
hardwareAccelerated?: boolean | undefined;
|
|
|
|
/**
|
|
* Determines whether your modal should go under the system statusbar.
|
|
*/
|
|
statusBarTranslucent?: boolean | undefined;
|
|
|
|
/**
|
|
* Determines whether your modal should go under the system navigationbar.
|
|
*/
|
|
navigationBarTranslucent?: boolean | undefined;
|
|
}
|
|
|
|
export type ModalProps = ModalBaseProps &
|
|
ModalPropsIOS &
|
|
ModalPropsAndroid &
|
|
ViewProps;
|
|
|
|
export class Modal extends React.Component<ModalProps> {}
|