-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Fix Screen Reader issue preventing bottom sheet from closing without selection #81536
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
Merged
arosiclair
merged 64 commits into
Expensify:main
from
marufsharifi:fix/a11y-bottomsheet-close-screen-reader
May 1, 2026
Merged
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 7fad995
added translation
marufsharifi 61b9e63
fixed for android web
marufsharifi c02c0a7
Fix CI lint/prettier and avoid perf test regression
marufsharifi 8cbc19c
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi fb1812f
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi df543ff
applied ai feedbacks
marufsharifi dc146b2
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi e800de4
fix(a11y): focus first menu item on open and add SR dismiss target fo…
marufsharifi f316c05
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi ce736f0
fixed to focus the first item of the bottom docked once opened in ios
marufsharifi 4f8b7aa
fixed on ios - web
marufsharifi 0752822
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi bc109f6
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi 86f5c30
fixed type and lint errors.
marufsharifi e6b75b3
Fix accessibility focus typing and lint issues
marufsharifi 671dc39
fix(a11y): delay iOS dismiss accessibility until menu item focus
marufsharifi 05e7161
fix(lint): replace deprecated runAfterInteractions usage
marufsharifi f0c6a50
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi 054369a
fix(a11y): gate iOS dismiss until first popover item focuses
marufsharifi 3788e8a
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi c4e129a
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi f6a1939
Refactor PopoverMenu focus handling; clarify bottom-docked dismiss a1…
marufsharifi 38e3c1a
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi 2d3bfbc
fix(a11y): focus first popover item before enabling dismiss on iOS
marufsharifi 1390a8e
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi 6fcf6db
refactor(a11y): remove redundant dismiss accessibility reset on popov…
marufsharifi ede169e
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi 675f047
refactor(a11y): remove redundant native iOS guard in BaseModal
marufsharifi e5014bd
refactor(a11y): simplify popover focus effect dependencies
marufsharifi 947c903
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi cccac98
fixed type failure.
marufsharifi e7e9437
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi 1c80329
fix(a11y): focus first FAB menu item when opening action menu
marufsharifi cd07d0b
fix(a11y): harden initial focus for FAB action menu on iOS
marufsharifi 508b5b6
format FAB popover menu with prettier
marufsharifi f49ee40
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi 56e1436
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi 255ffc0
refactor(a11y): extract bottom-docked dismiss accessibility hook
marufsharifi 30f8ef6
fix(lint): defer bottom-docked dismiss accessibility state updates
marufsharifi 1e01e11
fix(a11y): confirm first popover item focus before enabling dismiss o…
marufsharifi 530bbb1
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi 8645938
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi dbd323c
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi 3906aac
Fix accessibility focus for report filter popovers
marufsharifi 9cbb07e
fixed type error
marufsharifi 7e8d595
Fix lint and type
marufsharifi 17ddb20
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi 513496a
Scope iOS dismiss deferral to active bottom-docked popovers
marufsharifi 3db86d5
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi 6558f4e
Fix chat create popover accessibility focus on reopen
marufsharifi 1942369
fixed prettier
marufsharifi 72090cb
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi d111530
Unify filter modal accessibility handling into shared hook
marufsharifi b6fccb2
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi 30632cc
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi a162ea2
Fix accessibility focus for search display bottom sheets
marufsharifi 02c8d11
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi 00d9b65
Preserve search popup state across dropdown re-renders
marufsharifi b5a890a
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi f3974c3
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi 0df479f
fix(a11y): focus dismiss first in bottom-docked modals
marufsharifi f8a4b06
added DismissDialog to CONST
marufsharifi 89e5105
Merge branch 'main' into fix/a11y-bottomsheet-close-screen-reader
marufsharifi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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'; | ||
| import useLocalize from '@hooks/useLocalize'; | ||
| import usePrevious from '@hooks/usePrevious'; | ||
| import useResponsiveLayout from '@hooks/useResponsiveLayout'; | ||
| import useSafeAreaInsets from '@hooks/useSafeAreaInsets'; | ||
|
|
@@ -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(); | ||
|
|
@@ -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); | ||
|
|
||
|
|
@@ -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; | ||
| } | ||
|
|
||
|
|
@@ -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; | ||
|
marufsharifi marked this conversation as resolved.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| return ( | ||
| <ModalContext.Provider value={modalContextValue}> | ||
|
|
@@ -348,7 +354,7 @@ function BaseModal({ | |
| onSwipeComplete={onClose} | ||
| swipeDirection={swipeDirection} | ||
| shouldPreventScrollOnFocus={shouldPreventScrollOnFocus} | ||
| initialFocus={initialFocus} | ||
| initialFocus={modalInitialFocus} | ||
| swipeThreshold={swipeThreshold} | ||
| isVisible={isVisible} | ||
| backdropColor={theme.overlay} | ||
|
|
@@ -389,6 +395,19 @@ function BaseModal({ | |
| ref={ref} | ||
| fsClass={forwardedFSClass} | ||
| > | ||
| {shouldShowBottomDockedDismissButton && ( | ||
| <PressableWithoutFeedback | ||
| ref={bottomDockedDismissButtonRef} | ||
| onPress={handleBackdropPress} | ||
| role={CONST.ROLE.BUTTON} | ||
|
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 />} | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.