WebberUI

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.jsonfiles[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(展開的項目 valuenull 為收合)與 onValueChange 即可接管開闔狀態;不傳則由元件內部管理。

const [open, setOpen] = useState<string | null>(null);

<MegaMenu value={open} onValueChange={setOpen}>
  {/* ... */}
</MegaMenu>

Props

MegaMenu

Prop型別預設值說明
valuestring | null受控模式的展開項目,null 為收合
defaultValuestring | nullnull非受控模式的初始展開項目
onValueChange(value: string | null) => void展開項目變更時的回呼
align"start" | "center" | "end""start"面板相對導覽列的水平對齊
closeDelaynumber150滑鼠移出後延遲關閉的毫秒數

MegaMenuList

Prop型別預設值說明
labelstring"主導覽"導覽列(nav)的無障礙名稱
classNamestring追加到導覽列容器的 className

MegaMenuItem

Prop型別預設值說明
valuestring此項目的唯一識別(必填)
classNamestring追加到項目容器(li)的 className

MegaMenuTrigger / MegaMenuContent

Prop型別預設值說明
childrenReactNode觸發鈕內容 / 面板內容
classNamestring追加的 className(Content 套用於內容區)

細節

  • 單一容器 morph:各 MegaMenuContent 於 render 時把內容登記到共享集合,由內部 Viewport 集中渲染於同一個帶 layout 的容器;切換項目時以 popLayout 讓離場面板脫離排版流,容器立即依新內容量測並補間高度。
  • 懸停意圖:滑鼠移入觸發鈕即展開,移出導覽列後延遲 closeDelay 才關閉,留出移動到面板的緩衝;再次移入會取消關閉。
  • 面板即在導覽列下方:面板為 nav 內的絕對定位子節點,不使用 portal,滑鼠在觸發鈕與面板之間移動不會誤觸關閉。

可及性

  • 觸發鈕為原生 button,帶 aria-haspopuparia-expanded 與展開時的 aria-controls,指向面板區域(role="region")。
  • 鍵盤操作:Enter / Space 切換展開;ArrowLeft / ArrowRightHome / End 於觸發鈕之間移動(面板已開時同步切換);ArrowDown 展開並將焦點移入面板;Escape 關閉並將焦點歸還觸發鈕。
  • 點擊導覽列以外區域會關閉面板。
  • 使用者系統開啟「減少動態效果」時,停用高度 morph 與位移縮放,僅保留短暫淡入淡出。

On this page