Files
gridpilot.gg/apps/website/ui/ImagePlaceholder.tsx
2026-01-19 12:35:16 +01:00

59 lines
1.5 KiB
TypeScript

import { AlertCircle, Image as ImageIcon, Loader2 } from 'lucide-react';
import { Box } from './Box';
import { Icon } from './Icon';
import { Text } from './Text';
export interface ImagePlaceholderProps {
width?: string | number;
height?: string | number;
animate?: 'pulse' | 'none' | 'spin';
aspectRatio?: string;
variant?: 'default' | 'loading' | 'error';
message?: string;
rounded?: string;
}
export const ImagePlaceholder = ({
width = '100%',
height = '100%',
animate = 'pulse',
aspectRatio,
variant = 'default',
message,
rounded
}: ImagePlaceholderProps) => {
const icons = {
default: ImageIcon,
loading: Loader2,
error: AlertCircle,
};
return (
<Box
width={width}
height={height}
aspectRatio={aspectRatio}
display="flex"
flexDirection="col"
alignItems="center"
justifyContent="center"
bg="var(--ui-color-bg-surface-muted)"
style={{ borderRadius: rounded === 'none' ? '0' : (rounded ? `var(--ui-radius-${rounded})` : 'var(--ui-radius-md)') }}
gap={2}
>
<Icon
icon={icons[variant]}
size={8}
intent="low"
animate={variant === 'loading' ? 'spin' : (animate === 'spin' ? 'spin' : 'none')}
className={animate === 'pulse' && variant !== 'loading' ? 'animate-pulse' : ''}
/>
{message && (
<Text size="xs" variant="low" align="center" paddingX={4}>
{message}
</Text>
)}
</Box>
);
};