Files
gridpilot.gg/apps/website/components/sponsors/SponsorBenefitCard.tsx
2025-12-17 15:34:56 +01:00

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>
);
}