Files
gridpilot.gg/apps/website/components/mockups/TeamCompetitionMockup.tsx
2025-12-02 19:44:18 +01:00

275 lines
12 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { motion, useReducedMotion } from 'framer-motion';
import { useState, useEffect } from 'react';
export default function TeamCompetitionMockup() {
const shouldReduceMotion = useReducedMotion();
const [hoveredDriver, setHoveredDriver] = useState<number | null>(null);
const [hoveredTeam, setHoveredTeam] = useState<number | null>(null);
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
setIsMobile(window.innerWidth < 768);
}, []);
const teamColors = ['#198CFF', '#6FE37A', '#FFC556', '#43C9E6', '#9333EA'];
if (isMobile) {
return (
<div className="relative w-full h-full bg-gradient-to-br from-deep-graphite via-iron-gray to-deep-graphite rounded-lg p-3 overflow-hidden">
<div className="space-y-4">
<div>
<div className="text-sm font-semibold text-white mb-3">Drivers</div>
<div className="space-y-2">
{[1, 2, 3].map((i) => (
<div
key={i}
className="relative flex items-center gap-2 bg-iron-gray rounded-lg p-2 border border-charcoal-outline overflow-hidden"
>
<div
className="absolute left-0 top-0 bottom-0 w-1"
style={{ backgroundColor: teamColors[i-1] }}
/>
<div
className="h-5 w-5 rounded-full flex items-center justify-center font-semibold text-xs border-2"
style={{
borderColor: teamColors[i-1],
backgroundColor: `${teamColors[i-1]}20`
}}
>
<span className="text-white">{i}</span>
</div>
<div className="h-6 w-6 rounded-full flex items-center justify-center text-sm" style={{ backgroundColor: `${teamColors[i-1]}20`, borderWidth: '1px', borderColor: teamColors[i-1] }}>
🏎
</div>
<div className="flex-1">
<div className="h-2.5 w-full bg-white/10 rounded"></div>
</div>
<div className="h-3 w-10 bg-charcoal-outline rounded text-xs flex items-center justify-center text-white/70"></div>
</div>
))}
</div>
</div>
<div className="h-px bg-gradient-to-r from-transparent via-charcoal-outline to-transparent" />
<div>
<div className="text-sm font-semibold text-white mb-3">Constructors</div>
<div className="space-y-2">
{[1, 2, 3].map((i) => (
<div
key={i}
className="relative flex items-center gap-2 bg-iron-gray rounded-lg p-2 border border-charcoal-outline overflow-hidden"
>
<div
className="absolute left-0 top-0 bottom-0 w-1"
style={{ backgroundColor: teamColors[i-1] }}
/>
<div
className="h-6 w-6 rounded flex items-center justify-center text-sm border-2"
style={{
borderColor: teamColors[i-1],
backgroundColor: `${teamColors[i-1]}20`
}}
>
🏁
</div>
<div className="flex-1">
<div className="h-2.5 w-full bg-white/10 rounded mb-1"></div>
<div className="relative h-1.5 bg-charcoal-outline rounded-full overflow-hidden">
<div
className="absolute inset-y-0 left-0 rounded-full"
style={{ backgroundColor: teamColors[i-1], width: `${100 - (i-1) * 15}%` }}
/>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</div>
);
}
const leftColumnVariants = {
hidden: { opacity: 0, x: shouldReduceMotion ? 0 : -20 },
visible: {
opacity: 1,
x: 0,
transition: {
type: 'spring' as const,
stiffness: 100,
damping: 20
}
}
};
const rightColumnVariants = {
hidden: { opacity: 0, x: shouldReduceMotion ? 0 : 20 },
visible: {
opacity: 1,
x: 0,
transition: {
type: 'spring' as const,
stiffness: 100,
damping: 20
}
}
};
const rowVariants = {
hidden: { opacity: 0, scale: shouldReduceMotion ? 1 : 0.95 },
visible: (i: number) => ({
opacity: 1,
scale: 1,
transition: {
delay: shouldReduceMotion ? 0 : 0.3 + i * 0.05,
type: 'spring' as const,
stiffness: 300,
damping: 25
}
})
};
return (
<div className="relative w-full h-full bg-gradient-to-br from-deep-graphite via-iron-gray to-deep-graphite rounded-lg p-1.5 sm:p-3 md:p-4 lg:p-6 overflow-hidden">
<div className="grid grid-cols-2 gap-2 sm:gap-3 md:gap-4 lg:gap-6 h-full">
<motion.div
variants={leftColumnVariants}
initial="hidden"
animate="visible"
className="relative"
>
<div className="h-3 sm:h-4 md:h-5 w-16 sm:w-20 md:w-24 bg-white/10 rounded mb-1.5 sm:mb-2 md:mb-3 lg:mb-4 text-[8px] sm:text-[10px] md:text-xs flex items-center justify-center text-white font-semibold">
Drivers
</div>
<div className="space-y-1 sm:space-y-1.5 md:space-y-2">
{[1, 2, 3, 4, 5].map((i) => (
<motion.div
key={i}
custom={i}
variants={rowVariants}
initial="hidden"
animate="visible"
className="relative flex items-center gap-1.5 sm:gap-2 md:gap-2.5 lg:gap-3 bg-iron-gray rounded-lg p-1 sm:p-1.5 md:p-2 lg:p-2.5 border border-charcoal-outline overflow-hidden"
onHoverStart={() => !shouldReduceMotion && setHoveredDriver(i)}
onHoverEnd={() => setHoveredDriver(null)}
whileHover={shouldReduceMotion ? {} : {
scale: 1.02,
boxShadow: `0 0 20px ${teamColors[i-1]}40`,
transition: { duration: 0.15 }
}}
>
<div
className="absolute left-0 top-0 bottom-0 w-0.5"
style={{ backgroundColor: teamColors[i-1] }}
/>
<div
className="h-3.5 w-3.5 sm:h-4 sm:w-4 md:h-5 md:w-5 rounded-full flex items-center justify-center font-semibold text-[8px] sm:text-[9px] md:text-[10px] border-2"
style={{
borderColor: teamColors[i-1],
backgroundColor: `${teamColors[i-1]}20`
}}
>
<span className="text-white">{i}</span>
</div>
<div className="h-5 w-5 sm:h-6 sm:w-6 md:h-7 md:w-7 rounded-full flex items-center justify-center text-[10px] sm:text-xs" style={{ backgroundColor: `${teamColors[i-1]}20`, borderWidth: '1px', borderColor: teamColors[i-1] }}>
🏎
</div>
<div className="flex-1 min-w-0">
<div className="h-1.5 sm:h-2 md:h-2.5 w-full bg-white/10 rounded"></div>
</div>
<div className="h-2 sm:h-2.5 md:h-3 w-8 sm:w-10 md:w-12 bg-charcoal-outline rounded font-mono text-[8px] sm:text-[9px] md:text-[10px] flex items-center justify-center text-white/70"></div>
{hoveredDriver === i && (
<motion.div
className="absolute inset-0 pointer-events-none"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
style={{
background: `linear-gradient(90deg, ${teamColors[i-1]}10 0%, transparent 100%)`
}}
/>
)}
</motion.div>
))}
</div>
</motion.div>
<div className="absolute left-1/2 top-8 bottom-8 w-px bg-gradient-to-b from-transparent via-charcoal-outline to-transparent backdrop-blur-sm" />
<motion.div
variants={rightColumnVariants}
initial="hidden"
animate="visible"
className="relative"
>
<div className="h-3 sm:h-4 md:h-5 w-20 sm:w-24 md:w-32 bg-white/10 rounded mb-1.5 sm:mb-2 md:mb-3 lg:mb-4 text-[8px] sm:text-[10px] md:text-xs flex items-center justify-center text-white font-semibold">
Constructors
</div>
<div className="space-y-1 sm:space-y-1.5 md:space-y-2">
{[1, 2, 3, 4, 5].map((i) => (
<motion.div
key={i}
custom={i}
variants={rowVariants}
initial="hidden"
animate="visible"
className="relative flex items-center gap-1.5 sm:gap-2 md:gap-2.5 lg:gap-3 bg-iron-gray rounded-lg p-1 sm:p-1.5 md:p-2 lg:p-2.5 border border-charcoal-outline overflow-hidden"
onHoverStart={() => !shouldReduceMotion && setHoveredTeam(i)}
onHoverEnd={() => setHoveredTeam(null)}
whileHover={shouldReduceMotion ? {} : {
scale: 1.02,
boxShadow: `0 0 20px ${teamColors[i-1]}40`,
transition: { duration: 0.15 }
}}
>
<div
className="absolute left-0 top-0 bottom-0 w-0.5"
style={{ backgroundColor: teamColors[i-1] }}
/>
<div
className="h-5 w-5 sm:h-6 sm:w-6 md:h-7 md:w-7 rounded flex items-center justify-center text-[10px] sm:text-xs md:text-sm border-2"
style={{
borderColor: teamColors[i-1],
backgroundColor: `${teamColors[i-1]}20`
}}
>
🏁
</div>
<div className="flex-1 min-w-0">
<div className="h-1.5 sm:h-2 md:h-2.5 w-full bg-white/10 rounded mb-0.5 sm:mb-1 md:mb-1.5"></div>
<div className="relative h-0.5 sm:h-1 md:h-1.5 bg-charcoal-outline rounded-full overflow-hidden">
<motion.div
className="absolute inset-y-0 left-0 rounded-full"
style={{ backgroundColor: teamColors[i-1] }}
initial={{ width: '0%' }}
animate={{ width: `${100 - (i-1) * 15}%` }}
transition={{ duration: shouldReduceMotion ? 0 : 0.8, delay: 0.4 + i * 0.05 }}
/>
</div>
</div>
{i === 3 && (
<div className="h-3 sm:h-3.5 md:h-4 px-0.5 sm:px-1 md:px-1.5 bg-warning-amber/20 rounded text-[7px] sm:text-[8px] md:text-[9px] flex items-center justify-center text-warning-amber font-semibold border border-warning-amber/30">
=
</div>
)}
{hoveredTeam === i && (
<motion.div
className="absolute inset-0 pointer-events-none"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
style={{
background: `linear-gradient(90deg, ${teamColors[i-1]}10 0%, transparent 100%)`
}}
/>
)}
</motion.div>
))}
</div>
</motion.div>
</div>
</div>
);
}