100 lines
2.2 KiB
TypeScript
100 lines
2.2 KiB
TypeScript
import { Image as ImageIcon, Play } from 'lucide-react';
|
|
import { Box } from './Box';
|
|
import { Icon } from './Icon';
|
|
import { Image } from './Image';
|
|
import { Surface } from './Surface';
|
|
import { Text } from './Text';
|
|
|
|
interface MediaPreviewCardProps {
|
|
type: 'image' | 'video';
|
|
src: string;
|
|
alt: string;
|
|
title?: string;
|
|
subtitle?: string;
|
|
onClick?: () => void;
|
|
aspectRatio?: string;
|
|
isLoading?: boolean;
|
|
className?: string;
|
|
}
|
|
|
|
export function MediaPreviewCard({
|
|
type,
|
|
src,
|
|
alt,
|
|
title,
|
|
onClick,
|
|
aspectRatio = '16/9',
|
|
isLoading = false,
|
|
className = '',
|
|
}: MediaPreviewCardProps) {
|
|
return (
|
|
<Surface
|
|
variant="muted"
|
|
rounded="xl"
|
|
border
|
|
overflow="hidden"
|
|
cursor="pointer"
|
|
onClick={onClick}
|
|
group
|
|
className={className}
|
|
>
|
|
<Box position="relative" w="full" aspectRatio={aspectRatio}>
|
|
{isLoading ? (
|
|
<Box fullWidth fullHeight bg="bg-white/5" className="animate-pulse" />
|
|
) : (
|
|
<Image
|
|
src={src}
|
|
alt={alt}
|
|
fullWidth
|
|
fullHeight
|
|
className="object-cover"
|
|
/>
|
|
)}
|
|
|
|
{/* Overlay */}
|
|
<Box
|
|
position="absolute"
|
|
inset={0}
|
|
bg="bg-black/40"
|
|
display="flex"
|
|
center
|
|
opacity={0}
|
|
groupHoverOpacity={1}
|
|
transition="all 0.2s"
|
|
>
|
|
<Box
|
|
w="12"
|
|
h="12"
|
|
rounded="full"
|
|
bg="bg-white/20"
|
|
display="flex"
|
|
center
|
|
className="backdrop-blur-md"
|
|
>
|
|
<Icon
|
|
icon={type === 'video' ? Play : ImageIcon}
|
|
size={6}
|
|
color="white"
|
|
/>
|
|
</Box>
|
|
</Box>
|
|
|
|
{title && (
|
|
<Box
|
|
position="absolute"
|
|
bottom={0}
|
|
left={0}
|
|
right={0}
|
|
p={3}
|
|
bg="bg-gradient-to-t from-black/80 to-transparent"
|
|
>
|
|
<Text size="xs" weight="medium" color="text-white" truncate>
|
|
{title}
|
|
</Text>
|
|
</Box>
|
|
)}
|
|
</Box>
|
|
</Surface>
|
|
);
|
|
}
|