Mega Menu
大型下拉導覽選單,切換項目時面板高度自適應平滑 morph,支援懸停與鍵盤操作。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
150
<MegaMenu />
安裝
npx shadcn@latest add https://webberui.com/r/mega-menu.json或在 components.json 設定 registries 後,改用 @webberui/mega-menu 安裝。
安裝依賴後,從 registry JSON(/r/mega-menu.json 的 files[0].content)複製 mega-menu.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion clsx tailwind-merge lucide-react使用
以 compound components 組合。每個 MegaMenuItem 需帶唯一的 value,並包含一個 MegaMenuTrigger 與一個 MegaMenuContent。
import {
MegaMenu,
MegaMenuList,
MegaMenuItem,
MegaMenuTrigger,
MegaMenuContent,
} from "@/components/ui/mega-menu";
<MegaMenu align="center">
<MegaMenuList label="主導覽">
<MegaMenuItem value="products">
<MegaMenuTrigger>產品</MegaMenuTrigger>
<MegaMenuContent>{/* 大型面板內容 */}</MegaMenuContent>
</MegaMenuItem>
<MegaMenuItem value="resources">
<MegaMenuTrigger>資源</MegaMenuTrigger>
<MegaMenuContent>{/* 另一組內容,高度可不同 */}</MegaMenuContent>
</MegaMenuItem>
</MegaMenuList>
</MegaMenu>不同項目的面板內容尺寸不同時,切換時容器會自動 morph 高度與寬度,而非瞬間跳動。
受控模式
傳入 value(展開的項目 value,null 為收合)與 onValueChange 即可接管開闔狀態;不傳則由元件內部管理。
const [open, setOpen] = useState<string | null>(null);
<MegaMenu value={open} onValueChange={setOpen}>
{/* ... */}
</MegaMenu>Props
MegaMenu
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
value | string | null | — | 受控模式的展開項目,null 為收合 |
defaultValue | string | null | null | 非受控模式的初始展開項目 |
onValueChange | (value: string | null) => void | — | 展開項目變更時的回呼 |
align | "start" | "center" | "end" | "start" | 面板相對導覽列的水平對齊 |
closeDelay | number | 150 | 滑鼠移出後延遲關閉的毫秒數 |
MegaMenuList
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
label | string | "主導覽" | 導覽列(nav)的無障礙名稱 |
className | string | — | 追加到導覽列容器的 className |
MegaMenuItem
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
value | string | — | 此項目的唯一識別(必填) |
className | string | — | 追加到項目容器(li)的 className |
MegaMenuTrigger / MegaMenuContent
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | ReactNode | — | 觸發鈕內容 / 面板內容 |
className | string | — | 追加的 className(Content 套用於內容區) |
細節
- 單一容器 morph:各
MegaMenuContent於 render 時把內容登記到共享集合,由內部 Viewport 集中渲染於同一個帶layout的容器;切換項目時以popLayout讓離場面板脫離排版流,容器立即依新內容量測並補間高度。 - 懸停意圖:滑鼠移入觸發鈕即展開,移出導覽列後延遲
closeDelay才關閉,留出移動到面板的緩衝;再次移入會取消關閉。 - 面板即在導覽列下方:面板為
nav內的絕對定位子節點,不使用 portal,滑鼠在觸發鈕與面板之間移動不會誤觸關閉。
可及性
- 觸發鈕為原生
button,帶aria-haspopup、aria-expanded與展開時的aria-controls,指向面板區域(role="region")。 - 鍵盤操作:
Enter/Space切換展開;ArrowLeft/ArrowRight與Home/End於觸發鈕之間移動(面板已開時同步切換);ArrowDown展開並將焦點移入面板;Escape關閉並將焦點歸還觸發鈕。 - 點擊導覽列以外區域會關閉面板。
- 使用者系統開啟「減少動態效果」時,停用高度 morph 與位移縮放,僅保留短暫淡入淡出。