⟦Škíp tó çóñtéñt~~~~~~⟧
uiify

Table of contents

⟦Çómpáçt héádíñg ñávígátíóñ wíth hóvér mágñífíçátíóñ áñd šçróllšpý.~~~~~~~~~~~~~~~~~~~~~~~~⟧

⟦Brówšérš~~~⟧
Chrome 123+Firefox 121+Safari 17.5+
⟦Tíér~~⟧
2
⟦Búñdlé çómpréššéd~~~~~~⟧
4.14 kB
⟦Fórçéd láýóút búdgét~~~~~~~⟧
0 ms
⟦Áxé búdgét~~~~⟧
0
⟦ŠŠR çómpátíblé~~~~~⟧
⟦Ýéš~~⟧
⟦Públíšhéd çóñtráçt~~~~~~~⟧
⟦Téšt hárñéšš~~~~~⟧

⟦Pláýgróúñd~~~~⟧

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.

⟦ÁPÍ~~⟧

TableOfContents.Root (/client)

⟦Próp~~⟧⟦Týpé~~⟧⟦Défáúlt~~~⟧⟦Déšçríptíóñ~~~~⟧
scrollSpybooleantrue⟦Tráçk šámé-págé tárgétš íñ dóçúméñt órdér áftér hýdrátíóñ.~~~~~~~~~~~~~~~~~~~~~⟧
scrollTargetstring—⟦Šçrólláblé éléméñt ÍD. Ómít tó tráçk thé ówñíñg wíñdów; á míššíñg ÍD dóéš ñót fáll báçk.~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~⟧
contentTargetstring—⟦Çóñtéñt éléméñt ÍD, límítíñg tárgét díšçóvérý áñd détérmíñíñg thé ártíçlé éñd.~~~~~~~~~~~~~~~~~~~~~~~~~~~~⟧
offsetnumber0⟦Píxélš bélów thé šçróll víéwpórt štárt úšéd tó šéléçt thé çúrréñt héádíñg.~~~~~~~~~~~~~~~~~~~~~~~~~~⟧
valuestring | null—⟦Çóñtrólléd çúrréñt tárgét ÍD. ñúll çléárš šéléçtíóñ.~~~~~~~~~~~~~~~~~~~⟧
defaultValuestring | nullnull⟦Íñítíál çúrréñt tárgét ÍD.~~~~~~~~~~⟧
onValueChange(value: string | null) => void—⟦Répórtš šçróllšpý çháñgéš wíthóút móvíñg fóçúš.~~~~~~~~~~~~~~~~~⟧
openboolean—⟦Çóñtrólléd pópóvér štáté.~~~~~~~~~⟧
defaultOpenbooleanfalse⟦Íñítíál ópéñ štáté ápplíéd áftér hýdrátíóñ.~~~~~~~~~~~~~~~~⟧
onOpenChange(open: boolean) => void—⟦Répórtš hóvér, áçtívátíóñ áñd ñátívé díšmíššál réqúéštš.~~~~~~~~~~~~~~~~~~~~⟧
openOnHoverbooleantrue⟦Ópéñ óñ móúšé hóvér; tóúçh úšéš thé ñátívé búttóñ.~~~~~~~~~~~~~~~~~~⟧
openDelaynumber100⟦Móúšé hóvér ópéñíñg déláý íñ míllíšéçóñdš.~~~~~~~~~~~~~~~⟧
closeDelaynumber200⟦Gráçé péríód fór móvíñg bétwééñ tríggér áñd líšt.~~~~~~~~~~~~~~~~~~⟧
renderReactElement | ((props, state) => ReactElement)—⟦Répláçé thé réñdéréd éléméñt whílé kéépíñg béhávíór áñd áççéššíbílítý wíríñg.~~~~~~~~~~~~~~~~~~~~~~~~~~~⟧

TableOfContents.Trigger

⟦Próp~~⟧⟦Týpé~~⟧⟦Défáúlt~~~⟧⟦Déšçríptíóñ~~~~⟧
target*string—⟦Úñíqúé Çóñtéñt ÍD, wíréd wíth ñátívé pópóvértárgét.~~~~~~~~~~~~~~~~~~⟧
aria-labelstring—⟦Áççéššíblé ñámé réqúíréd whéñ thé tríggér çóñtáíñš óñlý thé déçórátívé ráíl.~~~~~~~~~~~~~~~~~~~~~~~~~~~⟧

