import React, { useEffect, useRef, useState } from "react"; import { motion, useAnimation } from "framer-motion"; import clsx from "clsx"; import MouseTracker from "../../MouseTracker"; // Import the MouseTracker component const HoverableSkillList = ({ title, items = [], // Default to an empty array to avoid undefined errors color = "red", hoveredItem, setHoveredItem, section, getKey, isVisible, }) => { const borderClass = `text-${color}-400`; const controls = useAnimation(); const skillLevelRefs = useRef([]); const [isMobile, setIsMobile] = useState(false); // Detect if the device is mobile useEffect(() => { const checkIsMobile = () => { setIsMobile(window.innerWidth <= 768); // Adjust breakpoint as needed }; checkIsMobile(); // Check on initial render window.addEventListener("resize", checkIsMobile); // Check on window resize return () => { window.removeEventListener("resize", checkIsMobile); // Cleanup }; }, []); useEffect(() => { if (isVisible) { controls.start((item) => { const circumference = 2 * Math.PI * 40; // Adjusted radius const skillLevel = parseInt( item.skill.split(": ")[1].split("/")[0], 10 ); return { strokeDashoffset: circumference - (skillLevel / 5) * circumference, transition: { duration: 1, ease: "easeInOut" }, }; }); } else { controls.set({ strokeDashoffset: 2 * Math.PI * 40 }); } }, [isVisible, controls]); // Check if the current item is hovered const isHovered = hoveredItem.section === section && hoveredItem.index !== null; return ( <div className="relative mx-auto text-center"> <h2 className={clsx("text-2xl font-sans font-semibold mb-8", borderClass)} > {title} </h2> <div className="flex gap-3 flex-wrap justify-center"> {items.map((item, index) => { const circumference = 2 * Math.PI * 40; return ( <div key={getKey(item, index)} className="relative flex flex-col items-center mb-2 group" onMouseEnter={() => !isMobile && setHoveredItem({ section, index }) } onMouseLeave={() => !isMobile && setHoveredItem({ section: null, index: null }) } onClick={() => isMobile && setHoveredItem({ section, index })} > <div className="relative w-[70px] h-[70px] sm:w-[70px] sm:h-[70px] md:w-[80px] md:h-[80px] lg:w-[90px] lg:h-[90px]"> {" "} {/* Adjusted size for mobile */} <svg className="absolute top-0 left-0 w-full h-full transform -rotate-90" viewBox="0 0 100 100" > {/* Background Circle */} <circle cx="50" cy="50" r="40" fill="transparent" stroke="gray" strokeWidth="6" strokeDasharray={circumference} /> {/* Animated Progress Circle */} <motion.circle cx="50" cy="50" r="40" fill="transparent" stroke="currentColor" strokeWidth="7" strokeDasharray={circumference} initial={{ strokeDashoffset: circumference }} animate={controls} custom={item} className={clsx(borderClass, "transition-all duration-300")} /> </svg> {/* Icon */} <motion.img alt={item.name} src={item.logo} className={clsx( "p-2 w-[60px] h-[60px] sm:w-[70px] sm:h-[70px] rounded-full transition-all duration-100 absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2", isHovered && hoveredItem.index === index && "shadow-[0_0_50px_rgba(255,255,255,0.9)]" )} /> </div> <p className="mt-2 text-base text-white">{item.name}</p> {/* Inline Tooltip for Mobile */} {isMobile && isHovered && hoveredItem.index === index && ( <div className="absolute bottom-full mb-2 bg-black text-white text-sm font-bold rounded-md px-8 py-3 shadow-lg"> {item.skill} </div> )} </div> ); })} </div> {/* MouseTracker for Desktop Tooltip */} {!isMobile && isHovered && ( <MouseTracker text={items[hoveredItem.index].skill} /> )} </div> ); }; export default HoverableSkillList;