Files
fotospiel-app/resources/js/guest-v2/components/CompassHub.tsx
2026-02-02 13:01:20 +01:00

151 lines
4.0 KiB
TypeScript

import React from 'react';
import { Sheet } from '@tamagui/sheet';
import { YStack } from '@tamagui/stacks';
import { SizableText as Text } from '@tamagui/text';
import { Button } from '@tamagui/button';
import { useAppearance } from '@/hooks/use-appearance';
export type CompassAction = {
key: string;
label: string;
icon?: React.ReactNode;
onPress?: () => void;
};
type CompassHubProps = {
open: boolean;
onOpenChange: (open: boolean) => void;
quadrants: [CompassAction, CompassAction, CompassAction, CompassAction];
centerAction: CompassAction;
title?: string;
};
const quadrantPositions: Array<{
top?: number;
right?: number;
bottom?: number;
left?: number;
}> = [
{ top: 0, left: 0 },
{ top: 0, right: 0 },
{ bottom: 0, left: 0 },
{ bottom: 0, right: 0 },
];
export default function CompassHub({
open,
onOpenChange,
quadrants,
centerAction,
title = 'Quick jump',
}: CompassHubProps) {
const close = () => onOpenChange(false);
const { resolved } = useAppearance();
const isDark = resolved === 'dark';
if (!open) {
return null;
}
return (
<Sheet
modal
open={open}
onOpenChange={onOpenChange}
snapPoints={[100]}
snapPointsMode="percent"
dismissOnOverlayPress
dismissOnSnapToBottom
zIndex={100000}
>
<Sheet.Overlay
{...({
backgroundColor: isDark ? 'rgba(15, 23, 42, 0.55)' : 'rgba(15, 23, 42, 0.22)',
pointerEvents: 'auto',
onClick: close,
onMouseDown: close,
onTouchStart: close,
} as any)}
/>
<Sheet.Frame
{...({
width: '100%',
height: '100%',
alignSelf: 'center',
backgroundColor: 'transparent',
padding: 24,
pointerEvents: 'box-none',
} as any)}
>
<YStack
position="absolute"
top={0}
right={0}
bottom={0}
left={0}
pointerEvents="auto"
onPress={close}
onClick={close}
onTouchStart={close}
/>
<YStack flex={1} alignItems="center" justifyContent="center" gap="$3" pointerEvents="auto">
<Text fontSize="$5" fontFamily="$display" fontWeight="$8" color="$color">
{title}
</Text>
<YStack width={280} height={280} position="relative" className="guest-compass-flyin">
{quadrants.map((action, index) => (
<Button
key={action.key}
onPress={() => {
action.onPress?.();
close();
}}
width={120}
height={120}
borderRadius={24}
backgroundColor="$surface"
borderWidth={1}
borderColor="$borderColor"
position="absolute"
{...quadrantPositions[index]}
>
<YStack alignItems="center" gap="$2">
{action.icon}
<Text fontSize="$3" fontWeight="$7">
{action.label}
</Text>
</YStack>
</Button>
))}
<Button
onPress={() => {
centerAction.onPress?.();
close();
}}
width={90}
height={90}
borderRadius={45}
backgroundColor="$primary"
position="absolute"
top="50%"
left="50%"
style={{ transform: 'translate(-45px, -45px)' }}
>
<YStack alignItems="center" gap="$1">
{centerAction.icon}
<Text fontSize="$2" fontWeight="$7" color="white">
{centerAction.label}
</Text>
</YStack>
</Button>
</YStack>
<Text fontSize="$2" color="$color" opacity={0.6}>
Tap outside to close
</Text>
</YStack>
</Sheet.Frame>
</Sheet>
);
}