@k2b/ui
TableOfContents
Native section links with a container or window scroll spy.
Section links follow this small scroll container. The navigation stays in view.
Sharing
Select Share to invite another reader.
Access
Choose who can read the document.
Links
Copy the link.
TSX
Copyconst [root, setRoot] = createSignal<HTMLElement>();const items = [ { id: "toc-demo-sharing", label: "Sharing" }, { id: "toc-demo-access", label: "Access" }, { id: "toc-demo-links", label: "Links" },];<div ref={setRoot} style={{ height: "16rem", overflow: "auto", display: "grid", "grid-template-columns": "8rem 1fr", gap: "1rem" }}> <TableOfContents items={items} scrollRoot={root} sticky /> <article> <section style={{ "min-height": "14rem" }}><h2 id="toc-demo-sharing">Sharing</h2><p>Select Share to invite another reader.</p></section> <section style={{ "min-height": "14rem" }}><h2 id="toc-demo-access">Access</h2><p>Choose who can read the document.</p></section> <section style={{ "min-height": "7rem" }}><h2 id="toc-demo-links">Links</h2><p>Copy the link.</p></section> </article></div>TableOfContents links to sections and marks the current section as content scrolls.
Use TableOfContents
Use it beside a page or a scrollable article. Each item identifies an existing heading.
Import
import { TableOfContents } from "@k2b/ui";Example
const [root, setRoot] = createSignal<HTMLElement>();
const items = [{ id: "sharing", label: "Sharing" }];
<TableOfContents items={items} scrollRoot={root} sticky />
<article ref={setRoot} style={{ height: "20rem", overflow: "auto" }}>
<h2 id="sharing">Sharing</h2>
</article>Items have an id and a text label. Empty items render nothing.
The visible title and navigation name default to “On this page” or
“Auf dieser Seite” from the inherited locale. Pass title to replace it.
Without scrollRoot, the window decides the active section. Pass an element
or accessor for a content scroller. The last heading above a line one quarter
down its visible box becomes active. Before the first heading reaches that
line, the first item stays active. At the end of scrolling, a visible last
heading becomes active. onActiveChange receives the new ID, or undefined
when the list becomes empty, once per change.
The active section also updates without scrolling when the scroll root, a
direct child of it, or a heading's parent element changes size, for example
after an image loads or a disclosure opens.
sticky keeps the navigation in view within the caller's layout.
Links use normal browser anchor navigation. Changing the active section does
not change the list's geometry. Server markup marks the first item current.
Accessibility
The visible heading names the nav. Native links remain keyboard accessible.
Only the active link has aria-current="location".
Runtime
Native links work without JavaScript. The scroll spy starts in the browser and removes its listeners when disposed.