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 defaultgetDepth– function to retrieve depth of headinggetValue– function to retrieve heading valuescrollHost– host element to attach scroll event listeneroffset– 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