‮Skip to content‬
uiify

Table of contents

‮Compact heading navigation with hover magnification and scrollspy.‬

‮Browsers‬
Chrome 123+Firefox 121+Safari 17.5+
‮Tier‬
2
‮Bundle compressed‬
4.14 kB
‮Forced layout budget‬
0 ms
‮Axe budget‬
0
‮SSR compatible‬
‮Yes‬
‮Published contract‬
‮Test harness‬

‮Playground‬

Overview

A table of contents gives readers a quick map of a long page. Follow a heading to jump directly to its section, or keep reading and let the current position update as you scroll.

Installation

Import the client entry to enable scroll tracking and pointer interaction. The native button and heading links are already usable before the page finishes loading.

Configuration

Match every line and link to a unique heading ID. Choose a scroll container and a content boundary when the article lives inside another page.

Examples

Hover a line to see its heading in the contents list. Click the line to jump there. On a touch screen, open the list and select the heading you want to read.

Accessibility

The contents are ordinary navigation links. Use the keyboard to open the list, move through its headings, and dismiss it with Escape. Scrolling never moves keyboard focus.

Styling

Adjust line length, spacing and the panel width with CSS variables. The current section uses bolder text; the heading under the pointer gets a separate hover background.

Conclusion

The same component works beside a document or inside a reader. Its compact rail stays available while the article scrolls, without taking a separate content column.

‮API‬

TableOfContents.Root (/client)

‮Prop‬‮Type‬‮Default‬‮Description‬
scrollSpybooleantrue‮Track same-page targets in document order after hydration.‬
scrollTargetstring—‮Scrollable element ID. Omit to track the owning window; a missing ID does not fall back.‬
contentTargetstring—‮Content element ID, limiting target discovery and determining the article end.‬
offsetnumber0‮Pixels below the scroll viewport start used to select the current heading.‬
valuestring | null—‮Controlled current target ID. null clears selection.‬
defaultValuestring | nullnull‮Initial current target ID.‬
onValueChange(value: string | null) => void—‮Reports scrollspy changes without moving focus.‬
openboolean—‮Controlled popover state.‬
defaultOpenbooleanfalse‮Initial open state applied after hydration.‬
onOpenChange(open: boolean) => void—‮Reports hover, activation and native dismissal requests.‬
openOnHoverbooleantrue‮Open on mouse hover; touch uses the native button.‬
openDelaynumber100‮Mouse hover opening delay in milliseconds.‬
closeDelaynumber200‮Grace period for moving between trigger and list.‬
renderReactElement | ((props, state) => ReactElement)—‮Replace the rendered element while keeping behavior and accessibility wiring.‬

TableOfContents.Trigger

‮Prop‬‮Type‬‮Default‬‮Description‬
target*string—‮Unique Content ID, wired with native popovertarget.‬
aria-labelstring—‮Accessible name required when the trigger contains only the decorative rail.‬

TableOfContents.Indicator

‮Prop‬‮Type‬‮Default‬‮Description‬
value*string—‮Target ID matching a Link fragment; one indicator per section.‬
level1 | 2 | 3 | 4 | 5 | 62‮Heading depth available through --uiify-toc-level.‬
selectedbooleanfalse‮Server entry selection; client derives selection from Root.value.‬
renderReactElement | ((props, state) => ReactElement)—‮Replace the rendered element while keeping behavior and accessibility wiring.‬

TableOfContents.Content

‮Prop‬‮Type‬‮Default‬‮Description‬
id*string—‮Unique popover ID matching Trigger.target.‬
side"top" | "right" | "bottom" | "left""left"‮Native CSS anchor side; layout flips when necessary.‬
align"start" | "center" | "end""start"‮Alignment beside the trigger.‬
renderReactElement | ((props, state) => ReactElement)—‮Replace the rendered element while keeping behavior and accessibility wiring.‬

TableOfContents.Link

TableOfContents.Rail / List

‮Prop‬‮Type‬‮Default‬‮Description‬
renderReactElement | ((props, state) => ReactElement)—‮Replace the rendered element while keeping behavior and accessibility wiring.‬

‮Keyboard‬

‮Key‬‮Action‬
Enter / Space‮Toggle the native contents popover from its trigger‬
Tab / Shift+Tab‮Move through ordinary heading links‬
Escape‮Dismiss the popover; return focus from the list to its trigger‬

‮Accessibility‬

‮Label the navigation landmark and its icon-only trigger. The server entry supports native popover activation, dismissal and fragment links before hydration; the /client entry adds hover, click pinning, magnification and scrollspy. Current links expose aria-current=location and decorative indicators are hidden from assistive technology. Scrollspy never moves focus or announces scrolling. With reduced motion, the optional skin disables line transitions.‬

‮Styling hooks‬

data-uiify-table-of-contentsdata-partdata-selecteddata-highlighteddata-statedata-sidedata-aligndata-positioning--uiify-toc-line-size--uiify-toc-line-max-size--uiify-toc-line-thickness--uiify-toc-row-size--uiify-toc-magnify-radius--uiify-toc-indent--uiify-toc-panel-size--uiify-toc-duration--uiify-toc-level--uiify-toc-index--uiify-toc-pointer