76 lines
2.2 KiB
TypeScript
76 lines
2.2 KiB
TypeScript
// components/PortfolioProjectOverview.tsx
|
|
import { motion } from "framer-motion";
|
|
import { ReactNode } from "react";
|
|
|
|
interface PortfolioProjectOverviewProps {
|
|
icon: ReactNode;
|
|
title: string;
|
|
description?: string;
|
|
points?: string[];
|
|
borderColor?: string;
|
|
hoverColor?: string;
|
|
}
|
|
|
|
export function PortfolioProjectOverview({
|
|
icon,
|
|
title,
|
|
description,
|
|
points,
|
|
borderColor = "border-accent/20",
|
|
hoverColor = "accent",
|
|
}: PortfolioProjectOverviewProps) {
|
|
return (
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
whileHover={{
|
|
scale: 1.05,
|
|
y: -4,
|
|
transition: { duration: 0.3, ease: "easeOut" },
|
|
}}
|
|
transition={{ duration: 0.6 }}
|
|
viewport={{ once: true }}
|
|
className={`bg-card/30 rounded-2xl p-8 border-2 ${borderColor} cursor-pointer group
|
|
hover:border-${hoverColor}/40 hover:bg-card/40
|
|
hover:shadow-lg hover:shadow-${hoverColor}/10
|
|
transition-all duration-300 ease-out`}
|
|
>
|
|
{/* Icon */}
|
|
<motion.div
|
|
initial={{ opacity: 0, scale: 0.8 }}
|
|
whileInView={{ opacity: 1, scale: 1 }}
|
|
transition={{ duration: 0.6, delay: 0.2 }}
|
|
viewport={{ once: true }}
|
|
className="flex justify-start mb-6"
|
|
>
|
|
<div
|
|
className={`w-16 h-16 bg-background/20 backdrop-blur-sm rounded-full
|
|
border border-border/30 flex items-center justify-center
|
|
group-hover:border-${hoverColor}/50 group-hover:bg-${hoverColor}/10
|
|
transition-all duration-300 ease-out`}
|
|
>
|
|
{icon}
|
|
</div>
|
|
</motion.div>
|
|
|
|
{/* Title */}
|
|
<h3 className="text-2xl font-semibold text-foreground mb-6">{title}</h3>
|
|
|
|
{/* Content */}
|
|
{description && (
|
|
<p className="text-muted-foreground leading-relaxed">{description}</p>
|
|
)}
|
|
{points && (
|
|
<div className="space-y-3">
|
|
{points.map((point, i) => (
|
|
<div key={i} className="flex items-start gap-3">
|
|
<span className="w-5 h-5 text-accent mt-0.5 flex-shrink-0">✔</span>
|
|
<span className="text-muted-foreground text-base">{point}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</motion.div>
|
|
);
|
|
}
|