49 lines
1.4 KiB
TypeScript
49 lines
1.4 KiB
TypeScript
'use client';
|
|
import React from 'react';
|
|
import { clsx } from 'clsx';
|
|
import { twMerge } from 'tailwind-merge';
|
|
|
|
export type CardVariant = 'default' | 'interactive' | 'elevated' | 'glowing';
|
|
|
|
export interface CardProps {
|
|
variant?: CardVariant;
|
|
children: React.ReactNode;
|
|
className?: string;
|
|
onClick?: React.MouseEventHandler<HTMLDivElement>;
|
|
}
|
|
|
|
const variantStyles: Record<CardVariant, string> = {
|
|
default: 'bg-gray-900 border border-gray-700',
|
|
interactive:
|
|
'bg-gray-900 border border-gray-700 cursor-pointer hover:scale-[1.02] hover:border-gray-600 hover:bg-gray-800/80 active:scale-[0.99]',
|
|
elevated:
|
|
'bg-gray-900 border border-gray-700 shadow-lg shadow-black/25',
|
|
glowing:
|
|
'bg-gray-900 border border-indigo-500/30 shadow-[0_0_20px_rgba(99,102,241,0.15)]',
|
|
};
|
|
|
|
export const Card = React.forwardRef<HTMLDivElement, CardProps>(
|
|
({ variant = 'default', children, className, onClick, ...props }, ref) => {
|
|
return (
|
|
<div
|
|
ref={ref}
|
|
onClick={onClick}
|
|
role={onClick ? 'button' : undefined}
|
|
tabIndex={onClick ? 0 : undefined}
|
|
className={twMerge(
|
|
clsx(
|
|
'rounded-2xl p-6 transition-all duration-200 ease-out',
|
|
variantStyles[variant],
|
|
),
|
|
className,
|
|
)}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</div>
|
|
);
|
|
},
|
|
);
|
|
|
|
Card.displayName = 'Card';
|