Files
core/src/shared/components/Card.js
T

110 lines
4.2 KiB
JavaScript

'use client';
import React from 'react';
const Card = ({
children,
title,
subtitle,
header,
footer,
variant = 'default',
padding = 'md',
hover = false,
spacing = 'md',
className = '',
...props
}) => {
const baseClassName = 'border transition-all duration-[120ms] ease-out';
const isLightDark = variant === 'lightDark';
const variants = {
default: 'rounded-xl bg-white dark:bg-[#0B0B0B] border-neutral-200 dark:border-[#1B1B1B]',
elevated: 'rounded-xl bg-neutral-50/80 dark:bg-neutral-900/40 border-neutral-200 dark:border-neutral-800/50',
outline: 'rounded-xl bg-transparent border-neutral-300 dark:border-neutral-700/50',
solid: 'rounded-xl bg-neutral-100 dark:bg-neutral-800 border-neutral-200 dark:border-neutral-700',
lightDark: 'rounded-xl bg-white dark:bg-neutral-900/40 border-neutral-200 dark:border-neutral-800/50',
success: 'rounded-xl bg-green-700/10 dark:bg-green-600/10 border-green-800/30 dark:border-green-600/20',
info: 'rounded-xl bg-blue-700/10 dark:bg-blue-600/10 border-blue-800/30 dark:border-blue-600/20',
warning: 'rounded-xl bg-yellow-700/10 dark:bg-yellow-600/10 border-yellow-800/30 dark:border-yellow-600/20',
danger: 'rounded-xl bg-red-700/10 dark:bg-red-600/10 border-red-800/30 dark:border-red-600/20'
};
const variantsHover = {
default: 'hover:bg-neutral-50 dark:hover:bg-neutral-800/40 hover:border-neutral-300 dark:hover:border-neutral-700/50',
elevated: 'hover:bg-neutral-100 dark:hover:bg-neutral-900/50 hover:border-neutral-300 dark:hover:border-neutral-700/50',
outline: 'hover:border-neutral-400 dark:hover:border-neutral-600/50',
solid: 'hover:bg-neutral-200 dark:hover:bg-neutral-700/80',
lightDark: 'hover:bg-neutral-50/90 hover:border-neutral-300/80 dark:hover:bg-neutral-900/50 dark:hover:border-neutral-700/50',
success: 'hover:bg-green-700/15 dark:hover:bg-green-600/15 hover:border-green-800/40 dark:hover:border-green-600/30',
info: 'hover:bg-blue-700/15 dark:hover:bg-blue-600/15 hover:border-blue-800/40 dark:hover:border-blue-600/30',
warning: 'hover:bg-yellow-700/15 dark:hover:bg-yellow-600/15 hover:border-yellow-800/40 dark:hover:border-yellow-600/30',
danger: 'hover:bg-red-700/15 dark:hover:bg-red-600/15 hover:border-red-800/40 dark:hover:border-red-600/30'
};
const paddings = {
none: '',
sm: 'p-4',
md: 'p-6',
lg: 'p-8'
};
const spacings = {
none: '',
sm: 'flex flex-col gap-2',
md: 'flex flex-col gap-4',
lg: 'flex flex-col gap-6'
};
const headerBorderClass = 'border-neutral-200 dark:border-[#1B1B1B]';
const footerBorderClass = 'border-neutral-200 dark:border-[#1B1B1B]';
const titleClass = 'text-sm font-medium text-neutral-900 dark:text-white';
const subtitleClass = 'text-xs text-neutral-500 dark:text-neutral-400 mt-1';
const CardHeader = () => {
if (header) return header;
if (!title && !subtitle) return null;
return (
<div className={`border-b ${headerBorderClass} pb-4 mb-6`}>
{title && (
<h3 className={titleClass}>
{title}
</h3>
)}
{subtitle && (
<p className={subtitleClass}>
{subtitle}
</p>
)}
</div>
);
};
const CardFooter = () => {
if (!footer) return null;
return (
<div className={`border-t ${footerBorderClass} pt-4 mt-6`}>
{footer}
</div>
);
};
return (
<div
className={`${baseClassName} ${variants[variant] || variants.default} ${hover ? (variantsHover[variant] || variantsHover.default) : ''} ${className}`}
{...props}
>
<div className={paddings[padding]}>
<CardHeader />
<div className={spacings[spacing]}>
{children}
</div>
<CardFooter />
</div>
</div>
);
};
export default Card;