下拉式選單與選單系統
目的
下拉式選單與選單系統技能提供一個標準化框架,用於設計網頁介面中的浮動動作選單、溢出選單、上下文選單及階層式子選單。下拉式選單顯示一個組織化的互動命令、選項或子動作列表,這些列表依附於觸發元素(如圖示按鈕、分割按鈕或上下文動作)。
設計一個有效的下拉式選單系統需要在空間佈局、視覺層級、項目分組、鍵盤導覽語意、碰撞處理(視窗邊界)以及觸控行動裝置的響應式適配之間取得平衡,同時不讓使用者迷失方向,並符合 WCAG 2.1 AA 無障礙規範。
使用案例
- 動作與選項選單: 在資料表格、卡片或頁面標題中,顯示依附於觸發按鈕的次要頁面或行動作(例如「編輯」、「複製」、「匯出」、「刪除」)。
- 溢出與更多選單: 當容器空間受限時,容納優先級較低的工具或導航連結(例如工具列或表格標題中的「...」按鈕)。
- 上下文彈出選單: 在特定視覺畫布或列表項目上,透過右鍵或長按觸發顯示有針對性的上下文指令。
- 階層式子選單: 在多層選單覆蓋層中組織巢狀動作或多層級類別選項。
- 選擇動作選單(可勾選與單選項目): 在浮動動作面板中切換檢視狀態、欄位可見性或排序偏好。
何時不該使用
- 表單選擇輸入(下拉式方塊與選取輸入): 對於使用者選取單一或多個值以填入欄位的表單輸入(如選取國家或產品類別),請使用
custom-select-and-combobox-system。 - 高密度導航面板: 對於包含結構化類別、登陸頁面與行銷促銷的多欄全域網站導航,請使用
mega-menu-navigation-system。 - 大型模態與任務工作區: 對於複雜的子任務、多欄位編輯或需要保留焦點的多步驟精靈表單,請使用
overlay-and-dialog-system或bottom-sheet-design-system。 - 上下文說明與工具提示: 對於非互動式、懸停/聚焦的文字描述來說明元素功能,請使用
tooltip-and-hint-system。
輸入
- 觸發元件與幾何形狀: 主要觸發元素類型(標準按鈕、圖示按鈕、分割按鈕或右鍵目標區域)與空間定位。
- 選單項目清單與階層: 動作列表、項目類型(標準、可勾選、單選、破壞性)、圖示、鍵盤快捷鍵、分隔線與群組章節標籤。
- 表面與高度標記: 背景表面顏色、邊框樣式、投影標記(
--elevation-popover)與 z-index 定位(--z-popover),來自elevation-and-depth-system與accessible-color-system。 - 視窗與裝置上下文: 裝置方向、螢幕寬度斷點與觸控支援特性。
輸出
- 選單結構與佈局藍圖: CSS 與 HTML 結構規格,涵蓋選單容器尺寸、內邊距、項目對齊、尾隨快捷提示與章節分隔線間距。
- 空間定位與碰撞策略: 錨點定位(上/下/左/右)、對齊、動態翻轉/滑動邏輯,以及最大高度可滾動邊界的佈局規則。
- 響應式行動裝置適配模型: 在行動視窗中,將窄桌面下拉式選單轉換為底部動作表(
bottom-sheet-design-system)或全寬觸控列表的設計規格。 - ARIA 與鍵盤導覽規格: 程式化無障礙規則,涵蓋 ARIA 角色(
role="menu"、role="menuitem"、role="menuitemcheckbox"、role="menuitemradio")、展開狀態(aria-expanded)與方向鍵焦點管理。
工作流程
1. 定義選單結構與項目結構
將選單中的項目分類為邏輯功能組,以最大化可掃描性:
- 標題與章節標籤: 使用大寫微字體或微妙章節標題來分組相關動作(
font-size: 0.75rem、font-weight: 600、letter-spacing: 0.05em)。 - 標準項目組成: 使用 flexbox 水平對齊元素(
gap: 0.75rem):- 前導圖示: 16x16px 或 20x20px 圖示,說明動作目的。
- 標籤文字: 簡潔、以動作為導向的動詞(例如「下載 PDF」、「複製項目」)。
- 尾隨快捷提示: 等寬字體的鍵盤快捷鍵文字(例如
⌘E、Ctrl+D),視覺上淡化(color: var(--text-tertiary))。 - 尾隨箭頭: 表示階層式子選單觸發器(
>)。
- 特殊項目類型:
- 可勾選項目(
role="menuitemcheckbox"): 啟用時顯示前導勾選標記。 - 單選項目(
role="menuitemradio"): 在群組中選中時顯示單選點。 - 破壞性項目: 使用獨特的警告顏色標記(
color: var(--color-danger))來樣式化負面動作(如「刪除」、「移除」),並透過視覺分隔線與良性動作分開。
- 可勾選項目(
- 分隔線(
role="separator"): 使用微妙的水平規則(1px solid var(--border-subtle))來劃分不同的動作群組(例如將檢視動作與編輯/刪除動作分組)。
2. 建立空間定位與碰撞處理
設定佈局規則,使選單在觸發器旁邊清晰呈現,且不超出螢幕邊緣:
- 錨點對齊: 相對於觸發按鈕邊界定位選單彈出視窗:
- 底部-左 / 底部-右: 觸發按鈕下方的預設定位。當觸發器靠近右側螢幕邊界時,向右邊緣對齊(例如資料表格列動作欄)。
- 頂部-左 / 頂部-右: 當靠近視窗底部時,方向翻轉至觸發按鈕上方。
- 視窗碰撞與翻轉規則:
- 與螢幕邊緣保持至少 12px 的外邊距(
viewport-margin: 12px)。 - 設定最大高度限制(
max-height: calc(100vh - 32px)),並為長選單啟用內部垂直滾動(overflow-y: auto)。
- 與螢幕邊緣保持至少 12px 的外邊距(
- 高度標記: 應用頂層堆疊(
z-index: var(--z-popover))與陰影(box-shadow: var(--shadow-popover)),將浮動選單與背景表格行或卡片視覺上分開。
3. 配置互動與子選單動態
- 觸發狀態: 確保觸發按鈕使用
aria-expanded="true"指示開啟狀態,並具有微妙的按壓視覺狀態(background-color: var(--bg-hover))。 - 子選單懸停與鍵盤延遲:
- 階層式子選單在滑鼠懸停時開啟,並帶有輕微的意圖延遲(150–200ms 意圖計時器),以防止指標移動時意外觸發閃爍。
- 在子選單觸發器上按
ArrowRight展開子選單並將焦點移入;ArrowLeft關閉子選單並將焦點返回上層選單項目。
- 關閉觸發: 在以下情況下關閉開啟的選單覆蓋層:
- 使用者點擊選單面板外部(點擊外部監聽器)。
- 使用者按下
Escape鍵。 - 執行了有效的選單項目動作(除非是可勾選的切換項目)。
- 焦點離開選單覆蓋層。
4. 設計響應式行動裝置適配
桌面浮動下拉式選單(例如 220px 浮動方塊)在行動觸控螢幕上表現不佳,因為觸控目標小且定位需求精確:
- 行動觸控轉換(
< 768px):- 將桌面彈出視窗轉換為底部動作表(
bottom-sheet-design-system),固定於視窗底部。 - 將項目行高增至最小觸控目標 44px(最好 48px),並提供全寬水平觸控區域。
- 提供明確的視覺拖曳手柄或底部的「取消」按鈕,以便輕鬆用拇指關閉。
- 將桌面彈出視窗轉換為底部動作表(
- 觸控回饋: 應用不同的活動觸控背景狀態(
:active)以提供即時觸覺回饋。
5. 程式化無障礙與鍵盤語意
- ARIA 地標與角色對應:
- 設定觸發按鈕:
aria-haspopup="menu"、aria-expanded="true|false"、aria-controls="menu-id"。 - 設定選單容器:
role="menu"、aria-labelledby="trigger-id"、tabindex="-1"。 - 設定選單項目:
role="menuitem"、role="menuitemcheckbox"或role="menuitemradio"。
- 設定觸發按鈕:
- 鍵盤導覽模型:
Enter/Space/ArrowDown在觸發器上:開啟選單並聚焦第一個選單項目。ArrowDown/ArrowUp:依序在選單項目間移動焦點(從上到下循環)。Home/End:直接將焦點移至第一個或最後一個選單項目。Escape:立即關閉選單並將焦點返回觸發按鈕。Tab:立即關閉選單並允許標準文件焦點推進。- 打字搜尋(Typeahead Character Search): 按下字母鍵(例如「D」)直接將焦點移到下一個以該字母開頭的選單項目。
決策規則
選單類型與上下文選擇
| 上下文 / 目標 | 建議模式 | ARIA 結構 | 行動裝置適配 |
|---|---|---|---|
| 行 / 卡片動作 | 動作下拉式選單 | role="menu" / role="menuitem" | 底部動作表 |
| 工具列溢出(「...」) | 溢出選單 | role="menu" / role="menuitem" | 底部動作表 |
| 右鍵畫布工具 | 上下文選單 | role="menu" / role="menuitem" | 長按底部表 |
| 表單選項選取 | 下拉式方塊選取 | role="combobox" / role="option" | 原生選取 / 底部表 |
| 多層檢視 / 篩選切換 | 可勾選動作面板 | role="menu" / role="menuitemcheckbox" | 底部動作表 |
定位與對齊規則
- 資料表格列選單: 定位於觸發按鈕的右上或右下對齊,以防止超出右側表格視窗邊緣的水平截斷。
- 標題 / 導航動作: 根據與螢幕邊緣的距離,定位於右下或左下。
- 子選單: 預設向右開啟(
left: 100%);如果右側空間小於 200px,則翻轉向左開啟(right: 100%)。
限制條件
- 無障礙(WCAG 2.1 AA):
- SC 1.4.3 對比度(最低): 項目文字、圖示與鍵盤提示必須與選單背景維持至少 4.5:1 的對比度。
- SC 2.1.1 鍵盤: 選單內的每個項目和動作都必須完全可透過鍵盤存取和觸發。
- SC 2.4.7 焦點可見: 聚焦的選單項目必須具有明顯的視覺焦點狀態(例如背景顏色變化 + 符合對比度的醒目指示器)。
- SC 2.5.8 目標尺寸: 桌面選單項目必須維持至少 32px 高度;行動動作表項目必須滿足至少 44x44px 的觸控目標。
- 視窗邊界限制: 開啟的選單絕不能延伸到螢幕外或造成水平頁面滾動條。使用碰撞翻轉和內部垂直滾動(
max-height)。 - 空間內邊距與密度: 維持一致的內部水平內邊距(例如
padding: 0.5rem 0.75rem)與垂直容器內邊距(padding: 0.25rem 0)。
常見失敗模式
- 表單下拉式方塊混淆: 對表單選取下拉式選單使用
role="menu"而非role="combobox"/role="listbox",使螢幕閱讀器混淆值選取與指令執行。 - 關閉時焦點迷失: 當選單透過
Escape或選取關閉時,未能將鍵盤焦點恢復到觸發按鈕,導致焦點遺失在document.body。 - 容器裁剪陷阱: 將下拉式選單放置在具有
overflow: hidden的表格儲存格或容器中,導致開啟的選單被視覺裁剪。 - 行動裝置觸控目標過小: 在觸控螢幕上渲染 24px 的桌面下拉式選單項目,而未將其轉換為觸控友善的底部表。
- 意外子選單關閉: 階層式子選單缺乏意圖計時器延遲,導致當滑鼠對角線移動到子項目時,子選單折疊。
驗證標準
- 選單容器使用適當的 ARIA 語意(
role="menu"、role="menuitem"、role="separator")。 - 鍵盤導覽完全支援
ArrowDown、ArrowUp、Home、End、Escape與字母打字搜尋。 - 關閉選單(透過
Escape或項目點擊)會以程式化方式將焦點恢復到觸發元素。 - 視窗碰撞規則能乾淨地翻轉或滾動長選單,而不會造成螢幕溢出。
- 響應式斷點(
< 768px)將桌面下拉式選單轉換為觸控友善的底部動作表。 - 項目文字、快捷提示與焦點指示器背景滿足 WCAG AA 對比度(≥4.5:1)。