Navigation
Inputs & Forms
Selection
Containers & Overlays
On-Page Menu
Table of contents of a long page that follows the scroll position.
Overview
The OnPageMenu lists the sections of a long page. The section in view is highlighted by an indicator that moves along the line, a click scrolls to a section. Subsections are indented below their section. The menu at the right of this page is an OnPageMenu, too: scroll and watch it follow.
componentsmenu-itemservices
"use client";import React, {useState} from "react";import {OnPageMenu, OnPageMenuItem, SwitchSelect} from "@brynlabs/fusion-ui";const items: OnPageMenuItem[] = [{id: "components",title: "Components",children: [{id: "menu-item", title: "Menu item"}],},{id: "services", title: "Services and dependency injection"},];const ids = ["components", "menu-item", "services"];export const OnPageMenuExample = () => {const [activeId, setActiveId] = useState("components");return (<div style={{display: "flex", flexWrap: "wrap", gap: "3rem", alignItems: "start"}}><div style={{width: "16rem"}}><OnPageMenu items={items} activeId={activeId} /></div><SwitchSelectaria-label={"Active section"}options={ids.map(id => ({label: id, value: id}))}value={activeId}onChange={setActiveId}/></div>);};
Following the scroll position
Without activeId, the menu follows the window scroll position itself: the last section whose top passed the top of the page is active, and the last one once the page is scrolled to the bottom. Place the menu in a sticky column and give the sections a scroll-margin-top, so they are not hidden behind the fixed views when the menu scrolls to them.
<div className={styles.layout}><main><h2 id="installation">Installation</h2>…<h2 id="usage">Usage</h2>…</main><aside className={styles.aside}><OnPageMenuitems={[{id: "installation", title: "Installation"},{id: "usage", title: "Usage", children: [{id: "hooks", title: "Hooks"}]},]}/></aside></div>
@use "@brynlabs/fusion-ui" as fusionui;.aside {position: sticky;top: calc(fusionui.get-view-offset("top") + var(--size--150));}h2 {scroll-margin-top: calc(fusionui.get-view-offset("top") + var(--size--150));}

