97 lines
2.7 KiB
TypeScript
97 lines
2.7 KiB
TypeScript
'use client';
|
|
|
|
import { motion, useReducedMotion } from 'framer-motion';
|
|
import { ReactNode, useEffect, useState } from 'react';
|
|
import { LucideIcon } from 'lucide-react';
|
|
|
|
interface SponsorBenefitCardProps {
|
|
icon: LucideIcon;
|
|
title: string;
|
|
description: string;
|
|
stats?: {
|
|
value: string;
|
|
label: string;
|
|
};
|
|
variant?: 'default' | 'highlight';
|
|
delay?: number;
|
|
}
|
|
|
|
export default function SponsorBenefitCard({
|
|
icon: Icon,
|
|
title,
|
|
description,
|
|
stats,
|
|
variant = 'default',
|
|
delay = 0,
|
|
}: SponsorBenefitCardProps) {
|
|
const shouldReduceMotion = useReducedMotion();
|
|
const [isMounted, setIsMounted] = useState(false);
|
|
|
|
useEffect(() => {
|
|
setIsMounted(true);
|
|
}, []);
|
|
|
|
const isHighlight = variant === 'highlight';
|
|
|
|
const cardContent = (
|
|
<div
|
|
className={`
|
|
relative h-full rounded-xl p-6 transition-all duration-300
|
|
${isHighlight
|
|
? 'bg-gradient-to-br from-primary-blue/10 to-primary-blue/5 border border-primary-blue/30'
|
|
: 'bg-iron-gray/50 border border-charcoal-outline hover:border-charcoal-outline/80'
|
|
}
|
|
`}
|
|
>
|
|
{/* Icon */}
|
|
<div
|
|
className={`
|
|
w-12 h-12 rounded-xl flex items-center justify-center mb-4
|
|
${isHighlight
|
|
? 'bg-primary-blue/20'
|
|
: 'bg-iron-gray border border-charcoal-outline'
|
|
}
|
|
`}
|
|
>
|
|
<Icon className={`w-6 h-6 ${isHighlight ? 'text-primary-blue' : 'text-gray-400'}`} />
|
|
</div>
|
|
|
|
{/* Content */}
|
|
<h3 className="text-lg font-semibold text-white mb-2">{title}</h3>
|
|
<p className="text-sm text-gray-400 leading-relaxed">{description}</p>
|
|
|
|
{/* Stats */}
|
|
{stats && (
|
|
<div className="mt-4 pt-4 border-t border-charcoal-outline/50">
|
|
<div className="flex items-baseline gap-2">
|
|
<span className={`text-2xl font-bold ${isHighlight ? 'text-primary-blue' : 'text-white'}`}>
|
|
{stats.value}
|
|
</span>
|
|
<span className="text-sm text-gray-500">{stats.label}</span>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Highlight Glow Effect */}
|
|
{isHighlight && (
|
|
<div className="absolute -inset-px rounded-xl bg-gradient-to-br from-primary-blue/20 to-transparent opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none" />
|
|
)}
|
|
</div>
|
|
);
|
|
|
|
if (!isMounted || shouldReduceMotion) {
|
|
return <div className="group">{cardContent}</div>;
|
|
}
|
|
|
|
return (
|
|
<motion.div
|
|
className="group"
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.4, delay }}
|
|
whileHover={{ y: -4, transition: { duration: 0.2 } }}
|
|
>
|
|
{cardContent}
|
|
</motion.div>
|
|
);
|
|
} |