Gooey Menu
液態黏滯展開選單:懸浮觸發鈕點開後,項目以 SVG goo 濾鏡從按鈕中「拉」出並融合,支援四方向與扇形放射。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
16
44
56
<GooeyMenu />
安裝
npx shadcn@latest add https://webberui.com/r/gooey-menu.json或在 components.json 設定 registries 後,改用 @webberui/gooey-menu 安裝。
安裝依賴後,從 registry JSON(/r/gooey-menu.json 的 files[0].content)複製 gooey-menu.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion clsx tailwind-merge lucide-react使用
import { Heart, Bookmark, Share2 } from "lucide-react";
import { GooeyMenu, type GooeyMenuItem } from "@/components/ui/gooey-menu";
const items: GooeyMenuItem[] = [
{ icon: <Heart />, label: "喜歡", onClick: () => like() },
{ icon: <Bookmark />, label: "收藏", onClick: () => save() },
{ icon: <Share2 />, label: "分享", href: "/share" },
];
<GooeyMenu items={items} direction="up" />;受控模式:
const [open, setOpen] = useState(false);
<GooeyMenu items={items} open={open} onOpenChange={setOpen} direction="radial" />;Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
items | GooeyMenuItem[] | — | 選單項目(見下表) |
direction | 'up' | 'down' | 'left' | 'right' | 'radial' | 'up' | 展開方向;radial 為向上扇形放射 |
open | boolean | — | 受控開啟狀態,不傳則由內部管理 |
onOpenChange | (open: boolean) => void | — | 開啟狀態變更回呼 |
icon | ReactNode | <Plus /> | 觸發鈕圖示;預設圖示開啟時旋轉 45° 成叉號 |
label | string | 「開啟/關閉選單」 | 觸發鈕的無障礙標籤 |
gap | number | 16 | 液滴之間的間距(px) |
itemSize | number | 44 | 項目直徑(px) |
triggerSize | number | 56 | 觸發鈕直徑(px) |
radius | number | 自動推算 | radial 模式的放射半徑(px) |
closeOnSelect | boolean | true | 點擊項目後是否自動收合 |
className | string | — | 追加到根容器的 className |
GooeyMenuItem
| 欄位 | 型別 | 說明 |
|---|---|---|
icon | ReactNode | 圖示(建議 lucide-react,尺寸由元件統一控制) |
label | string | 無障礙標籤,同時作為懸停/聚焦時的提示文字 |
onClick | () => void | 點擊回呼 |
href | string | 若提供則此項渲染為連結 <a> |
className | string | 追加到此項按鈕的 className |
細節
- goo 濾鏡:液體層套上 SVG
feGaussianBlur+feColorMatrix——先模糊、再拉高 alpha 對比,使觸發鈕與項目的圓形背景融成一團有機黏滯的液面;濾鏡 id 以useId產生,同頁多個選單不會互相污染 - 雙層結構:純色液滴背景與圖示分屬兩層——背景層負責黏滯融合,圖示與點擊互動放在不套濾鏡的上層,因此圖示始終清晰、不受模糊影響
- 黏滯拉扯:收合時所有項目縮回觸發鈕中心並藏於同色液滴內;展開時由近而遠、收合時由遠而近地錯開時序,配合 spring 讓液滴像被「拉」出又「吸」回
- 方向與放射:
up/down/left/right沿單軸等距排開,radial以正上方為中心展成扇形(項目越多扇面越寬)
可及性
- 觸發鈕為原生
<button>,帶aria-haspopup="menu"、aria-expanded與aria-controls;項目容器為role="menu"、各項為role="menuitem" - 完整鍵盤支援:於觸發鈕按方向鍵即開啟並聚焦首項;項目間以 roving tabindex 搭配方向鍵/Home/End 巡覽;Esc 收合並將焦點歸還觸發鈕
- 點擊選單外部自動收合;每個項目以
aria-label命名,懸停或聚焦時另顯示視覺提示標籤(標籤本身aria-hidden,避免重複朗讀) - 液體層與濾鏡皆標記
aria-hidden,純裝飾不干擾輔助科技 - 使用者系統開啟「減少動態效果」時,液滴的錯落時序、按壓與懸停縮放皆停用,改為即時開闔(DOM 結構不變)