TableOfContents.Indicator

⟦Próp~~⟧⟦Týpé~~⟧⟦Défáúlt~~~⟧⟦Déšçríptíóñ~~~~⟧
value*string—⟦Tárgét ÍD mátçhíñg á Líñk frágméñt; óñé íñdíçátór pér šéçtíóñ.~~~~~~~~~~~~~~~~~~~~~~⟧
level1 | 2 | 3 | 4 | 5 | 62⟦Héádíñg dépth áváíláblé thróúgh --úíífý-tóç-lévél.~~~~~~~~~~~~~~~~~~⟧
selectedbooleanfalse⟦Šérvér éñtrý šéléçtíóñ; çlíéñt dérívéš šéléçtíóñ fróm Róót.válúé.~~~~~~~~~~~~~~~~~~~~~~~⟧
renderReactElement | ((props, state) => ReactElement)—⟦Répláçé thé réñdéréd éléméñt whílé kéépíñg béhávíór áñd áççéššíbílítý wíríñg.~~~~~~~~~~~~~~~~~~~~~~~~~~~⟧

TableOfContents.Content

⟦Próp~~⟧⟦Týpé~~⟧⟦Défáúlt~~~⟧⟦Déšçríptíóñ~~~~⟧
id*string—⟦Úñíqúé pópóvér ÍD mátçhíñg Tríggér.tárgét.~~~~~~~~~~~~~~~⟧
side"top" | "right" | "bottom" | "left""left"⟦Ñátívé ÇŠŠ áñçhór šídé; láýóút flípš whéñ ñéçéššárý.~~~~~~~~~~~~~~~~~~~⟧
align"start" | "center" | "end""start"⟦Álígñméñt béšídé thé tríggér.~~~~~~~~~~~⟧
renderReactElement | ((props, state) => ReactElement)—⟦Répláçé thé réñdéréd éléméñt whílé kéépíñg béhávíór áñd áççéššíbílítý wíríñg.~~~~~~~~~~~~~~~~~~~~~~~~~~~⟧

TableOfContents.Link

TableOfContents.Rail / List

⟦Próp~~⟧⟦Týpé~~⟧⟦Défáúlt~~~⟧⟦Déšçríptíóñ~~~~⟧
renderReactElement | ((props, state) => ReactElement)—⟦Répláçé thé réñdéréd éléméñt whílé kéépíñg béhávíór áñd áççéššíbílítý wíríñg.~~~~~~~~~~~~~~~~~~~~~~~~~~~⟧

⟦Kéýbóárd~~~⟧

⟦Kéý~~⟧⟦Áçtíóñ~~~⟧
Enter / Space⟦Tógglé thé ñátívé çóñtéñtš pópóvér fróm ítš tríggér~~~~~~~~~~~~~~~~~~⟧
Tab / Shift+Tab⟦Móvé thróúgh órdíñárý héádíñg líñkš~~~~~~~~~~~~~⟧
Escape⟦Díšmíšš thé pópóvér; rétúrñ fóçúš fróm thé líšt tó ítš tríggér~~~~~~~~~~~~~~~~~~~~~~⟧

⟦Áççéššíbílítý~~~~~⟧

⟦Lábél thé ñávígátíóñ láñdmárk áñd ítš íçóñ-óñlý tríggér. Thé šérvér éñtrý šúppórtš ñátívé pópóvér áçtívátíóñ, díšmíššál áñd frágméñt líñkš béfóré hýdrátíóñ; thé /çlíéñt éñtrý áddš hóvér, çlíçk píññíñg, mágñífíçátíóñ áñd šçróllšpý. Çúrréñt líñkš éxpóšé áríá-çúrréñt=lóçátíóñ áñd déçórátívé íñdíçátórš áré híddéñ fróm áššíštívé téçhñólógý. Šçróllšpý ñévér móvéš fóçúš ór áññóúñçéš šçróllíñg. Wíth rédúçéd mótíóñ, thé óptíóñál škíñ díšábléš líñé tráñšítíóñš.~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~⟧

⟦Štýlíñg hóókš~~~~~⟧

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