84 lines
2.6 KiB
TypeScript
84 lines
2.6 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;
|
|
/** Optional bottom offset so content sits above the bottom nav/safe-area. */
|
|
bottomOffsetPx?: number;
|
|
};
|
|
|
|
export function MobileSheet({ open, title, onClose, children, footer, 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={[82]}
|
|
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: '$4',
|
|
paddingBottom: '$7',
|
|
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="$3">
|
|
<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>
|
|
);
|
|
}
|