defuss-shadcn / Navigation / toc
Table of ContentsMOL
A section-nav block of heading links - the docs rail you're looking at on the right, packaged as a reusable pattern. Native fragment links do the scrolling; the current section is marked with aria-current. No JavaScript shipped - the host's IntersectionObserver moves the marker.
On this page (4)
§Default
A section nav with the current section marked via aria-current='location' - here as a left rail beside the main content. Scroll the content or click a link: a few lines of host script move the marker with an IntersectionObserver, exactly what the docs' own runtime does. The component itself ships no JavaScript.
§Docs rail
The layout these docs use: main content on the left, the ToC as a sticky rail on the right. The rail stays in place (position: sticky) while the content scrolls underneath, and the same host observer moves aria-current as each section reaches the top.
§Density
Set data-density on the component root to scale the link rows' vertical rhythm. A whitespace policy, not a zoom: only the block padding scales (ratio 0.75 / 1 / 1.25), font size stays identical. comfortable matches the unsized default.
§CSS view file
/* -- Table of Contents component ------------------------------ */@layer components { .toc { display: block; } .toc-title { font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: var(--foreground); margin: 0 0 0.5rem; padding: 0 0.5rem; } /* -- Density ---------------------------------------------------- data-density on the .toc root scales the vertical rhythm of the links (0.75 / 1 / 1.25 of the 3px block padding); comfortable matches the unsized default. Font size stays put - whitespace, not zoom. */ .toc:where([data-density="compact"]) .toc-link { padding: 0.125rem 0.5rem; } .toc:where([data-density="comfortable"]) .toc-link { padding: 0.1875rem 0.5rem; } .toc:where([data-density="spacious"]) .toc-link { padding: 0.25rem 0.5rem; } .toc-link { display: block; padding: 0.1875rem 0.5rem; font-size: 0.8125rem; color: var(--muted-foreground); text-decoration: none; border-left: 2px solid transparent; transition: color 150ms, border-color 150ms; line-height: 1.6; &:hover { color: var(--foreground); } &[aria-current="location"] { color: var(--foreground); border-left-color: var(--primary); } } @media (prefers-reduced-motion: reduce) { .toc-link { transition: none; } } @media (forced-colors: active) { .toc-link[aria-current="location"] { border-left-color: LinkText; } }}Comments, ideas or improvements? Edit this page's source on GitHub