Group guest v2 fab controls
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

This commit is contained in:
Codex Agent
2026-02-03 21:56:07 +01:00
parent fbb6fd4404
commit b97f5de101
2 changed files with 64 additions and 33 deletions

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { YStack } from '@tamagui/stacks';
import { XStack, YStack } from '@tamagui/stacks';
import { Button } from '@tamagui/button';
import { Sparkles, Share2, Image, Camera, Settings, Home, Menu } from 'lucide-react';
import { useLocation, useNavigate } from 'react-router-dom';
@@ -34,6 +34,9 @@ export default function AppShell({ children }: AppShellProps) {
const matomoEnabled = typeof window !== 'undefined' && Boolean((window as any).__MATOMO_GUEST__?.enabled);
const isUploadRoute = /\/upload(?:\/|$)/.test(location.pathname);
const showFab = !/\/photo\/\d+/.test(location.pathname);
const dockBackground = isDark ? 'rgba(12, 16, 32, 0.72)' : 'rgba(255, 255, 255, 0.9)';
const dockBorder = isDark ? 'rgba(255,255,255,0.16)' : 'rgba(15,23,42,0.12)';
const dockShadow = isDark ? '0 14px 28px rgba(2, 6, 23, 0.5)' : '0 12px 24px rgba(15, 23, 42, 0.14)';
const goTo = (path: string) => () => {
setCompassOpen(false);
@@ -128,28 +131,7 @@ export default function AppShell({ children }: AppShellProps) {
{children}
</YStack>
{showFab ? (
<>
{isUploadRoute ? null : (
<Button
size="$3"
circular
position="fixed"
bottom={28}
left="calc(50% - 84px)"
zIndex={1100}
backgroundColor={isDark ? 'rgba(12, 16, 32, 0.75)' : 'rgba(255, 255, 255, 0.9)'}
borderWidth={1}
borderColor={isDark ? 'rgba(255,255,255,0.16)' : 'rgba(15,23,42,0.12)'}
onPress={goTo('/')}
style={{ boxShadow: isDark ? '0 10px 20px rgba(2, 6, 23, 0.45)' : '0 8px 16px rgba(15, 23, 42, 0.14)' }}
>
<Home size={16} color={actionIconColor} />
</Button>
)}
<FloatingActionButton
onPress={goTo('/upload')}
hidden={isUploadRoute}
/>
isUploadRoute ? (
<Button
size="$5"
circular
@@ -157,17 +139,61 @@ export default function AppShell({ children }: AppShellProps) {
bottom={28}
right={20}
zIndex={1100}
backgroundColor={isDark ? 'rgba(12, 16, 32, 0.75)' : 'rgba(255, 255, 255, 0.9)'}
backgroundColor={dockBackground}
borderWidth={1}
borderColor={isDark ? 'rgba(255,255,255,0.16)' : 'rgba(15,23,42,0.12)'}
borderColor={dockBorder}
width={72}
height={72}
onPress={openCompass}
style={{ boxShadow: isDark ? '0 10px 20px rgba(2, 6, 23, 0.45)' : '0 8px 16px rgba(15, 23, 42, 0.14)' }}
style={{ boxShadow: dockShadow }}
>
<Menu size={24} color={actionIconColor} />
</Button>
</>
) : (
<XStack
position="fixed"
bottom={24}
left="50%"
zIndex={1100}
alignItems="center"
gap="$2"
padding="$2"
borderRadius={999}
borderWidth={1}
borderColor={dockBorder}
backgroundColor={dockBackground}
style={{ transform: 'translateX(-50%)', boxShadow: dockShadow }}
>
<Button
size="$3"
circular
backgroundColor={isDark ? 'rgba(12, 16, 32, 0.75)' : 'rgba(255, 255, 255, 0.9)'}
borderWidth={1}
borderColor={dockBorder}
onPress={goTo('/')}
style={{ boxShadow: isDark ? '0 10px 20px rgba(2, 6, 23, 0.45)' : '0 8px 16px rgba(15, 23, 42, 0.14)' }}
>
<Home size={16} color={actionIconColor} />
</Button>
<FloatingActionButton
onPress={goTo('/upload')}
inline
/>
<Button
size="$5"
circular
backgroundColor={isDark ? 'rgba(12, 16, 32, 0.75)' : 'rgba(255, 255, 255, 0.9)'}
borderWidth={1}
borderColor={dockBorder}
width={72}
height={72}
onPress={openCompass}
style={{ boxShadow: isDark ? '0 10px 20px rgba(2, 6, 23, 0.45)' : '0 8px 16px rgba(15, 23, 42, 0.14)' }}
>
<Menu size={24} color={actionIconColor} />
</Button>
</XStack>
)
) : null}
<CompassHub
open={compassOpen}

View File

@@ -7,12 +7,17 @@ type FloatingActionButtonProps = {
onPress: () => void;
onLongPress?: () => void;
hidden?: boolean;
inline?: boolean;
};
export default function FloatingActionButton({ onPress, onLongPress, hidden = false }: FloatingActionButtonProps) {
export default function FloatingActionButton({ onPress, onLongPress, hidden = false, inline = false }: FloatingActionButtonProps) {
const longPressTriggered = React.useRef(false);
const { isDark } = useGuestThemeVariant();
const translateValue = hidden ? 'translateX(-50%) translateY(36px) scale(0.72)' : 'translateX(-50%)';
const translateValue = inline
? 'none'
: hidden
? 'translateX(-50%) translateY(36px) scale(0.72)'
: 'translateX(-50%)';
return (
<Button
@@ -33,9 +38,9 @@ export default function FloatingActionButton({ onPress, onLongPress, hidden = fa
longPressTriggered.current = true;
onLongPress();
}}
position="fixed"
bottom={20}
left="50%"
position={inline ? 'relative' : 'fixed'}
bottom={inline ? undefined : 20}
left={inline ? undefined : '50%'}
zIndex={1100}
width={68}
height={68}
@@ -51,7 +56,7 @@ export default function FloatingActionButton({ onPress, onLongPress, hidden = fa
pointerEvents={hidden ? 'none' : 'auto'}
style={{
transform: translateValue,
transition: 'transform 320ms cubic-bezier(0.22, 0.61, 0.36, 1), opacity 220ms ease',
transition: inline ? undefined : 'transform 320ms cubic-bezier(0.22, 0.61, 0.36, 1), opacity 220ms ease',
boxShadow: isDark
? '0 20px 40px rgba(255, 79, 216, 0.38), 0 0 0 8px rgba(255, 79, 216, 0.16)'
: '0 18px 32px rgba(15, 23, 42, 0.2), 0 0 0 8px rgba(255, 255, 255, 0.7)',