Hooks
useActiveSection
Highlighting the active section of a long page while scrolling.
Highlighting the active section while scrolling — and smoothly moving to it on click. The table of contents on the right of this very page runs on it.
Example
import { useActiveSection } from "@toimetdev/pathlogs-hooks";
function Toc({ entries }) {
const { active, scrollTo } = useActiveSection(
entries.map((e) => e.id),
{ offset: 80 } // height of the sticky header
);
return (
<ul>
{entries.map((e) => (
<li key={e.id}>
<button
onClick={() => scrollTo(e.id)}
aria-current={active === e.id ? "true" : undefined}
>
{e.title}
</button>
</li>
))}
</ul>
);
}Sections are located with document.getElementById, so on the page itself it is enough to put ids on the headings.
Options
| Prop | Type | Default | Description |
|---|---|---|---|
ids* | string[] | — | Section ids, in the order they appear on the page. |
offset | number | (() => number) | 0 | The top inset below which a section counts as «scrolled to» — usually the height of the sticky bar. Pass a function if that height depends on the screen width. |
enabled | boolean | true | Turn tracking off. |
ids*string[]Section ids, in the order they appear on the page.
offsetnumber | (() => number)defaults to: 0
The top inset below which a section counts as «scrolled to» — usually the height of the sticky bar. Pass a function if that height depends on the screen width.
enabledbooleandefaults to: true
Turn tracking off.
Returns { active, scrollTo }. Smooth scrolling is disabled under prefers-reduced-motion.
Highlighting rules
The active section is the last one whose top edge has already passed the offset line. With two exceptions:
- Before you have reached any of them — the first one is active. Otherwise nothing would be highlighted at the top of the page.
- At the very bottom of the page — the last one is active. Short sections at the end physically cannot rise to the line, and without this rule they would never light up.
The arithmetic itself lives in activeSectionId(positions, line, atBottom) — a pure, DOM-free function covered by tests.