Scroll-aware Navbar
會隨滾動收縮、隱藏或變寬的導航列,三種樣式共用一致的節奏並支援巢狀捲動容器。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
24
72
56
448
<ScrollAwareNavbar />
安裝
npx shadcn@latest add https://webberui.com/r/scroll-aware-navbar.json或在 components.json 設定 registries 後,改用 @webberui/scroll-aware-navbar 安裝。
安裝依賴後,從 registry JSON(/r/scroll-aware-navbar.json 的 files[0].content)複製 scroll-aware-navbar.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion clsx tailwind-merge使用
import { ScrollAwareNavbar } from "@/components/ui/scroll-aware-navbar";
<ScrollAwareNavbar variant="shrink">
<span className="font-semibold">Webber</span>
<nav className="flex gap-4">
<a href="#features">功能</a>
<a href="#docs">文件</a>
</nav>
<button className="rounded-full bg-neutral-900 px-3 py-1.5 text-white">
開始
</button>
</ScrollAwareNavbar>導航列以 sticky top-0 貼齊捲動容器頂部,children 由你自由排版(預設 justify-between)。若捲動發生在巢狀 overflow 容器內,將該容器的 ref 傳入 container:
const scrollerRef = React.useRef<HTMLDivElement>(null);
<div ref={scrollerRef} className="h-[400px] overflow-y-auto">
<ScrollAwareNavbar variant="float" container={scrollerRef}>
{/* ... */}
</ScrollAwareNavbar>
{/* 內容 */}
</div>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | React.ReactNode | — | 導航列內容,通常為品牌、連結與行動按鈕 |
variant | "shrink" | "hide" | "float" | "shrink" | 滾動反應樣式:收縮、隱藏、或變寬 |
threshold | number | 24 | 判定為「已滾動」的門檻(px) |
expandedHeight | number | 72 | 置頂時的展開高度(px) |
condensedHeight | number | 56 | 滾動後的收縮高度(px),供 shrink 與 float 使用 |
pillWidth | number | 448 | float 樣式置頂時的膠囊寬度上限(px) |
position | "sticky" | "fixed" | "sticky" | 定位方式;fixed 需自行為內容預留空間 |
container | RefObject<HTMLElement | null> | — | 巢狀捲動容器的 ref;未傳入時追蹤整個視窗 |
className | string | — | 套用在可視導航列(內層 bar)上,可加 max-w、字級等 |
wrapperClassName | string | — | 套用在最外層定位容器(header)上,例如覆寫 z-index |
aria-label | string | "主導航列" | 導航列 landmark 的無障礙標籤 |
三種樣式
- shrink:置頂時透明地浮在內容之上;滾動超過
threshold後高度由expandedHeight收縮到condensedHeight,並淡入毛玻璃背景與底線。 - hide:向下滾動時整條以位移收起、向上滾動時滑回,適合讓內容區在閱讀時佔滿高度。滾動後同樣浮現背景。
- float:置頂時是一顆置中的窄膠囊(
pillWidth)並與頂端保留間距;滾動後變寬鋪滿容器、圓角收斂並貼齊頂部。
細節
- 以
useScroll追蹤捲動位置,hide樣式再比對前後位移判斷方向;含 2px 死區避免抖動。 float的變寬目標寬度以ResizeObserver量測外層容器實際寬度取得,因此展寬動畫平滑且隨容器尺寸自適應。- 背景以獨立圖層淡入淡出,收縮或浮現時不牽動內容排版。
可及性
- 最外層為
<header>landmark 並帶aria-label;hide樣式收起後,鍵盤焦點一旦移入導航列會立即滑回,焦點不會停在畫面外。 - 使用者系統開啟「減少動態效果」時,停用向下捲動的位移隱藏(導航列恆為可見),其餘狀態改為即時切換而非過渡動畫。
- 所有
useScroll事件監聽與ResizeObserver於 unmount 時完整清理。