Files
fotospiel-app/resources/js/guest-v2/components/FabActionRing.tsx
2026-02-03 15:18:44 +01:00

94 lines
2.9 KiB
TypeScript

import React from 'react';
import { YStack, XStack } from '@tamagui/stacks';
import { Button } from '@tamagui/button';
import { SizableText as Text } from '@tamagui/text';
import { useGuestThemeVariant } from '../lib/guestTheme';
type FabAction = {
key: string;
label: string;
icon: React.ReactNode;
onPress?: () => void;
};
type FabActionRingProps = {
open: boolean;
onOpenChange: (open: boolean) => void;
actions: FabAction[];
};
const positions = [
{ x: 0, y: -120 },
{ x: -70, y: -100 },
{ x: -120, y: -24 },
{ x: -92, y: 52 },
];
export default function FabActionRing({ open, onOpenChange, actions }: FabActionRingProps) {
const { isDark } = useGuestThemeVariant();
const borderColor = isDark ? 'rgba(255,255,255,0.18)' : 'rgba(15, 23, 42, 0.12)';
const surfaceColor = isDark ? 'rgba(12, 16, 32, 0.92)' : 'rgba(255, 255, 255, 0.95)';
const textColor = isDark ? '#F8FAFF' : '#0F172A';
const shadow = isDark ? '0 16px 28px rgba(2, 6, 23, 0.55)' : '0 14px 24px rgba(15, 23, 42, 0.18)';
const ringActions = actions.slice(0, positions.length);
if (!open) return null;
return (
<YStack position="fixed" inset={0} zIndex={1090} pointerEvents="box-none">
<YStack
position="absolute"
inset={0}
backgroundColor={isDark ? 'rgba(2,6,23,0.5)' : 'rgba(15,23,42,0.2)'}
onPress={() => onOpenChange(false)}
/>
<YStack position="absolute" bottom={24} right={20} pointerEvents="box-none">
{ringActions.map((action, index) => {
const offset = positions[index];
return (
<XStack
key={action.key}
alignItems="center"
gap="$2"
position="absolute"
style={{
transform: `translate(${offset.x}px, ${offset.y}px)`,
opacity: open ? 1 : 0,
transition: 'transform 260ms ease, opacity 200ms ease',
}}
>
<Button
size="$3"
circular
backgroundColor={surfaceColor}
borderWidth={1}
borderColor={borderColor}
onPress={() => {
onOpenChange(false);
action.onPress?.();
}}
style={{ boxShadow: shadow }}
>
{action.icon}
</Button>
<XStack
paddingHorizontal="$3"
paddingVertical="$2"
borderRadius="$pill"
backgroundColor={surfaceColor}
borderWidth={1}
borderColor={borderColor}
style={{ boxShadow: shadow }}
>
<Text fontSize="$2" fontWeight="$6" color={textColor}>
{action.label}
</Text>
</XStack>
</XStack>
);
})}
</YStack>
</YStack>
);
}