71 lines
2.3 KiB
TypeScript
71 lines
2.3 KiB
TypeScript
"use client";
|
|
|
|
import * as React from "react"
|
|
import Image from "next/image"
|
|
import { m } from "framer-motion";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
/* ── Base Card ── */
|
|
interface CardProps {
|
|
children: React.ReactNode;
|
|
hover?: boolean;
|
|
glass?: boolean;
|
|
className?: string;
|
|
}
|
|
|
|
export function Card({ children, hover = true, glass = false, className }: CardProps) {
|
|
return (
|
|
<m.div
|
|
whileHover={hover ? { y: -6 } : undefined}
|
|
transition={{ duration: 0.35, ease: [0.16, 1, 0.3, 1] }}
|
|
className={cn(
|
|
"rounded-2xl overflow-hidden transition-shadow duration-300",
|
|
glass
|
|
? "bg-white/10 backdrop-blur-md border border-white/20"
|
|
: "bg-white border border-gray-100 shadow-[var(--shadow-sm)] hover:shadow-[var(--shadow-lg)]",
|
|
className
|
|
)}
|
|
>
|
|
{children}
|
|
</m.div>
|
|
);
|
|
}
|
|
|
|
/* ── Image Card ── */
|
|
interface ImageCardProps {
|
|
src: string;
|
|
alt: string;
|
|
title: string;
|
|
subtitle?: string;
|
|
badge?: string;
|
|
className?: string;
|
|
}
|
|
|
|
export function ImageCard({ src, alt, title, subtitle, badge, className }: ImageCardProps) {
|
|
return (
|
|
<Card className={cn("group cursor-pointer", className)}>
|
|
<div className="relative h-64 overflow-hidden">
|
|
<Image
|
|
src={src}
|
|
alt={alt}
|
|
fill
|
|
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
|
className="object-cover transition-transform duration-700 group-hover:scale-105"
|
|
/>
|
|
<div className="absolute inset-0 bg-gradient-to-t from-black/50 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-400" />
|
|
{badge && (
|
|
<span className="absolute top-4 left-4 text-[10px] uppercase tracking-[0.18em] font-semibold px-3 py-1 bg-[var(--color-moy-gold)] text-[var(--color-moy-dark)] rounded-full">
|
|
{badge}
|
|
</span>
|
|
)}
|
|
</div>
|
|
<div className="p-6 border-t-[1.5px] border-transparent group-hover:border-[var(--color-moy-gold)] transition-[border-color] duration-300">
|
|
<h3 className="text-xl font-serif text-[var(--color-moy-dark)] mb-2 leading-snug">{title}</h3>
|
|
{subtitle && (
|
|
<p className="text-sm text-gray-500 leading-relaxed">{subtitle}</p>
|
|
)}
|
|
</div>
|
|
</Card>
|
|
);
|
|
}
|