Bottom Sheet 設計系統
目的
Bottom Sheet 設計系統提供一個標準化、以行動裝置為優先的設計框架,用於 Web 介面及漸進式 Web 應用程式 (PWA) 中的滑出式底部面板、動作面板及模態底部抽屜。現代行動裝置具有較大的長寬比,使得頂部覆蓋層和置中模態彈出視窗難以單手觸及。底部面板將互動任務、情境選單、篩選控制項及詳細子視圖錨定在螢幕底部,位於使用者拇指的自然觸及範圍內。
設計有效的底部面板系統需要建立卡榫吸附高度(輕窺/折疊、部分/半高、全高)、觸控拖曳操控元件(拖曳手柄)、背景變暗(遮罩/背幕)、主體滾動鎖定機制、視口安全區域內邊距 (env(safe-area-inset-bottom)),以及無縫的響應式桌面轉換(在較寬的視口上將底部面板轉換為置中模態或彈出選單)。
使用案例
- 行動裝置產品選項選擇器: 在電子商務產品詳細頁面上呈現尺寸、顏色、數量和訂閱週期選擇器,無需離開 PDP。
- 行動裝置篩選與排序控制項: 為電子商務目錄頁面或 SaaS 搜尋檢視提供多面向篩選選項,並帶有持續顯示的「套用篩選」動作列。
- 情境動作面板: 在社交動態、媒體卡片或資料表格上觸發一鍵快速動作(分享、書籤、加入清單、檢舉)。
- 地點與地圖詳細資料卡片: 顯示可展開的興趣點詳細資訊或送貨追蹤時間軸,從地圖檢視上方滑出(從輕窺卡榫到全高展開)。
- 行動裝置多步驟子工作流程: 完成快速的內聯任務,例如結帳付款方式選擇、地址選取或快速意見回饋提交。
何時不該使用
- 全域導航路由: 對於跨主要區塊的主要應用程式導航,請使用
bottom-navigation-system或site-navigation-system。 - 破壞性確認警示: 對於關鍵、不可逆的操作(例如「刪除帳戶」),請使用置中的
overlay-and-dialog-system模態對話框 (role="alertdialog"),要求明確確認。 - 頁面內可折疊內容: 若要在頁面流程中切換內聯可展開內容,請使用
accordion-ui-system或tab-ui-system。 - 寬螢幕桌面佈局 (>1024px): 請勿在桌面螢幕上顯示全寬的底部面板。應將 UI 調整為置中模態對話框 (
overlay-and-dialog-system)、側邊抽屜 (dashboard-layout-system) 或錨定彈出選單 (tooltip-and-hint-system)。
輸入
- 任務類型與深度: 內容的性質(快速一鍵動作清單 vs. 多欄位表單 vs. 可滾動詳細清單)。
- 卡榫配置: 吸附高度的選擇(單一卡榫:100% 全高;雙重卡榫:50% 半高與 100% 全高;三重卡榫:20% 輕窺、50% 半高、90% 全高)。
- 觸發上下文: 啟動面板的元素或使用者動作(按鈕點擊、長按、滑動手勢或深度連結)。
- 設計 Token: 表面背景顏色、邊框圓角、拖曳手柄尺寸、投影陰影、背景遮罩透明度以及字體排印比例。
- 桌面適應策略: 針對 1024px 以上視口所選擇的佈局轉換方式(轉換為置中模態、轉換為錨定彈出選單,或轉換為滑入式側邊抽屜)。
輸出
- Bottom Sheet 結構規格: 定義拖曳手柄列、頁首(標題 + 關閉按鈕)、可滾動主體、固定頁尾(CTA 按鈕列)以及安全區域內邊距的佈局藍圖。
- 卡榫高度與手勢 Token 矩陣: CSS 變數與吸附臨界值定義 (
--sheet-detent-peek、--sheet-detent-half、--sheet-detent-full),包含拖曳速度關閉規則。 - 背景遮罩與高度規格: 背景遮罩透明度 Token、背景模糊濾鏡設定、z-index 階層,以及主體滾動鎖定規則(主體
overflow: hidden)。 - 鍵盤與螢幕報讀器 ARIA 對應:
role="dialog"、aria-modal="true"、aria-labelledby、焦點陷阱規範,以及Escape按鍵處理器定義。 - 響應式桌面適應藍圖: 將行動裝置底部面板轉換為平板和桌面裝置的置中模態對話框或彈出選單的媒體查詢斷點。
工作流程
1. 分類面板類型與卡榫結構
根據內容數量與互動頻率選擇適當的卡榫模式:
- 非模態動作面板(輕窺/適配內容): 自動調整大小以適應簡短內容(2–5 個選單動作)。高度通常在 180px 到 320px 之間。在選取動作或點擊背景遮罩時關閉。
- 半高 / 雙重卡榫面板(視口的 50% 與 90%): 用於中等密度的任務,例如產品規格選擇或排序。開啟時為 50% 高度 (
50vh);向上拖曳則吸附至 90% 高度 (90vh)。 - 全高 / 可展開面板(視口的 90%–100%): 用於複雜的行動裝置工作流程,例如多面向篩選或結帳步驟。提供固定的頁首和頁尾,以及內部可滾動的主體。
2. 定義視覺結構與空間層級
使用五個不同的結構層級建構面板:
- 背景遮罩: 固定覆蓋整個視口 (
background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(4px); z-index: 1000;)。 - 面板容器: 固定在底部螢幕邊緣 (
position: fixed; bottom: 0; left: 0; right: 0; border-radius: 16px 16px 0 0; background: var(--surface-bg); z-index: 1001;)。 - 拖曳手柄列: 頂部置中的視覺藥丸 (
width: 36px; height: 5px; border-radius: 999px; background: var(--border-neutral); margin: 8px auto; cursor: grab;)。 - 頁首層: 包含面板標題 (
h2)、可選的副標題和明確的關閉按鈕 (<button aria-label="關閉面板">✕</button>)。 - 可滾動主體層: 內部內容容器,配置為
overflow-y: auto; -webkit-overflow-scrolling: touch;。 - 固定頁尾 CTA 層: 底部固定的動作列,帶有主要/次要按鈕和安全區域內邊距 (
padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px)))。
3. 建立手勢、吸附與關閉機制
設定流暢的觸控互動以提供實體手勢回饋:
- 拖曳操控互動: 向下拖曳手柄或頁首,會使用
transform: translateY()平滑地將面板向下移動。 - 吸附臨界值:
- 如果向下拖曳超過目前高度的 30% 或以速度 > 0.5px/ms 向下撥動,則觸發完全關閉。
- 如果在雙重卡榫模式下拖曳介於 30% 到 70% 之間,則吸附到最近的卡榫(50% 或 90%)。
- 滾動鎖定衝突: 在可滾動主體層內拖曳時,僅當主體滾動位置位於
scrollTop === 0且使用者向下滑動時,才啟動面板的拖曳關閉。 - 主體滾動鎖定: 當模態底部面板開啟時,對
document.body套用overflow: hidden,以防止背景頁面滾動外洩。
4. 實施視口安全區域與表面對比
確保與行動裝置硬體顯示器裁切區域及淺色/深色模式完全視覺整合:
- 安全區域內邊距處理: 始終對面板容器或固定頁尾套用
padding-bottom: env(safe-area-inset-bottom, 16px),以使內容/按鈕不會被 iOS Home Indicator 遮擋。 - 最大高度限制: 將全高面板限制在
max-height: calc(100vh - 48px)或max-height: calc(100dvh - 48px),以便在頂部保留 48px 變暗的父頁面上下文。 - 表面陰影: 使用深的投影陰影 Token (
box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.15)) 以與背景頁面內容產生分離感。
5. 配置無障礙與鍵盤導航
確保完全符合 WCAG 2.1 / 2.2 AA 標準:
- ARIA 角色: 容器必須使用
role="dialog"或role="region"(對於非模態輕窺面板)、aria-modal="true"以及aria-labelledby="sheet-title-id"。 - 焦點管理:
- 開啟時,程式化地將焦點移動到面板內的第一個可聚焦元素或關閉按鈕。
- 實施焦點陷阱,防止
Tab或Shift+Tab逃離面板進入惰性背景。 - 關閉時,將焦點恢復到開啟面板的觸發元素。
- 鍵盤控制: 按下
Escape必須立即關閉面板。 - 螢幕報讀器宣告: 面板內部的動態內容變更必須使用
aria-live="polite"區域。
6. 設計響應式桌面適應
當底部面板在桌面顯示器(≥1024px)上拉伸至全寬時會顯得不精緻。實施明確的響應式轉換規則:
- 桌面模態模式(預設): 在 1024px 以上的視口,將底部面板轉換為置中模態對話框 (
width: 100%; max-width: 540px; border-radius: 16px; margin: auto; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);)。 - 桌面彈出選單模式(情境選單): 對於快速動作面板,將其轉換為錨定在觸發按鈕旁的彈出選單。
- 桌面側邊抽屜模式(複雜表單/篩選器): 對於深層多面向篩選或多步驟流程,轉換為右對齊的滑入式側邊抽屜 (
width: 400px; height: 100vh; top: 0; right: 0; border-radius: 16px 0 0 16px;)。
決策規則
卡榫選擇矩陣
| 面板類型 | 卡榫配置 | 內容數量 | 理想使用案例 |
|---|---|---|---|
| 動作面板 | 適配內容(單一卡榫) | 2–6 個動作連結/項目 | 快速分享、情境選單、簡單選項切換。 |
| 選擇面板 | 雙重卡榫(初始 50vh,展開 90vh) | 5–15 個可滾動項目 | 產品尺寸/顏色選取器、地址選擇器、付款方式。 |
| 互動式抽屜 | 三重卡榫(120px 輕窺,50vh,90vh) | 複雜空間/地圖資料 | 送貨追蹤地圖卡片、即時交通站點、共乘詳細資訊。 |
| 完整流程面板 | 單一卡榫(90vh - 100vh 固定) | 多區塊表單/篩選器 | 目錄多面向篩選、行動結帳步驟、問卷調查工作流程。 |
桌面轉換選擇
- 使用置中模態: 當面板包含結構化表單、規格選擇器或結帳選項時。
- 使用錨定彈出選單: 當面板包含簡短的情境動作(分享、編輯、刪除)時。
- 使用側邊抽屜: 當面板包含儀表板和資料表格上的篩選控制項或編輯面板時。
限制條件
- 無障礙 (WCAG 2.1 / 2.2 AA):
- 當
aria-modal="true"啟用時,必須提供明確的焦點陷阱。 - 所有內部項目和關閉按鈕的觸控目標必須至少為 44x44px (WCAG 2.5.8 / 2.5.5)。
- 模態底部面板後方的背景內容必須標記為
inert或對輔助技術隱藏。
- 當
- 觸控與手勢尺寸:
- 即使視覺手柄是 36x5px,拖曳手柄的點擊目標也必須透過不可見內邊距放大(
min-height: 24px、min-width: 60px)。
- 即使視覺手柄是 36x5px,拖曳手柄的點擊目標也必須透過不可見內邊距放大(
- 視口動態單位:
- 在支援的地方使用
dvh(動態視口高度)(例如height: 90dvh),否則回退到vh,以容納行動裝置動態網址列的展開和折疊。
- 在支援的地方使用
常見失敗模式
- 缺少安全區域內邊距: 省略
env(safe-area-inset-bottom),導致主要頁尾動作按鈕與 iOS 手勢列重疊。 - 桌面全寬拉伸面板: 允許行動裝置底部面板在桌面顯示器上擴展到 1920px 寬度。
- 滾動劫持鎖死: 未能將內容滾動與面板拖曳關閉手勢分離,導致使用者嘗試向下滾動文字時面板收合。
- 缺少鍵盤 Escape 處理器: 省略
Escape按鍵事件監聽器,將桌面鍵盤使用者困在模態面板覆蓋層中。 - 焦點洩漏至背景: 在模態底部面板開啟時,背景頁面元素仍可透過
Tab鍵到達。
驗證標準
- 面板佈局包含明確的視覺拖曳操控元件、帶有標題的頁首、可滾動主體和固定頁尾。
- 安全區域內邊距 (
padding-bottom: env(safe-area-inset-bottom)) 已實作於固定頁尾和面板容器上。 - 拖曳手柄點擊區域符合觸控無障礙的最小 44px 高度。
- 面板使用
role="dialog"、aria-modal="true"、aria-labelledby,並在啟用時陷阱焦點。 - 按下
Escape或點擊背景遮罩會關閉模態面板,並將焦點恢復到觸發按鈕。 - 當模態面板開啟時,背景頁面滾動已鎖定 (
overflow: hidden)。 - 1024px 以上的視口能乾淨地將底部面板轉換為置中模態對話框、彈出選單或側邊抽屜。