117 lines
3.4 KiB
TypeScript
117 lines
3.4 KiB
TypeScript
"use client";
|
|
|
|
import React from "react";
|
|
import Image from "next/image";
|
|
import { motion } from "framer-motion";
|
|
import { CT, CP } from '@/components/Texts';
|
|
|
|
interface CubeProps {
|
|
title: string;
|
|
descriptionTitle: string;
|
|
description: string;
|
|
isActive: boolean;
|
|
index: number;
|
|
onHover: () => void;
|
|
onLeave: () => void;
|
|
}
|
|
|
|
|
|
export function Cube({ title, descriptionTitle, description, isActive, index, onHover, onLeave }: CubeProps) {
|
|
return (
|
|
<div className="relative flex flex-col items-center">
|
|
<motion.div
|
|
className="relative cursor-pointer pointer-events-none"
|
|
onMouseEnter={onHover}
|
|
onMouseLeave={onLeave}
|
|
style={{
|
|
zIndex: 10 - index,
|
|
}}
|
|
animate={{
|
|
scale: isActive ? 1.05 : 1,
|
|
}}
|
|
transition={{
|
|
duration: 0.3,
|
|
ease: "easeOut",
|
|
}}
|
|
>
|
|
{/* Image Cube */}
|
|
<Image
|
|
src="/images/cube.png"
|
|
alt="Cube"
|
|
width={507}
|
|
height={234}
|
|
className="w-60 sm:w-80 lg:w-96 h-auto drop-shadow-lg pointer-events-auto"
|
|
style={{
|
|
filter: isActive
|
|
? 'brightness(1.1) drop-shadow(0 25px 25px rgba(144, 137, 252, 0.4))'
|
|
: 'brightness(0.9) drop-shadow(0 10px 15px rgba(144, 137, 252, 0.2))',
|
|
}}
|
|
/>
|
|
|
|
{/* Title overlay */}
|
|
<div className="absolute inset-0 flex items-center justify-center">
|
|
<CT as="h3" className="px-4 drop-shadow-lg" style={{ transform: 'rotate(0deg) skewX(0deg)', transformOrigin: 'center' }}>
|
|
{title}
|
|
</CT>
|
|
</div>
|
|
|
|
{/* Description with arrow line - Desktop */}
|
|
{isActive && (
|
|
<motion.div
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
exit={{ opacity: 0 }}
|
|
transition={{ duration: 0.3 }}
|
|
className="hidden lg:block absolute left-full top-1/2 -translate-y-1/2 z-50"
|
|
>
|
|
{/* Arrow line */}
|
|
<svg
|
|
className="absolute left-0 top-1/2 -translate-y-1/2"
|
|
width="120"
|
|
height="2"
|
|
viewBox="0 0 120 2"
|
|
fill="none"
|
|
>
|
|
<line
|
|
x1="0"
|
|
y1="1"
|
|
x2="120"
|
|
y2="1"
|
|
stroke="currentColor"
|
|
strokeWidth="1"
|
|
opacity="0.6"
|
|
/>
|
|
</svg>
|
|
|
|
{/* Description text */}
|
|
<div className="ml-32 w-80 text-[#2F3178]">
|
|
<h4 className="text-base font-semibold mb-2">
|
|
{descriptionTitle}
|
|
</h4>
|
|
<CP>{description}</CP>
|
|
</div>
|
|
</motion.div>
|
|
)}
|
|
|
|
{/* Description for Mobile - Below cube */}
|
|
{isActive && (
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 10 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
exit={{ opacity: 0, y: 10 }}
|
|
transition={{ duration: 0.3 }}
|
|
className="lg:hidden absolute top-full left-1/2 -translate-x-1/2 mt-8 z-50"
|
|
>
|
|
<div className="w-64 sm:w-80 px-4 text-[#2F3178]">
|
|
<h4 className="text-base font-semibold mb-2 text-center">
|
|
{descriptionTitle}
|
|
</h4>
|
|
<CP className="text-center">{description}</CP>
|
|
</div>
|
|
</motion.div>
|
|
)}
|
|
</motion.div>
|
|
</div>
|
|
);
|
|
}
|