11import React , { useCallback , useContext , useEffect , useMemo , useRef , useState } from 'react' ;
2- import type { LayoutChangeEvent } from 'react-native' ;
2+ import type { GestureResponderEvent , LayoutChangeEvent } from 'react-native' ;
33// Animated required for side panel navigation
44// eslint-disable-next-line no-restricted-imports
55import { Animated , View } from 'react-native' ;
66import ColorSchemeWrapper from '@components/ColorSchemeWrapper' ;
77import NavigationBar from '@components/NavigationBar' ;
8+ import { PressableWithoutFeedback } from '@components/Pressable' ;
89import ScreenWrapperOfflineIndicatorContext from '@components/ScreenWrapper/ScreenWrapperOfflineIndicatorContext' ;
910import ScrollView from '@components/ScrollView' ;
1011import useKeyboardState from '@hooks/useKeyboardState' ;
12+ import useLocalize from '@hooks/useLocalize' ;
1113import usePrevious from '@hooks/usePrevious' ;
1214import useResponsiveLayout from '@hooks/useResponsiveLayout' ;
1315import useSafeAreaInsets from '@hooks/useSafeAreaInsets' ;
@@ -78,6 +80,7 @@ function BaseModal({
7880 const theme = useTheme ( ) ;
7981 const styles = useThemeStyles ( ) ;
8082 const StyleUtils = useStyleUtils ( ) ;
83+ const { translate} = useLocalize ( ) ;
8184 const { windowWidth, windowHeight} = useWindowDimensions ( ) ;
8285 // We need to use isSmallScreenWidth instead of shouldUseNarrowLayout to apply correct modal width
8386 const canUseTouchScreen = canUseTouchScreenCheck ( ) ;
@@ -95,6 +98,7 @@ function BaseModal({
9598
9699 const shouldCallHideModalOnUnmount = useRef ( false ) ;
97100 const hideModalCallbackRef = useRef < ( callHideCallback : boolean ) => void > ( undefined ) ;
101+ const bottomDockedDismissButtonRef = useRef < View > ( null ) ;
98102
99103 const wasVisible = usePrevious ( isVisible ) ;
100104
@@ -177,8 +181,8 @@ function BaseModal({
177181 onModalShow ( ) ;
178182 } , [ onModalShow , shouldSetModalVisibility , type ] ) ;
179183
180- const handleBackdropPress = ( e ?: KeyboardEvent ) => {
181- if ( e ? .key === CONST . KEYBOARD_SHORTCUTS . ENTER . shortcutKey ) {
184+ const handleBackdropPress = ( e ?: GestureResponderEvent | KeyboardEvent ) => {
185+ if ( e && 'key' in e && e . key === CONST . KEYBOARD_SHORTCUTS . ENTER . shortcutKey ) {
182186 return ;
183187 }
184188
@@ -311,6 +315,8 @@ function BaseModal({
311315 const isBottomDockedModalInLandscapeMode = type === CONST . MODAL . MODAL_TYPE . BOTTOM_DOCKED && isInLandscapeMode ;
312316
313317 const shouldWrapChildrenInScrollView = shouldWrapModalChildrenInScrollViewIfBottomDockedInLandscapeMode && isBottomDockedModalInLandscapeMode ;
318+ const shouldShowBottomDockedDismissButton = isSmallScreenWidth && type === CONST . MODAL . MODAL_TYPE . BOTTOM_DOCKED && ! ! ( onBackdropPress ?? onClose ) ;
319+ const modalInitialFocus = shouldShowBottomDockedDismissButton ? ( ) => bottomDockedDismissButtonRef . current : initialFocus ;
314320
315321 return (
316322 < ModalContext . Provider value = { modalContextValue } >
@@ -348,7 +354,7 @@ function BaseModal({
348354 onSwipeComplete = { onClose }
349355 swipeDirection = { swipeDirection }
350356 shouldPreventScrollOnFocus = { shouldPreventScrollOnFocus }
351- initialFocus = { initialFocus }
357+ initialFocus = { modalInitialFocus }
352358 swipeThreshold = { swipeThreshold }
353359 isVisible = { isVisible }
354360 backdropColor = { theme . overlay }
@@ -389,6 +395,19 @@ function BaseModal({
389395 ref = { ref }
390396 fsClass = { forwardedFSClass }
391397 >
398+ { shouldShowBottomDockedDismissButton && (
399+ < PressableWithoutFeedback
400+ ref = { bottomDockedDismissButtonRef }
401+ onPress = { handleBackdropPress }
402+ role = { CONST . ROLE . BUTTON }
403+ accessibilityRole = { CONST . ROLE . BUTTON }
404+ accessibilityLabel = { translate ( 'common.dismiss' ) }
405+ sentryLabel = { CONST . SENTRY_LABEL . MODAL . DISMISS_DIALOG }
406+ style = { styles . bottomDockedModalDismissButton }
407+ >
408+ < View />
409+ </ PressableWithoutFeedback >
410+ ) }
392411 < ColorSchemeWrapper > { shouldWrapChildrenInScrollView ? < ScrollView > { children } </ ScrollView > : children } </ ColorSchemeWrapper >
393412 </ Animated . View >
394413 { ! keyboardStateContextValue ?. isKeyboardActive && < NavigationBar /> }
0 commit comments