Skip to Content
DocsCloud UI HooksuseScrollSpy

useScrollSpy

Track scroll position for navigation and table of contents.

Import

import { useScrollSpy } from '@tidbcloud/uikit'

Usage

useScrollSpy tracks scroll position and returns the index of the element that is currently in the viewport. It’s useful for creating table of contents components and similar features.

import { useScrollSpy } from '@tidbcloud/uikit' import { NavLink, Stack } from '@tidbcloud/uikit' function Demo() { const { data, active } = useScrollSpy() return ( <div style={{ display: 'flex', gap: 20 }}> <nav style={{ position: 'sticky', top: 20 }}> <Stack gap="xs"> {data.map((item, index) => ( <NavLink key={item.id} label={item.value} active={active === index} onClick={() => item.getNode().scrollIntoView()} /> ))} </Stack> </nav> <main> <h1 id="section-1">Section 1</h1> <p>Content...</p> <h2 id="section-2">Section 2</h2> <p>Content...</p> <h2 id="section-3">Section 3</h2> <p>Content...</p> </main> </div> ) }

Options

  • selector – selector to get headings, 'h1, h2, h3, h4, h5, h6' by default
  • getDepth – function to retrieve depth of heading
  • getValue – function to retrieve heading value
  • scrollHost – host element to attach scroll event listener
  • offset – offset from the top of the viewport
import { useScrollSpy } from '@tidbcloud/uikit' // Custom selector for elements with data-heading attribute const { data, active } = useScrollSpy({ selector: '[data-heading]', getDepth: (element) => Number(element.getAttribute('data-depth')), getValue: (element) => element.getAttribute('data-value') || '', offset: 100 })

Reinitializing

If the DOM changes after mount, use reinitialize to update the headings data:

import { useEffect } from 'react' import { useScrollSpy } from '@tidbcloud/uikit' function Demo({ dependency }) { const { reinitialize, data, active } = useScrollSpy() useEffect(() => { reinitialize() }, [dependency]) return null }

Definition

interface UseScrollSpyHeadingData { depth: number value: string id: string getNode: () => HTMLElement } interface UseScrollSpyOptions { selector?: string getDepth?: (element: HTMLElement) => number getValue?: (element: HTMLElement) => string scrollHost?: HTMLElement offset?: number } interface UseScrollSpyReturnType { active: number data: UseScrollSpyHeadingData[] initialized: boolean reinitialize: () => void } function useScrollSpy(options?: UseScrollSpyOptions): UseScrollSpyReturnType
Last updated on