DocDoeAI / src /components /clean /shared /CleanCard.tsx
asnannp's picture
deploy: sync backend to Space root (learn-lesson HF cache fix)
65d68f5
Raw History Blame Contribute Delete
1.89 kB
"use client";
import { forwardRef } from "react";
import { cn } from "@/lib/utils";
// =============================================================================
// CleanCard — White card with subtle border, optional hover lift
// =============================================================================
export type CleanCardVariant = "default" | "outlined" | "elevated" | "ghost";
export interface CleanCardProps extends React.HTMLAttributes<HTMLDivElement> {
variant?: CleanCardVariant;
padding?: "none" | "sm" | "md" | "lg";
hoverable?: boolean;
}
const variantClasses: Record<CleanCardVariant, string> = {
default:
"bg-white border border-[#E4E6EC] shadow-[0_1px_2px_rgba(15,17,23,0.03),0_8px_24px_rgba(15,17,23,0.04)]",
outlined: "bg-white border border-[#E4E6EC]",
elevated:
"bg-white border border-[#EEF0F4] shadow-[0_4px_12px_rgba(15,17,23,0.05),0_16px_40px_-12px_rgba(15,17,23,0.1)]",
ghost: "bg-transparent",
};
const paddingClasses: Record<NonNullable<CleanCardProps["padding"]>, string> = {
none: "",
sm: "p-3",
md: "p-5",
lg: "p-6",
};
export const CleanCard = forwardRef<HTMLDivElement, CleanCardProps>(
({ variant = "default", padding = "md", hoverable = false, className, children, ...props }, ref) => {
return (
<div
ref={ref}
className={cn(
"rounded-xl transition-[transform,box-shadow,border-color] duration-150 ease-[cubic-bezier(0.23,1,0.32,1)]",
variantClasses[variant],
paddingClasses[padding],
hoverable &&
"cursor-pointer hover:-translate-y-0.5 hover:border-[#D4D7E0] hover:shadow-[0_2px_4px_rgba(15,17,23,0.04),0_14px_36px_rgba(15,17,23,0.08)] active:translate-y-0 active:scale-[0.995]",
className,
)}
{...props}
>
{children}
</div>
);
},
);
CleanCard.displayName = "CleanCard";