|
1 | 1 | import type {ImageContentFit} from 'expo-image'; |
2 | 2 | import type {ReactElement, ReactNode, Ref} from 'react'; |
3 | | -import React, {useMemo, useRef} from 'react'; |
| 3 | +import React, {useEffect, useMemo, useRef} from 'react'; |
4 | 4 | import type {GestureResponderEvent, Role, StyleProp, TextStyle, ViewStyle} from 'react-native'; |
5 | 5 | import {View} from 'react-native'; |
6 | 6 | import type {ValueOf} from 'type-fest'; |
@@ -618,6 +618,18 @@ function MenuItem({ |
618 | 618 | const {isExecuting} = useMenuItemGroupState() ?? {}; |
619 | 619 | const {singleExecution, waitForNavigate} = useMenuItemGroupActions() ?? {}; |
620 | 620 | const popoverAnchor = useRef<View>(null); |
| 621 | + const pressableRef = useRef<View>(null); |
| 622 | + useEffect(() => { |
| 623 | + const element = pressableRef.current; |
| 624 | + if (interactive || !element || typeof HTMLElement === 'undefined' || !(element instanceof HTMLElement) || typeof element.onclick === 'undefined') { |
| 625 | + return; |
| 626 | + } |
| 627 | + // React Native Web's Pressable always attaches an onClick handler to the DOM element. |
| 628 | + // TalkBack on Android web uses the presence of a click event listener to determine whether |
| 629 | + // an element is clickable and announces "double tap to activate" even for non-interactive elements. |
| 630 | + // Removing the onclick property prevents TalkBack from treating the element as clickable. |
| 631 | + element.onclick = null; |
| 632 | + }, [interactive]); |
621 | 633 | const deviceHasHoverSupport = hasHoverSupport(); |
622 | 634 | const isCompactMenu = useIsCompactMenu(); |
623 | 635 | const isCompactPopoverItem = isCompactMenu && !isSmallScreenWidth && !shouldIgnoreCompactStyle; |
@@ -861,7 +873,7 @@ function MenuItem({ |
861 | 873 | } |
862 | 874 | disabledStyle={shouldUseDefaultCursorWhenDisabled && [styles.cursorDefault]} |
863 | 875 | disabled={disabled || isExecuting} |
864 | | - ref={mergeRefs(ref, popoverAnchor)} |
| 876 | + ref={mergeRefs(ref, popoverAnchor, pressableRef)} |
865 | 877 | role={interactive ? role : undefined} |
866 | 878 | accessibilityLabel={accessibilityLabelWithContextMenuHint} |
867 | 879 | accessibilityHint={accessibilityHint} |
@@ -1122,7 +1134,7 @@ function MenuItem({ |
1122 | 1134 | </View> |
1123 | 1135 | )} |
1124 | 1136 | {!!brickRoadIndicator && ( |
1125 | | - <View style={[styles.alignItemsCenter, styles.justifyContentCenter, styles.ml1, styles.mr2]}> |
| 1137 | + <View style={[styles.alignItemsCenter, styles.justifyContentCenter, styles.ml1, badgeText ? undefined : styles.mr2]}> |
1126 | 1138 | <Icon |
1127 | 1139 | src={icons.DotIndicator} |
1128 | 1140 | fill={brickRoadIndicator === CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR ? theme.danger : theme.success} |
|
0 commit comments