mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-10-15 19:45:42 -04:00
fix(native): let Android menus open from their trigger
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
5 files changed
+56
-17
No files matched your search
@@ -46,6 +46,7 @@ import { SettingsRow } from "@/components/settings/settings-row";
|
||||
import { SettingsSection } from "@/components/settings/settings-section";
|
||||
import { TmdbLogo } from "@/components/tmdb-logo";
|
||||
import { Image } from "@/components/ui/image";
|
||||
import { MenuTrigger } from "@/components/ui/menu-trigger";
|
||||
import { ScaledIcon } from "@/components/ui/scaled-icon";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
@@ -285,8 +286,7 @@ export default function SettingsScreen() {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
<MenuTrigger
|
||||
accessibilityLabel={t`Edit profile photo`}
|
||||
accessibilityHint={t`Opens options to change or remove your photo`}
|
||||
className="mr-3"
|
||||
@@ -308,7 +308,7 @@ export default function SettingsScreen() {
|
||||
<View className="bg-primary absolute right-0 bottom-0 size-[18px] items-center justify-center rounded-full">
|
||||
<IconCamera size={10} color={primaryFgColor} />
|
||||
</View>
|
||||
</Pressable>
|
||||
</MenuTrigger>
|
||||
</MenuView>
|
||||
) : (
|
||||
<Pressable
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { MenuView } from "@expo/ui/community/menu";
|
||||
import { useLingui } from "@lingui/react/macro";
|
||||
import type { Icon } from "@tabler/icons-react-native";
|
||||
import { Pressable, View } from "react-native";
|
||||
import { View } from "react-native";
|
||||
|
||||
import { MenuTrigger } from "@/components/ui/menu-trigger";
|
||||
import { ScaledIcon } from "@/components/ui/scaled-icon";
|
||||
import { Sparkline } from "@/components/ui/sparkline";
|
||||
import { Text } from "@/components/ui/text";
|
||||
@@ -96,13 +97,11 @@ export function StatsCard(props: StatsCardProps) {
|
||||
const nextPeriod = periods.find((value) => value === nativeEvent.event);
|
||||
if (nextPeriod) onPeriodChange(nextPeriod);
|
||||
}}
|
||||
onOpenMenu={() => Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light)}
|
||||
>
|
||||
<Pressable
|
||||
onPress={() => Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light)}
|
||||
accessibilityRole="button"
|
||||
>
|
||||
<MenuTrigger onPress={() => Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light)}>
|
||||
<CardInner {...props} />
|
||||
</Pressable>
|
||||
</MenuTrigger>
|
||||
</MenuView>
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -2,9 +2,10 @@ import { Icon } from "@expo/ui";
|
||||
import { MenuView } from "@expo/ui/community/menu";
|
||||
import { useLingui } from "@lingui/react/macro";
|
||||
import { useRouter } from "expo-router";
|
||||
import { Alert, Pressable, View } from "react-native";
|
||||
import { Alert, View } from "react-native";
|
||||
|
||||
import { Image } from "@/components/ui/image";
|
||||
import { MenuTrigger } from "@/components/ui/menu-trigger";
|
||||
import { Text } from "@/components/ui/text";
|
||||
import { queryClient } from "@/lib/query-client";
|
||||
import { authClient } from "@/lib/server";
|
||||
@@ -58,10 +59,10 @@ export function HeaderAvatar() {
|
||||
]);
|
||||
}
|
||||
}}
|
||||
onOpenMenu={() => Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light)}
|
||||
>
|
||||
<Pressable
|
||||
<MenuTrigger
|
||||
onPress={() => Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light)}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={t`User menu`}
|
||||
hitSlop={8}
|
||||
>
|
||||
@@ -84,7 +85,7 @@ export function HeaderAvatar() {
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</Pressable>
|
||||
</MenuTrigger>
|
||||
</MenuView>
|
||||
);
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import { MenuView } from "@expo/ui/community/menu";
|
||||
import { useLingui } from "@lingui/react/macro";
|
||||
import { IconArrowsSort } from "@tabler/icons-react-native";
|
||||
import { Pressable } from "react-native";
|
||||
import { useCSSVariable } from "uniwind";
|
||||
|
||||
import { MenuTrigger } from "@/components/ui/menu-trigger";
|
||||
import { ScaledIcon } from "@/components/ui/scaled-icon";
|
||||
import * as Haptics from "@/utils/haptics";
|
||||
|
||||
@@ -49,15 +49,15 @@ export function SortMenu({ sortBy, sortDirection, onSortChange }: SortMenuProps)
|
||||
);
|
||||
if (option) onSortChange(option.sortBy, option.sortDirection);
|
||||
}}
|
||||
onOpenMenu={() => Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light)}
|
||||
>
|
||||
<Pressable
|
||||
<MenuTrigger
|
||||
onPress={() => Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light)}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={t`Sort`}
|
||||
hitSlop={8}
|
||||
>
|
||||
<ScaledIcon icon={IconArrowsSort} size={22} color={foregroundColor} />
|
||||
</Pressable>
|
||||
</MenuTrigger>
|
||||
</MenuView>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import type { ReactNode } from "react";
|
||||
import { Pressable, type PressableProps, View } from "react-native";
|
||||
|
||||
type MenuTriggerProps = Pick<
|
||||
PressableProps,
|
||||
| "onPress"
|
||||
| "hitSlop"
|
||||
| "accessibilityLabel"
|
||||
| "accessibilityHint"
|
||||
| "accessibilityRole"
|
||||
| "className"
|
||||
> & {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Child for `MenuView`. On Android, MenuView opens from its own wrapping Pressable, so the
|
||||
* trigger must not be touchable (an inner Pressable would swallow the tap). On iOS the SwiftUI
|
||||
* Menu handles the tap natively, so keep a Pressable for press feedback.
|
||||
*/
|
||||
export function MenuTrigger({ children, onPress, hitSlop, ...a11y }: MenuTriggerProps) {
|
||||
if (process.env.EXPO_OS === "android") {
|
||||
return (
|
||||
<View accessible {...a11y} accessibilityRole={a11y.accessibilityRole ?? "button"}>
|
||||
{children}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Pressable
|
||||
onPress={onPress}
|
||||
hitSlop={hitSlop}
|
||||
{...a11y}
|
||||
accessibilityRole={a11y.accessibilityRole ?? "button"}
|
||||
>
|
||||
{children}
|
||||
</Pressable>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user