WebberUI

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.jsonfiles[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型別預設值說明
magnificationnumber64游標最接近時的圖示尺寸(px)
baseSizenumber40靜止時的圖示尺寸(px)
distancenumber140放大影響半徑(px):游標與圖示中心的水平距離在此範圍內才會放大
classNamestring附加到 dock 容器的 class
childrenReact.ReactNode直接放入 DockItem 子元件

DockItem

Prop型別預設值說明
labelstring圖示標籤:hover 或鍵盤 focus 時顯示於上方,同時作為 aria-label
onClickReact.MouseEventHandler點擊事件(button 與連結皆適用)
hrefstring提供時渲染為 <a> 連結,否則為 <button>
childrenReact.ReactNode圖示內容:任意 SVG 或元素,會自動填滿圖示區並隨放大等比縮放
classNamestring附加到單一圖示按鈕的 class

細節

  • 共享 mouseX:容器 pointermove 更新共享的游標 X 座標(MotionValue),離開時設為 Infinity;每個 DockItemuseTransform 把「與游標的水平距離」映射成尺寸區間,再經 useSpring 平滑,形成經典 macOS 放大波形
  • dock 本體不跳動:容器高度固定為 baseSize + 留白、圖示底部對齊,放大時向上溢出
  • tooltip 標籤:hover 單一圖示時以 AnimatePresence 浮出上方小卡;標籤同時是 aria-label,小卡本身對輔助科技隱藏、不重複朗讀
  • 鍵盤可及性DockItem 是原生 <button>(有 href 時為 <a>),Tab 可逐一聚焦;focus-visible 時同樣放大到 magnification 並顯示標籤
  • 觸控裝置自動退化:僅回應滑鼠的 pointer 事件(pointerType === "mouse"),觸控時就是一列等尺寸的普通按鈕
  • 使用者系統開啟「減少動態效果」時停用放大與標籤位移動畫,DOM 結構完全一致、功能不受影響
  • 元件本體不依賴任何 icon 庫,children 放什麼 SVG 都會自動撐滿圖示區

On this page