Dock
macOS 風格放大 dock:圖示依與游標的水平距離平滑放大,hover 浮出標籤。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
64
40
140
<Dock />
安裝
npx shadcn@latest add https://webberui.com/r/dock.json安裝時會一併寫入 --wb-duration-fast CSS 變數到你的全域樣式。
安裝依賴後,從 registry JSON(/r/dock.json 的 files[0].content)複製 dock.tsx 原始碼到你的 components/ui/ 目錄,並在全域 CSS 加入:
npm install motion clsx tailwind-merge:root {
--wb-duration-fast: 200ms;
}使用
import { Dock, DockItem } from "@/components/ui/dock";
import { Home, Search, Settings } from "lucide-react";
<Dock>
<DockItem label="首頁" href="/">
<Home />
</DockItem>
<DockItem label="搜尋" onClick={() => console.log("search")}>
<Search />
</DockItem>
<DockItem label="設定" href="/settings">
<Settings />
</DockItem>
</Dock>Props
Dock
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
magnification | number | 64 | 游標最接近時的圖示尺寸(px) |
baseSize | number | 40 | 靜止時的圖示尺寸(px) |
distance | number | 140 | 放大影響半徑(px):游標與圖示中心的水平距離在此範圍內才會放大 |
className | string | — | 附加到 dock 容器的 class |
children | React.ReactNode | — | 直接放入 DockItem 子元件 |
DockItem
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
label | string | — | 圖示標籤:hover 或鍵盤 focus 時顯示於上方,同時作為 aria-label |
onClick | React.MouseEventHandler | — | 點擊事件(button 與連結皆適用) |
href | string | — | 提供時渲染為 <a> 連結,否則為 <button> |
children | React.ReactNode | — | 圖示內容:任意 SVG 或元素,會自動填滿圖示區並隨放大等比縮放 |
className | string | — | 附加到單一圖示按鈕的 class |
細節
- 共享 mouseX:容器 pointermove 更新共享的游標 X 座標(
MotionValue),離開時設為Infinity;每個DockItem以useTransform把「與游標的水平距離」映射成尺寸區間,再經useSpring平滑,形成經典 macOS 放大波形 - dock 本體不跳動:容器高度固定為
baseSize+ 留白、圖示底部對齊,放大時向上溢出 - tooltip 標籤:hover 單一圖示時以
AnimatePresence浮出上方小卡;標籤同時是aria-label,小卡本身對輔助科技隱藏、不重複朗讀 - 鍵盤可及性:
DockItem是原生<button>(有href時為<a>),Tab 可逐一聚焦;focus-visible時同樣放大到magnification並顯示標籤 - 觸控裝置自動退化:僅回應滑鼠的 pointer 事件(
pointerType === "mouse"),觸控時就是一列等尺寸的普通按鈕 - 使用者系統開啟「減少動態效果」時停用放大與標籤位移動畫,DOM 結構完全一致、功能不受影響
- 元件本體不依賴任何 icon 庫,
children放什麼 SVG 都會自動撐滿圖示區