Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
932b5c9
fix(a11y): allow bottom sheet to close via screen reader without sele…
marufsharifi Feb 5, 2026
7fad995
added translation
marufsharifi Feb 5, 2026
61b9e63
fixed for android web
marufsharifi Feb 8, 2026
c02c0a7
Fix CI lint/prettier and avoid perf test regression
marufsharifi Feb 8, 2026
8cbc19c
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Feb 9, 2026
fb1812f
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Feb 13, 2026
df543ff
applied ai feedbacks
marufsharifi Feb 13, 2026
dc146b2
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Mar 4, 2026
e800de4
fix(a11y): focus first menu item on open and add SR dismiss target fo…
marufsharifi Mar 4, 2026
f316c05
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Mar 4, 2026
ce736f0
fixed to focus the first item of the bottom docked once opened in ios
marufsharifi Mar 4, 2026
4f8b7aa
fixed on ios - web
marufsharifi Mar 4, 2026
0752822
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Mar 5, 2026
bc109f6
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Mar 6, 2026
86f5c30
fixed type and lint errors.
marufsharifi Mar 6, 2026
e6b75b3
Fix accessibility focus typing and lint issues
marufsharifi Mar 6, 2026
671dc39
fix(a11y): delay iOS dismiss accessibility until menu item focus
marufsharifi Mar 6, 2026
05e7161
fix(lint): replace deprecated runAfterInteractions usage
marufsharifi Mar 7, 2026
f0c6a50
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Mar 7, 2026
054369a
fix(a11y): gate iOS dismiss until first popover item focuses
marufsharifi Mar 7, 2026
3788e8a
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Mar 12, 2026
c4e129a
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Mar 14, 2026
f6a1939
Refactor PopoverMenu focus handling; clarify bottom-docked dismiss a1…
marufsharifi Mar 14, 2026
38e3c1a
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Mar 15, 2026
2d3bfbc
fix(a11y): focus first popover item before enabling dismiss on iOS
marufsharifi Mar 15, 2026
1390a8e
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Mar 16, 2026
6fcf6db
refactor(a11y): remove redundant dismiss accessibility reset on popov…
marufsharifi Mar 16, 2026
ede169e
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Mar 17, 2026
675f047
refactor(a11y): remove redundant native iOS guard in BaseModal
marufsharifi Mar 17, 2026
e5014bd
refactor(a11y): simplify popover focus effect dependencies
marufsharifi Mar 17, 2026
947c903
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Mar 24, 2026
cccac98
fixed type failure.
marufsharifi Mar 24, 2026
e7e9437
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Mar 26, 2026
1c80329
fix(a11y): focus first FAB menu item when opening action menu
marufsharifi Mar 26, 2026
cd07d0b
fix(a11y): harden initial focus for FAB action menu on iOS
marufsharifi Mar 26, 2026
508b5b6
format FAB popover menu with prettier
marufsharifi Mar 26, 2026
f49ee40
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Mar 28, 2026
56e1436
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Mar 31, 2026
255ffc0
refactor(a11y): extract bottom-docked dismiss accessibility hook
marufsharifi Mar 31, 2026
30f8ef6
fix(lint): defer bottom-docked dismiss accessibility state updates
marufsharifi Mar 31, 2026
1e01e11
fix(a11y): confirm first popover item focus before enabling dismiss o…
marufsharifi Mar 31, 2026
530bbb1
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Apr 2, 2026
8645938
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Apr 4, 2026
dbd323c
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Apr 7, 2026
3906aac
Fix accessibility focus for report filter popovers
marufsharifi Apr 7, 2026
9cbb07e
fixed type error
marufsharifi Apr 7, 2026
7e8d595
Fix lint and type
marufsharifi Apr 8, 2026
17ddb20
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Apr 9, 2026
513496a
Scope iOS dismiss deferral to active bottom-docked popovers
marufsharifi Apr 9, 2026
3db86d5
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Apr 11, 2026
6558f4e
Fix chat create popover accessibility focus on reopen
marufsharifi Apr 11, 2026
1942369
fixed prettier
marufsharifi Apr 11, 2026
72090cb
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Apr 13, 2026
d111530
Unify filter modal accessibility handling into shared hook
marufsharifi Apr 13, 2026
b6fccb2
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Apr 19, 2026
30632cc
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Apr 19, 2026
a162ea2
Fix accessibility focus for search display bottom sheets
marufsharifi Apr 19, 2026
02c8d11
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Apr 22, 2026
00d9b65
Preserve search popup state across dropdown re-renders
marufsharifi Apr 22, 2026
b5a890a
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Apr 27, 2026
f3974c3
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Apr 27, 2026
0df479f
fix(a11y): focus dismiss first in bottom-docked modals
marufsharifi Apr 27, 2026
f8a4b06
added DismissDialog to CONST
marufsharifi Apr 28, 2026
89e5105
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi Apr 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8830,6 +8830,9 @@ const CONST = {
SEND_BUTTON: 'AttachmentModal-SendButton',
IMAGE_ZOOM: 'AttachmentModal-ImageZoom',
},
MODAL: {
DISMISS_DIALOG: 'Modal-DismissDialog',
},
ATTACHMENT_PREVIEW: {
VIDEO_THUMBNAIL: 'AttachmentPreview-VideoThumbnail',
IMAGE_THUMBNAIL: 'AttachmentPreview-ImageThumbnail',
Expand Down
27 changes: 23 additions & 4 deletions src/components/Modal/BaseModal.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import React, {useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
import type {LayoutChangeEvent} from 'react-native';
import type {GestureResponderEvent, LayoutChangeEvent} from 'react-native';
// Animated required for side panel navigation
// eslint-disable-next-line no-restricted-imports
import {Animated, View} from 'react-native';
import ColorSchemeWrapper from '@components/ColorSchemeWrapper';
import NavigationBar from '@components/NavigationBar';
import {PressableWithoutFeedback} from '@components/Pressable';
import ScreenWrapperOfflineIndicatorContext from '@components/ScreenWrapper/ScreenWrapperOfflineIndicatorContext';
import ScrollView from '@components/ScrollView';
import useKeyboardState from '@hooks/useKeyboardState';
Comment thread
marufsharifi marked this conversation as resolved.
import useLocalize from '@hooks/useLocalize';
import usePrevious from '@hooks/usePrevious';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useSafeAreaInsets from '@hooks/useSafeAreaInsets';
Expand Down Expand Up @@ -78,6 +80,7 @@ function BaseModal({
const theme = useTheme();
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const {translate} = useLocalize();
const {windowWidth, windowHeight} = useWindowDimensions();
// We need to use isSmallScreenWidth instead of shouldUseNarrowLayout to apply correct modal width
const canUseTouchScreen = canUseTouchScreenCheck();
Expand All @@ -95,6 +98,7 @@ function BaseModal({

const shouldCallHideModalOnUnmount = useRef(false);
const hideModalCallbackRef = useRef<(callHideCallback: boolean) => void>(undefined);
const bottomDockedDismissButtonRef = useRef<View>(null);

const wasVisible = usePrevious(isVisible);

Expand Down Expand Up @@ -177,8 +181,8 @@ function BaseModal({
onModalShow();
}, [onModalShow, shouldSetModalVisibility, type]);

const handleBackdropPress = (e?: KeyboardEvent) => {
if (e?.key === CONST.KEYBOARD_SHORTCUTS.ENTER.shortcutKey) {
const handleBackdropPress = (e?: GestureResponderEvent | KeyboardEvent) => {
if (e && 'key' in e && e.key === CONST.KEYBOARD_SHORTCUTS.ENTER.shortcutKey) {
return;
}

Expand Down Expand Up @@ -311,6 +315,8 @@ function BaseModal({
const isBottomDockedModalInLandscapeMode = type === CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED && isInLandscapeMode;

const shouldWrapChildrenInScrollView = shouldWrapModalChildrenInScrollViewIfBottomDockedInLandscapeMode && isBottomDockedModalInLandscapeMode;
const shouldShowBottomDockedDismissButton = isSmallScreenWidth && type === CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED && !!(onBackdropPress ?? onClose);
const modalInitialFocus = shouldShowBottomDockedDismissButton ? () => bottomDockedDismissButtonRef.current : initialFocus;
Comment thread
marufsharifi marked this conversation as resolved.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bottomDockedDismissButtonRef can be null when we open the modal and close it immediately, which crashes the app. (read the root cause here)


return (
<ModalContext.Provider value={modalContextValue}>
Expand Down Expand Up @@ -348,7 +354,7 @@ function BaseModal({
onSwipeComplete={onClose}
swipeDirection={swipeDirection}
shouldPreventScrollOnFocus={shouldPreventScrollOnFocus}
initialFocus={initialFocus}
initialFocus={modalInitialFocus}
swipeThreshold={swipeThreshold}
isVisible={isVisible}
backdropColor={theme.overlay}
Expand Down Expand Up @@ -389,6 +395,19 @@ function BaseModal({
ref={ref}
fsClass={forwardedFSClass}
>
{shouldShowBottomDockedDismissButton && (
<PressableWithoutFeedback
ref={bottomDockedDismissButtonRef}
onPress={handleBackdropPress}
role={CONST.ROLE.BUTTON}
Comment thread
marufsharifi marked this conversation as resolved.
accessibilityRole={CONST.ROLE.BUTTON}
accessibilityLabel={translate('common.dismiss')}
sentryLabel={CONST.SENTRY_LABEL.MODAL.DISMISS_DIALOG}
style={styles.bottomDockedModalDismissButton}
>
<View />
</PressableWithoutFeedback>
)}
<ColorSchemeWrapper>{shouldWrapChildrenInScrollView ? <ScrollView>{children}</ScrollView> : children}</ColorSchemeWrapper>
</Animated.View>
{!keyboardStateContextValue?.isKeyboardActive && <NavigationBar />}
Expand Down
10 changes: 10 additions & 0 deletions src/styles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3649,6 +3649,16 @@ const staticStyles = (theme: ThemeColors) =>
backgroundColor: theme.overlay,
},

bottomDockedModalDismissButton: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
height: variables.iconSizeXSmall,
backgroundColor: theme.transparent,
zIndex: 1,
},

invisibleOverlay: {
backgroundColor: theme.transparent,
zIndex: 1000,
Expand Down
Loading