Files
gridpilot.gg/apps/website/ui/Card.tsx
2026-01-15 19:55:46 +01:00

62 lines
1.8 KiB
TypeScript

import React, { ReactNode, MouseEventHandler } from 'react';
import { Box, BoxProps } from './Box';
type Spacing = 0 | 0.5 | 1 | 1.5 | 2 | 2.5 | 3 | 3.5 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 72 | 80 | 96;
interface ResponsiveSpacing {
base?: Spacing;
md?: Spacing;
lg?: Spacing;
}
interface CardProps extends Omit<BoxProps<'div'>, 'children' | 'className' | 'onClick'> {
children: ReactNode;
className?: string;
onClick?: MouseEventHandler<HTMLDivElement>;
variant?: 'default' | 'highlight';
p?: Spacing | ResponsiveSpacing;
px?: Spacing | ResponsiveSpacing;
py?: Spacing | ResponsiveSpacing;
pt?: Spacing | ResponsiveSpacing;
pb?: Spacing | ResponsiveSpacing;
pl?: Spacing | ResponsiveSpacing;
pr?: Spacing | ResponsiveSpacing;
}
export function Card({
children,
className = '',
onClick,
variant = 'default',
...props
}: CardProps) {
const baseClasses = 'rounded-lg shadow-card border duration-200';
const variantClasses = {
default: 'bg-iron-gray border-charcoal-outline',
highlight: 'bg-gradient-to-r from-blue-900/20 to-blue-700/10 border-blue-500/30'
};
const classes = [
baseClasses,
variantClasses[variant],
onClick ? 'cursor-pointer hover:scale-[1.02]' : '',
className
].filter(Boolean).join(' ');
// Default padding if none provided
const hasPadding = props.p !== undefined || props.px !== undefined || props.py !== undefined ||
props.pt !== undefined || props.pb !== undefined || props.pl !== undefined || props.pr !== undefined;
return (
<Box
className={classes}
onClick={onClick}
p={hasPadding ? undefined : 6}
{...props}
>
{children}
</Box>
);
}