This repository has no description
Something went wrong. Try again.
2.0 kB · 74 lines
TSX
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475// src/components/TableOfContents.tsximport type { Heading } from '@/lib/lexical-headings'
interface TableOfContentsProps { headings: Heading[] title?: string showTitle?: boolean}
function flatten( list: Heading[], depth = 0, acc: Array<Heading & { depth: number }> = [],): Array<Heading & { depth: number }> { for (const h of list) { acc.push({ ...h, depth }) if (h.children?.length) flatten(h.children, depth + 1, acc) } return acc}
export function TableOfContents({ headings, title = 'Contents', showTitle = true,}: TableOfContentsProps) { const flat = flatten(headings) if (flat.length === 0) return null
return ( <nav className="toc-nav" aria-label="Article sections navigation"> {showTitle && ( <p className="text-ink-3 border-hair m-0 mb-4 flex justify-between border-b pb-3 font-mono text-[11px] tracking-[0.18em] uppercase"> <span>{title}</span> <span className="text-ink-4">{flat.length}</span> </p> )} <ul className="m-0 list-none p-0"> {flat.map((h) => ( <li key={h.id} className={`py-[5px]${h.depth > 0 ? ' pl-3.5' : ''}`}> <a href={`#${h.id}`} data-heading-id={h.id} className={[ 'toc-link text-ink-3 hover:text-ink relative flex items-start gap-2.5 pl-3.5 leading-snug no-underline transition-colors', h.depth > 0 ? 'text-[12.5px]' : 'text-[13px]', ].join(' ')} > {h.text} </a> </li> ))} </ul> <style>{` .toc-link::before { content: ''; position: absolute; left: 0; top: 9px; width: 6px; height: 1px; background: rgb(var(--ink-4)); } .toc-link.active { color: rgb(var(--ink)); } .toc-link.active::before { background: rgb(var(--ink)); width: 8px; } `}</style> </nav> )}