diff --git a/apps/mobile/src/components/ui/MenuPopup.android.tsx b/apps/mobile/src/components/ui/MenuPopup.android.tsx index 0237e3edf17aa..66a398bc21a81 100644 --- a/apps/mobile/src/components/ui/MenuPopup.android.tsx +++ b/apps/mobile/src/components/ui/MenuPopup.android.tsx @@ -8,7 +8,7 @@ import { Text, } from "@expo/ui/jetpack-compose"; import { defaultMinSize, padding, size, width } from "@expo/ui/jetpack-compose/modifiers"; -import { View } from "react-native"; +import { Pressable } from "react-native"; import { resolveScaledTextRole } from "../../lib/appearancePreferences"; import { useAndroidControlSizing } from "./useAndroidControlSizing"; @@ -16,15 +16,23 @@ import { useAppearancePreferences } from "../../features/settings/appearance/App import type { MenuPopupProps } from "./MenuPopup"; import { isAppSymbolName, SymbolView, type AppSymbolName } from "./AppSymbol"; +// The glyph is a React Native view hosted in the Compose row, and its native host consumes +// every touch over it, so the row's onClick never sees a tap on the icon. The glyph runs the +// row's action itself; the row stays the accessible element. function MenuIcon(props: { readonly name: AppSymbolName; + readonly onPress: () => void; readonly destructive?: boolean; readonly disabled?: boolean; }) { const { iconSize } = useAndroidControlSizing(); return ( - @@ -40,7 +48,7 @@ function MenuIcon(props: { : "accent-foreground" } /> - + ); } @@ -60,7 +68,7 @@ export function MenuPopup(props: MenuPopupProps) { {props.parent ? ( - + @@ -88,6 +96,7 @@ export function MenuPopup(props: MenuPopupProps) { props.onPress(action)} destructive={action.attributes?.destructive} disabled={action.attributes?.disabled} /> @@ -116,11 +125,19 @@ export function MenuPopup(props: MenuPopupProps) { {(action.subactions?.length ?? 0) > 0 ? ( - + props.onPress(action)} + disabled={action.attributes?.disabled} + /> ) : action.state === "on" ? ( - + props.onPress(action)} + disabled={action.attributes?.disabled} + /> ) : null}