導航

Fullscreen Menu

Nike 風格的全螢幕覆蓋選單,底幕由上而下揭幕、選單項目以階梯式錯開自遮罩下方向上滑入。

這是 WebberUI Pro 元件

下方的安裝指令需要授權才能執行,未授權時會回 401。

怎麼安裝 Pro 元件 →查看方案 →

把這個效果裝進你的專案

在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。

npx webberui@latest add "https://webberui.com/r/fullscreen-menu.json?t=<安裝 token>"

還沒有專案,或安裝遇到問題?看快速開始 →

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

編輯中的呼叫預設屬性
<FullscreenMenu/>

完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。

安裝

npx webberui@latest add "https://webberui.com/r/fullscreen-menu.json?t=<安裝 token>"

或在 components.json 設定 registries 後,改用 @webberui/fullscreen-menu 安裝。

使用

import {
  FullscreenMenu,
  FullscreenMenuTrigger,
  FullscreenMenuContent,
  FullscreenMenuItem,
} from "@/components/ui/fullscreen-menu";

<FullscreenMenu>
  <FullscreenMenuTrigger>開啟選單</FullscreenMenuTrigger>

  <FullscreenMenuContent>
    <FullscreenMenuItem href="#men" index="01">
      男子
    </FullscreenMenuItem>
    <FullscreenMenuItem href="#women" index="02">
      女子
    </FullscreenMenuItem>
    <FullscreenMenuItem href="#sport" index="03">
      運動系列
    </FullscreenMenuItem>
  </FullscreenMenuContent>
</FullscreenMenu>;

點擊觸發鈕後,底幕由畫面頂端向下揭幕,接著各 FullscreenMenuItem 依序自遮罩下方向上滑入。點擊底幕、按右上角關閉鈕或 Esc 皆可關閉;項目點選後預設自動關閉。

FullscreenMenuItem 有 href 時渲染為 <a>,否則為 <button>,可搭配 onSelect 處理點選行為:

<FullscreenMenuItem onSelect={() => router.push("/men")} index="01">
  男子
</FullscreenMenuItem>;

傳入 open 與 onOpenChange 可切換為受控模式(例如由外部的漢堡鈕控制):

const [open, setOpen] = React.useState(false);

<FullscreenMenu open={open} onOpenChange={setOpen}>
  {/* ... */}
</FullscreenMenu>;

Props

FullscreenMenu

Prop型別預設值說明
childrenReact.ReactNode—內容,需包含 FullscreenMenuTrigger 與 FullscreenMenuContent
openboolean—受控模式的開啟狀態,不傳則由元件內部管理
onOpenChange(open: boolean) => void—開啟狀態變更時的回呼(受控與非受控皆會觸發)

FullscreenMenuTrigger

Prop型別預設值說明
childrenReact.ReactNode—觸發鈕內容
classNamestring—追加到觸發鈕的 className

FullscreenMenuContent

Prop型別預設值說明
childrenReact.ReactNode—覆蓋層內容,通常為若干 FullscreenMenuItem
align"start" | "center""start"選單項目的水平對齊方式
labelstring"主選單"覆蓋層的無障礙標籤(套用到 role="dialog")
classNamestring—追加到覆蓋層容器的 className

FullscreenMenuItem

Prop型別預設值說明
childrenReact.ReactNode—項目文字
hrefstring—有值時渲染為 <a>;否則為 <button>
indexstring—選填的序號標籤(如 "01"),顯示在項目前方
onSelect() => void—點擊選取時的回呼
closeOnSelectbooleantrue選取後是否自動關閉選單
classNamestring—追加到項目連結的 className

FullscreenMenuClose

Prop型別預設值說明
childrenReact.ReactNodelucide-react X 圖示自訂按鈕內容
classNamestring—追加到關閉按鈕的 className

細節

  • 階梯式揭示:清單容器以 staggerChildren 對各項目錯開觸發時間,每個項目外層是 overflow-hidden 的靜態遮罩,內部連結才做 y 位移,因此文字像是從遮罩邊緣「升起」,形成 Nike 風格的乾淨裁切邊。退場時以 staggerDirection: -1 反向收合。
  • 由上而下的底幕:底幕以 scaleY(transformOrigin: top)由畫面頂端向下揭幕,退場時延遲一小段再收回,讓項目先退場、底幕最後才闔上。
  • Portal 到 body:覆蓋層與底幕經 createPortal 渲染到 document.body,避免祖先的 overflow 裁切或 transform 建立 containing block 影響 fixed 定位。
  • pointer-events 分層:對話層預設 pointer-events-none,讓覆蓋層以外的點擊落到底幕(點擊即關閉),只有連結、關閉鈕等互動元素自身恢復 pointer-events。
  • 受控模式:傳入 open 即切換為受控,元件不再改動內部狀態;onOpenChange 在受控與非受控下都會觸發,可用來與外部導覽狀態同步。
  • 可調校點:hover 與圖示的過渡時長取用 var(--wb-duration-fast, 200ms),緩動取用 var(--wb-ease-out, cubic-bezier(0.22,1,0.36,1)),未定義時回退預設值。

可及性

  • 覆蓋層帶 role="dialog"、aria-modal="true" 與 aria-label;開啟時焦點移入覆蓋層(tabIndex={-1}),關閉後焦點歸還給觸發鈕
  • 觸發鈕為原生 <button>,帶 aria-haspopup="dialog" 與 aria-expanded 狀態,開啟時以 aria-controls 連結覆蓋層
  • 選單以 <nav> 與 <ul>/<li> 語意結構承載,項目依 href 渲染為 <a> 或 <button>,皆可鍵盤聚焦與操作
  • 按 Esc 或點擊底幕皆可關閉;開啟期間 body 設為 overflow: hidden 鎖住背景捲動,關閉時恢復原值
  • 使用者系統開啟「減少動態效果」時,底幕與項目退化為快速淡入淡出,不產生任何位移感
  • 元件走輕量路線,未內建 focus trap;若覆蓋層內互動元素較多且需要完整的鍵盤焦點循環,建議自行搭配 focus trap 方案