WebberUI

Strata Headers

章節標題被滾過後依序吸附頂端層層堆疊,累積成由閱讀進度堆出的即時目錄。

載入預覽⋯

安裝

npx shadcn@latest add https://webberui.com/r/strata-headers.json

安裝依賴後,從 registry JSON(/r/strata-headers.jsonfiles[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型別預設值說明
childrenReact.ReactNode直接放入 StrataSection 子元件,每個子元素為一個章節
headerHeightnumber40每列標題的高度(px),同時決定堆疊的層距
classNamestring附加到最外層容器的 class

StrataSection

Prop型別預設值說明
titleReact.ReactNode章節標題,顯示在可堆疊的標題列上
childrenReact.ReactNode章節內容
idstring套用在標題列上的錨點 id
classNamestring附加到標題列按鈕的 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

On this page