Files
ACVE/components/courses/CourseLevelTabs.tsx
2026-03-15 13:52:11 +00:00

83 lines
2.6 KiB
TypeScript

"use client";
import { useEffect, useMemo, useState } from "react";
import { cn } from "@/lib/utils";
type CourseLevelTabItem = {
id: string;
label: string;
anchorId: string;
count: number;
};
type CourseLevelTabsProps = {
items: CourseLevelTabItem[];
};
export default function CourseLevelTabs({ items }: CourseLevelTabsProps) {
const [activeId, setActiveId] = useState(items[0]?.id ?? "");
const sectionIds = useMemo(() => items.map((item) => item.anchorId), [items]);
useEffect(() => {
if (items.length === 0) return;
const observer = new IntersectionObserver(
(entries) => {
const visible = entries
.filter((entry) => entry.isIntersecting)
.sort((a, b) => b.intersectionRatio - a.intersectionRatio);
if (visible.length === 0) return;
const matched = items.find((item) => item.anchorId === visible[0].target.id);
if (matched) setActiveId(matched.id);
},
{
rootMargin: "-30% 0px -55% 0px",
threshold: [0.2, 0.35, 0.5, 0.7],
},
);
sectionIds.forEach((sectionId) => {
const element = document.getElementById(sectionId);
if (element) observer.observe(element);
});
return () => observer.disconnect();
}, [items, sectionIds]);
const scrollToSection = (anchorId: string, id: string) => {
const section = document.getElementById(anchorId);
if (!section) return;
section.scrollIntoView({ behavior: "smooth", block: "start" });
setActiveId(id);
};
return (
<section className="acve-panel acve-section-tight sticky top-[8.4rem] z-30 border-border/80 bg-card/90 backdrop-blur">
<p className="mb-3 text-xs font-semibold uppercase tracking-[0.14em] text-muted-foreground">Nivel académico</p>
<div className="grid gap-2 sm:grid-cols-3">
{items.map((item) => {
const isActive = item.id === activeId;
return (
<button
key={item.id}
className={cn(
"rounded-xl border px-3 py-2 text-left transition-colors",
isActive
? "border-primary/45 bg-primary/10 text-primary"
: "border-border/80 bg-card/70 text-foreground hover:border-primary/30 hover:bg-accent/60",
)}
type="button"
onClick={() => scrollToSection(item.anchorId, item.id)}
>
<p className="text-sm font-semibold">{item.label}</p>
<p className="text-xs text-muted-foreground">{item.count} programas</p>
</button>
);
})}
</div>
</section>
);
}