From 817efb0c0d49fee64f4cf7cdd639b354fbef2240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Musia=C5=82?= Date: Tue, 23 Jun 2026 13:14:33 +0200 Subject: [PATCH 1/2] Fix landscape mode scroll for ChangePolicyEducationalModal --- src/components/CenteredModalLayout.tsx | 22 ++++---------- .../index.native.tsx | 30 +++++++++++++++++++ .../CenteredModalLayoutOverlay/index.tsx | 14 +++++++++ .../CenteredModalLayoutOverlay/types.ts | 6 ++++ src/pages/ChangePolicyEducationalModal.tsx | 7 +++-- 5 files changed, 60 insertions(+), 19 deletions(-) create mode 100644 src/components/CenteredModalLayoutOverlay/index.native.tsx create mode 100644 src/components/CenteredModalLayoutOverlay/index.tsx create mode 100644 src/components/CenteredModalLayoutOverlay/types.ts diff --git a/src/components/CenteredModalLayout.tsx b/src/components/CenteredModalLayout.tsx index 97e3db9203da..170c2dba1ddb 100644 --- a/src/components/CenteredModalLayout.tsx +++ b/src/components/CenteredModalLayout.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import type {MouseEvent} from 'react'; import type {DimensionValue, StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; import useBottomSafeSafeAreaPaddingStyle from '@hooks/useBottomSafeSafeAreaPaddingStyle'; @@ -8,10 +7,9 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import isInLandscapeModeUtil from '@libs/isInLandscapeMode'; -import Overlay from '@libs/Navigation/AppNavigator/Navigators/Overlay'; import CONST from '@src/CONST'; +import CenteredModalLayoutOverlay from './CenteredModalLayoutOverlay'; import FocusTrapForScreen from './FocusTrap/FocusTrapForScreen'; -import PressableWithoutFeedback from './Pressable/PressableWithoutFeedback'; type CenteredModalLayoutProps = { children: React.ReactNode; @@ -42,27 +40,19 @@ function CenteredModalLayout({children, width, height, onBackdropPress, contentS useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.ESCAPE, onBackdropPress, {shouldBubble: false}); - const handleInnerClick = (e: MouseEvent) => e.stopPropagation(); - return ( <> - - + - true} - onClick={handleInnerClick} - style={styles.getCenteredModalInnerView(shouldUseNarrowLayout, width, height)} - > + {children} - + ); } diff --git a/src/components/CenteredModalLayoutOverlay/index.native.tsx b/src/components/CenteredModalLayoutOverlay/index.native.tsx new file mode 100644 index 000000000000..bf98af77f69a --- /dev/null +++ b/src/components/CenteredModalLayoutOverlay/index.native.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import CONST from '@src/CONST'; +import type CenteredModalLayoutOverlayProps from './types'; + +/** + * On native the navigation `Overlay` can't back the modal (it depends on `position: fixed`), + * so we render a plain full-screen Pressable behind the card. Tapping the area outside the + * card (which the centered card layer lets through via `pointerEvents="box-none"`) closes the modal. + */ +function CenteredModalLayoutOverlay({onBackdropPress}: CenteredModalLayoutOverlayProps) { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + + return ( + + ); +} + +export default CenteredModalLayoutOverlay; diff --git a/src/components/CenteredModalLayoutOverlay/index.tsx b/src/components/CenteredModalLayoutOverlay/index.tsx new file mode 100644 index 000000000000..a034c42bb664 --- /dev/null +++ b/src/components/CenteredModalLayoutOverlay/index.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import Overlay from '@libs/Navigation/AppNavigator/Navigators/Overlay'; +import type CenteredModalLayoutOverlayProps from './types'; + +/** + * On web the navigation `Overlay` is used as the backdrop: it provides the dimmed, + * animated layer tied to the card transition (it relies on `position: fixed`, which only + * works on web) and handles closing the modal when the area outside the card is pressed. + */ +function CenteredModalLayoutOverlay({onBackdropPress}: CenteredModalLayoutOverlayProps) { + return ; +} + +export default CenteredModalLayoutOverlay; diff --git a/src/components/CenteredModalLayoutOverlay/types.ts b/src/components/CenteredModalLayoutOverlay/types.ts new file mode 100644 index 000000000000..1b0aa08c4624 --- /dev/null +++ b/src/components/CenteredModalLayoutOverlay/types.ts @@ -0,0 +1,6 @@ +type CenteredModalLayoutOverlayProps = { + /** Called when the backdrop (area outside the card) is pressed, before navigating back */ + onBackdropPress: () => void; +}; + +export default CenteredModalLayoutOverlayProps; diff --git a/src/pages/ChangePolicyEducationalModal.tsx b/src/pages/ChangePolicyEducationalModal.tsx index 06add4582618..4dae17067358 100644 --- a/src/pages/ChangePolicyEducationalModal.tsx +++ b/src/pages/ChangePolicyEducationalModal.tsx @@ -3,18 +3,18 @@ import CenteredModalLayout from '@components/CenteredModalLayout'; import ChangeWorkspaceMenuSectionList from '@components/ChangeWorkspaceMenuSectionList'; import FeatureTrainingContent from '@components/FeatureTrainingContent'; import useBeforeRemove from '@hooks/useBeforeRemove'; -import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; +import { useMemoizedLazyIllustrations } from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; -import {dismissChangePolicyModal} from '@libs/actions/Report'; +import { dismissChangePolicyModal } from '@libs/actions/Report'; import Navigation from '@libs/Navigation/Navigation'; import colors from '@styles/theme/colors'; import variables from '@styles/variables'; import CONST from '@src/CONST'; function ChangePolicyEducationalModal() { - const {translate} = useLocalize(); + const { translate } = useLocalize(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const illustrations = useMemoizedLazyIllustrations(['ReceiptFairy']); @@ -33,6 +33,7 @@ function ChangePolicyEducationalModal() { Date: Tue, 23 Jun 2026 13:22:04 +0200 Subject: [PATCH 2/2] fix prettier --- src/components/CenteredModalLayoutOverlay/index.native.tsx | 6 +----- src/components/CenteredModalLayoutOverlay/index.tsx | 6 +----- src/pages/ChangePolicyEducationalModal.tsx | 6 +++--- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/components/CenteredModalLayoutOverlay/index.native.tsx b/src/components/CenteredModalLayoutOverlay/index.native.tsx index bf98af77f69a..0266492872f3 100644 --- a/src/components/CenteredModalLayoutOverlay/index.native.tsx +++ b/src/components/CenteredModalLayoutOverlay/index.native.tsx @@ -5,11 +5,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; import type CenteredModalLayoutOverlayProps from './types'; -/** - * On native the navigation `Overlay` can't back the modal (it depends on `position: fixed`), - * so we render a plain full-screen Pressable behind the card. Tapping the area outside the - * card (which the centered card layer lets through via `pointerEvents="box-none"`) closes the modal. - */ +/** On native the navigation `Overlay` can't back the modal, so we render a plain full-screen Pressable behind the card. */ function CenteredModalLayoutOverlay({onBackdropPress}: CenteredModalLayoutOverlayProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); diff --git a/src/components/CenteredModalLayoutOverlay/index.tsx b/src/components/CenteredModalLayoutOverlay/index.tsx index a034c42bb664..2ef488d9b8cf 100644 --- a/src/components/CenteredModalLayoutOverlay/index.tsx +++ b/src/components/CenteredModalLayoutOverlay/index.tsx @@ -2,11 +2,7 @@ import React from 'react'; import Overlay from '@libs/Navigation/AppNavigator/Navigators/Overlay'; import type CenteredModalLayoutOverlayProps from './types'; -/** - * On web the navigation `Overlay` is used as the backdrop: it provides the dimmed, - * animated layer tied to the card transition (it relies on `position: fixed`, which only - * works on web) and handles closing the modal when the area outside the card is pressed. - */ +/** On web the navigation `Overlay` is used as the backdrop. */ function CenteredModalLayoutOverlay({onBackdropPress}: CenteredModalLayoutOverlayProps) { return ; } diff --git a/src/pages/ChangePolicyEducationalModal.tsx b/src/pages/ChangePolicyEducationalModal.tsx index 4dae17067358..bc507a6c8136 100644 --- a/src/pages/ChangePolicyEducationalModal.tsx +++ b/src/pages/ChangePolicyEducationalModal.tsx @@ -3,18 +3,18 @@ import CenteredModalLayout from '@components/CenteredModalLayout'; import ChangeWorkspaceMenuSectionList from '@components/ChangeWorkspaceMenuSectionList'; import FeatureTrainingContent from '@components/FeatureTrainingContent'; import useBeforeRemove from '@hooks/useBeforeRemove'; -import { useMemoizedLazyIllustrations } from '@hooks/useLazyAsset'; +import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; -import { dismissChangePolicyModal } from '@libs/actions/Report'; +import {dismissChangePolicyModal} from '@libs/actions/Report'; import Navigation from '@libs/Navigation/Navigation'; import colors from '@styles/theme/colors'; import variables from '@styles/variables'; import CONST from '@src/CONST'; function ChangePolicyEducationalModal() { - const { translate } = useLocalize(); + const {translate} = useLocalize(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const illustrations = useMemoizedLazyIllustrations(['ReceiptFairy']);