Files
fotospiel-app/resources/js/admin/mobile/components/Sheet.tsx
Codex Agent 3de1d3deab
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled
Misc unrelated updates
2026-01-12 10:31:31 +01:00

99 lines
2.8 KiB
TypeScript

import React from 'react';
import { YStack, XStack } from '@tamagui/stacks';
import { SizableText as Text } from '@tamagui/text';
import { Pressable } from '@tamagui/react-native-web-lite';
import { Sheet } from '@tamagui/sheet';
import { useTranslation } from 'react-i18next';
import { useAdminTheme } from '../theme';
type SheetProps = {
open: boolean;
title: string;
onClose: () => void;
children: React.ReactNode;
footer?: React.ReactNode;
snapPoints?: number[];
contentSpacing?: string;
padding?: string;
paddingBottom?: string;
/** Optional bottom offset so content sits above the bottom nav/safe-area. */
bottomOffsetPx?: number;
};
export function MobileSheet({
open,
title,
onClose,
children,
footer,
snapPoints = [82],
contentSpacing = '$3',
padding = '$4',
paddingBottom = '$7',
bottomOffsetPx = 88,
}: SheetProps) {
const { t } = useTranslation('mobile');
const { surface, textStrong, muted, overlay, shadow, border } = useAdminTheme();
const bottomOffset = `max(env(safe-area-inset-bottom, 0px), ${bottomOffsetPx}px)`;
if (!open) {
return null;
}
return (
<Sheet
modal
open={open}
onOpenChange={(next: boolean) => {
if (!next) {
onClose();
}
}}
snapPoints={snapPoints}
snapPointsMode="percent"
dismissOnOverlayPress
dismissOnSnapToBottom
zIndex={100000}
>
<Sheet.Overlay {...({ backgroundColor: `${overlay}66` } as any)} />
<Sheet.Frame
{...({
width: '100%',
maxWidth: 520,
alignSelf: 'center',
borderTopLeftRadius: 24,
borderTopRightRadius: 24,
backgroundColor: surface,
padding,
paddingBottom,
shadowColor: shadow,
shadowOpacity: 0.12,
shadowRadius: 18,
shadowOffset: { width: 0, height: -8 },
} as any)}
style={{ marginBottom: bottomOffset }}
>
<Sheet.Handle height={5} width={48} backgroundColor={border} borderRadius={999} marginBottom="$3" />
<Sheet.ScrollView
showsVerticalScrollIndicator={false}
{...({ contentContainerStyle: { paddingBottom: 6 } } as any)}
>
<YStack space={contentSpacing}>
<XStack alignItems="center" justifyContent="space-between">
<Text fontSize="$md" fontWeight="800" color={textStrong}>
{title}
</Text>
<Pressable onPress={onClose}>
<Text fontSize="$md" color={muted}>
{t('actions.close', 'Close')}
</Text>
</Pressable>
</XStack>
{children}
{footer ? footer : null}
</YStack>
</Sheet.ScrollView>
</Sheet.Frame>
</Sheet>
);
}