Files
zeekayandHanzo Dev 5f1710f5ed chore: initial commit — tree had no git at all
@luxfi/lps-docs. No history, no remote, not on GitHub.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-28 11:54:18 -07:00

73 lines
2.0 KiB
TypeScript

'use client';
import { useEffect, useState } from 'react';
import { cn } from '@/lib/utils';
import type { TOCItem } from '@/lib/toc';
interface TOCProps {
items: TOCItem[];
className?: string;
}
export function TableOfContents({ items, className }: TOCProps) {
const [activeId, setActiveId] = useState<string>('');
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setActiveId(entry.target.id);
}
});
},
{ rootMargin: '-80px 0px -80% 0px' }
);
// Observe all heading elements
items.forEach((item) => {
const element = document.getElementById(item.id);
if (element) observer.observe(element);
});
return () => observer.disconnect();
}, [items]);
if (items.length === 0) return null;
return (
<nav className={cn('text-sm', className)}>
<div className="font-medium mb-4 text-foreground">On this page</div>
<ul className="space-y-2">
{items.map((item) => (
<li
key={item.id}
style={{ paddingLeft: `${(item.level - 2) * 12}px` }}
>
<a
href={`#${item.id}`}
className={cn(
'block py-1 text-muted-foreground hover:text-foreground transition-colors duration-200',
'border-l-2 pl-3 -ml-px',
activeId === item.id
? 'border-foreground text-foreground font-medium'
: 'border-transparent'
)}
onClick={(e) => {
e.preventDefault();
const element = document.getElementById(item.id);
if (element) {
element.scrollIntoView({ behavior: 'smooth' });
setActiveId(item.id);
}
}}
>
{item.text}
</a>
</li>
))}
</ul>
</nav>
);
}