Strata Headers
章節標題被滾過後依序吸附頂端層層堆疊,累積成由閱讀進度堆出的即時目錄。
載入預覽⋯
安裝
npx shadcn@latest add https://webberui.com/r/strata-headers.json安裝依賴後,從 registry JSON(/r/strata-headers.json 的 files[0].content)複製 strata-headers.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion clsx tailwind-merge使用
以 StrataSection 包住每個章節,標題列會在被滾過後自動堆疊在頂端;點擊任一列標題捲回該章節:
import { StrataHeaders, StrataSection } from "@/components/ui/strata-headers";
<StrataHeaders headerHeight={40}>
<StrataSection title="第一章:起源">
<p>章節內容……</p>
</StrataSection>
<StrataSection title="第二章:發展">
<p>章節內容……</p>
</StrataSection>
<StrataSection title="第三章:現在">
<p>章節內容……</p>
</StrataSection>
</StrataHeaders>滾動容器可以是頁面本身,也可以是任何 overflow-y: auto 的區塊(如上方示範)——元件會自動偵測最近的可捲動祖先,不需要傳入 container ref。
Props
StrataHeaders
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | React.ReactNode | — | 直接放入 StrataSection 子元件,每個子元素為一個章節 |
headerHeight | number | 40 | 每列標題的高度(px),同時決定堆疊的層距 |
className | string | — | 附加到最外層容器的 class |
StrataSection
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
title | React.ReactNode | — | 章節標題,顯示在可堆疊的標題列上 |
children | React.ReactNode | — | 章節內容 |
id | string | — | 套用在標題列上的錨點 id |
className | string | — | 附加到標題列按鈕的 class(例如覆寫預設的 bg-white dark:bg-neutral-950 以配合頁面底色) |
細節
- 堆疊由 CSS 原生完成:第
i列標題套用position: sticky; top: i * headerHeight,不以 scroll 事件驅動版面,滾動效能與原生一致 - 吸附偵測使用 IntersectionObserver 哨兵——每個章節在標題列前放一個 1px 的流內哨兵,哨兵一被捲過釘住線即切換 pinned 狀態,開銷極低
- 吸附時字級縮小(transform scale,不觸發 layout)、浮現底線與陰影,並以章節序號標記堆疊順序
- 點擊任一列標題(無論是否已吸附)平滑捲回該章節頂部,捲動目標已扣除上方堆疊的高度,章節開頭不會被蓋住
- 使用者系統開啟「減少動態效果」時,sticky 堆疊屬於版面而非動效因此保留,但縮放/陰影過渡與平滑捲動皆停用(直接跳至定位)
- 標題列是原生
<button>:鍵盤可聚焦、Enter 觸發,吸附中的章節標記aria-current