102 lines
3.4 KiB
TypeScript
102 lines
3.4 KiB
TypeScript
"use client"
|
|
|
|
import { useState, useRef, useEffect } from "react"
|
|
|
|
const tabs = ["Новинки", "Коллекции", "Популярное"]
|
|
|
|
interface TabSelectorProps {
|
|
onTabChange: (index: number) => void;
|
|
}
|
|
|
|
export default function TabSelector({ onTabChange }: TabSelectorProps) {
|
|
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null)
|
|
const [activeIndex, setActiveIndex] = useState(0)
|
|
const [hoverStyle, setHoverStyle] = useState({})
|
|
const [activeStyle, setActiveStyle] = useState({ left: "0px", width: "0px" })
|
|
const tabRefs = useRef<(HTMLDivElement | null)[]>([])
|
|
|
|
useEffect(() => {
|
|
if (hoveredIndex !== null) {
|
|
const hoveredElement = tabRefs.current[hoveredIndex]
|
|
if (hoveredElement) {
|
|
const { offsetLeft, offsetWidth } = hoveredElement
|
|
setHoverStyle({
|
|
left: `${offsetLeft}px`,
|
|
width: `${offsetWidth}px`,
|
|
})
|
|
}
|
|
}
|
|
}, [hoveredIndex])
|
|
|
|
useEffect(() => {
|
|
const activeElement = tabRefs.current[activeIndex]
|
|
if (activeElement) {
|
|
const { offsetLeft, offsetWidth } = activeElement
|
|
setActiveStyle({
|
|
left: `${offsetLeft}px`,
|
|
width: `${offsetWidth}px`,
|
|
})
|
|
}
|
|
|
|
// Вызываем функцию обратного вызова при изменении активного таба
|
|
onTabChange(activeIndex);
|
|
}, [activeIndex, onTabChange])
|
|
|
|
useEffect(() => {
|
|
requestAnimationFrame(() => {
|
|
const firstElement = tabRefs.current[0]
|
|
if (firstElement) {
|
|
const { offsetLeft, offsetWidth } = firstElement
|
|
setActiveStyle({
|
|
left: `${offsetLeft}px`,
|
|
width: `${offsetWidth}px`,
|
|
})
|
|
}
|
|
})
|
|
}, [])
|
|
|
|
return (
|
|
<div className="flex justify-center items-center w-full py-8 bg-white">
|
|
<div className="w-full max-w-[1200px] h-[60px] relative flex items-center justify-center">
|
|
<div className="p-0">
|
|
<div className="relative">
|
|
{/* Hover Highlight */}
|
|
<div
|
|
className="absolute h-[30px] transition-all duration-300 ease-out bg-[#63823B]/20 rounded-[6px] flex items-center"
|
|
style={{
|
|
...hoverStyle,
|
|
opacity: hoveredIndex !== null ? 1 : 0,
|
|
}}
|
|
/>
|
|
|
|
{/* Active Indicator */}
|
|
<div
|
|
className="absolute bottom-[-6px] h-[2px] bg-[#2B5F47] transition-all duration-300 ease-out"
|
|
style={activeStyle}
|
|
/>
|
|
|
|
{/* Tabs */}
|
|
<div className="relative flex space-x-[24px] items-center">
|
|
{tabs.map((tab, index) => (
|
|
<div
|
|
key={index}
|
|
ref={(el) => (tabRefs.current[index] = el)}
|
|
className={`px-3 py-2 cursor-pointer transition-colors duration-300 h-[30px] ${
|
|
index === activeIndex ? "text-[#2B5F47] font-medium" : "text-[#2B5F47]/70"
|
|
}`}
|
|
onMouseEnter={() => setHoveredIndex(index)}
|
|
onMouseLeave={() => setHoveredIndex(null)}
|
|
onClick={() => setActiveIndex(index)}
|
|
>
|
|
<div className="text-sm leading-5 whitespace-nowrap flex items-center justify-center h-full">
|
|
{tab}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|