Tabs empiles verticalement avec un indicateur lateral anime.
"use client";
import { useState, useRef, useEffect } from "react";
export default function VerticalTabs({ tabs }: { tabs: { label: string; content: React.ReactNode }[] }) {
const [active, setActive] = useState(0);
const [indicatorY, setIndicatorY] = useState(0);
const [indicatorH, setIndicatorH] = useState(0);
const tabRefs = useRef<(HTMLButtonElement | null)[]>([]);
useEffect(() => {
const el = tabRefs.current[active];
if (el) {
const parent = el.parentElement!.getBoundingClientRect();
const rect = el.getBoundingClientRect();
setIndicatorY(rect.top - parent.top);
setIndicatorH(rect.height);
}
}, [active]);
return (
<div style={{ display: "flex", gap: 32 }}>
<div style={{ position: "relative" }}>
<div style={{
position: "absolute", left: 0, width: 3,
top: indicatorY, height: indicatorH,
background: "#E1FF6C", borderRadius: 2,
transition: "top 0.3s, height 0.3s",
}} />
{tabs.map((tab, i) => (
<button key={i} ref={el => { tabRefs.current[i] = el; }}
onClick={() => setActive(i)}>{tab.label}</button>
))}
</div>
<div>{tabs[active].content}</div>
</div>
);
}Tabs empiles verticalement avec un indicateur lateral (barre de 3px) qui glisse vers le tab actif. Le contenu change a droite. Ajoutez padding-left aux boutons pour laisser de la place a l'indicateur.