iT邦幫忙

2026 iThome 鐵人賽

DAY 18
0
Vibe Coding

看得懂、叫得出、驗得過:30 天 VibeCoding UI 元件實戰系列 第 18

Day 18|彈窗要不要鎖住背景?Modal、Non-modal、Alert Dialog 與危險確認

  • 分享至 

  • xImage
  •  

安安~我是ChiYu~

專案結構整理清楚後,我按下成員列上的「停用帳號」。畫面中央立刻出現一張白色卡片,後面有灰色遮罩,右下角還放了一顆紅色按鈕。

看起來非常像完成品。

下面是依照第一版問題重建的錯誤現場,不含真實帳號與個人資料:

停用帳號的錯誤第一版:白色卡片與灰色遮罩已完成,但停用對象不明、危險動作先取得焦點,背景仍可操作

圖 1:彈窗只問「確定要停用嗎」,沒有說停用誰;初始焦點落在危險操作,背景卻仍然能點。

需求其實只有一句:

按停用時跳出一個漂亮的彈窗。

「漂亮」很快就做到了。背景能不能繼續操作、Escape 會不會取消、初始焦點落在哪裡,以及停用後究竟影響誰,全部還在場外排隊。

Vibe Coding 遇到彈窗時,很容易先談卡片寬度、遮罩深淺和按鈕顏色。這些都能調,但使用者一旦被中斷,真正決定介面能不能用的,是:

  1. 他為什麼被攔下來?
  2. 現在必須回應什麼?
  3. 背景工作還能不能繼續?
  4. 如果不想做,能不能安全離開?
  5. 關閉後會回到哪裡?

今天就依中斷程度拆開 Dialog、Modal Dialog、Non-modal Dialog 與 Alert Dialog,再補上一個常見的危險確認情境。Confirmation Dialog 是產品情境名稱,不是另一個獨立的 ARIA 角色;真正實作時,仍要選擇 dialogalertdialog

我把這些差異放進 Vibe UI Atlas 的 Dialog 家族比較頁

Vibe UI Atlas 的 Dialog 家族比較:先判斷中斷程度,再決定 Dialog 類型

圖 2:白色卡片和灰色遮罩只能說明外觀;是否中斷背景、需不需要立即回應,才決定 Dialog 類型。

危險確認開啟後,我先按 Escape

我實際打開網站上的 Confirmation Dialog,沒有急著按「停用帳號」。第一個動作是確認焦點落在哪裡,接著按 Escape。

Demo 的結果是:

  • 初始焦點停在安全的「取消」。
  • 按下 Escape 後,林子安的帳號沒有被停用。
  • Dialog 關閉。
  • 焦點回到原本的「停用成員帳號」按鈕。
  • 畫面顯示「已用 Escape 取消,將回到開啟按鈕」。
我檢查的瞬間 實際結果 我為什麼在意
Dialog 剛開啟 焦點先停在「取消」。 使用者不會順手按 Enter 就執行危險動作。
按下 Escape Dialog 關閉,帳號狀態不變。 鍵盤使用者有可預期的撤退方式。
Dialog 關閉 焦點回到觸發按鈕。 不必從頁首重新尋找剛才的位置。
危險動作文案 按鈕寫「停用帳號」,沒有只寫「確定」。 執行前還能再確認真正後果。

這段測試沒有華麗動畫,卻比紅色按鈕更能決定危險確認是否安全。

Prompt 只寫「做一個刪除確認視窗」,AI 很可能把外觀做對,焦點卻直接放到危險操作;關閉後,也可能把使用者送回頁面最上方。紅色只是提醒,取消路徑才是使用者尚未做決定時的保險。

先排一張中斷梯子,再決定 Dialog 類型

當下情境 背景能否操作 使用者需要回應什麼 合適的元件
查看輔助資訊,同時還要對照原頁 可以 看完、自行關閉或繼續背景工作 Non-modal Dialog
短暫完成一個聚焦的小任務 不可以 完成、取消或關閉 Modal Dialog
系統出現不可忽略、必須當場處理的警示 不可以 理解訊息並明確回應 Alert Dialog
即將停用帳號、刪除草稿或覆蓋資料 通常不可以 確認對象與後果,再取消或執行 危險確認情境;依需求使用 Modal Dialog 或 Alert Dialog

這張表可以擋下兩種相反的誤用:

  • 使用者還需要比對原頁資料,卻為了一張浮動卡片鎖住整個背景。
  • 危險操作真的需要停下來確認,背景卻照樣可點。

Dialog 的中斷程度與焦點路徑:從任務風險選擇元件,並在關閉後把焦點還給入口

圖 3:先看背景工作是否能繼續,再判斷訊息重要性與動作風險;關閉後的焦點路徑也要一起規劃。

Dialog 是家族名稱,Modal 與 Non-modal 才回答背景規則

Dialog 元件頁示範一個暫時浮在目前頁面上的內容區域。

Vibe UI Atlas 的 Dialog 實際 Demo:在目前頁面上暫時顯示一段局部資訊

圖 4:Dialog 只是一個統稱;背景是否暫停,仍要由任務情境決定。

畫面浮在上面,不會自動讓它變成 Modal。真正的分界是使用者能不能繼續操作背景,以及不先處理 Dialog 會不會造成問題。

Modal Dialog:背景真的要暫停

Modal Dialog 元件頁使用邀請成員的確認工作。送出前需要核對收件人與角色,在確認或取消以前,背景的成員列表不應再被誤點。

Vibe UI Atlas 的 Modal Dialog 實際 Demo:背景暫停、焦點移入並提供關閉路徑

圖 5:Modal Dialog 要求使用者先處理眼前任務,背景不可操作,關閉後焦點回到入口。

模態不是比較有質感的外觀,而是暫時中斷背景工作。一個可用的 Modal Dialog 至少要完成:

  • 開啟後,焦點進入 Dialog 裡的合理位置。
  • Tab 與 Shift + Tab 不會跑回背景。
  • 背景真的不可操作,不只是蓋上一層遮罩。
  • 有明確的完成、取消或關閉方式。
  • 關閉後,焦點回到合理位置,通常是原本的開啟按鈕。

W3C 的 Modal Dialog Pattern 也要求開啟時把焦點移進 Dialog,關閉後通常回到觸發元素。至於初始焦點,沒有一個位置適合所有彈窗,要依內容與任務決定。W3C WAI-ARIA APG:Modal Dialog Pattern

這次處理高風險操作,因此焦點先放在「取消」。如果 Dialog 是一份長篇條款,初始焦點可能先放在標題或可閱讀內容;若是單一安全任務,也可能放在主要欄位。規格需要說理由,不是背一條永遠把焦點放左邊的規則。

Non-modal Dialog:浮在上面,背景仍能工作

管理員查看成員資料時,可能想開一個小型檢視器確認最近登入時間與角色,同時繼續整理背景清單。Non-modal Dialog 元件頁就是這種情境。

Vibe UI Atlas 的 Non-modal Dialog 實際 Demo:浮在上方但仍可繼續操作背景工作

圖 6:Non-modal Dialog 提供暫時工具或參考資訊,背景工作仍然可以繼續。

最容易出現的 bug,是畫面沒有遮罩,程式卻加上 aria-modal="true" 或把焦點鎖在 Dialog 裡。視覺說背景可以用,鍵盤行為卻把人困住,兩邊各自宣布一套規則。

HTML 原生 <dialog> 可以透過 show() 開啟為非模態,也能以 showModal() 進入模態狀態。差別仍在是否阻斷背景互動,不在 CSS 長得像不像。MDN:<dialog>

Non-modal 也不是「完全不用管理焦點」。開啟後要讓使用者知道面板已出現,能在背景與面板之間移動,也能清楚關閉。若浮層遮住正在操作的資料,還要能移動、收合或選擇更合適的位置。

Alert Dialog:重要訊息才值得中斷

Alert Dialog 元件頁處理使用者必須讀到並回應的訊息,例如權限異常,或不理解就無法安全繼續的系統狀況。

Vibe UI Atlas 的 Alert Dialog 實際 Demo:網站畫面顯示同步失敗訊息與回應按鈕

圖 7:Demo 把同步失敗放進 Alert Dialog;但如果使用者不必立刻回應,頁內 Alert 或 Banner 會更合適。

「有 3 位成員的權限尚未同步,請稍後重試。」雖然重要,卻不一定需要 Alert Dialog。若使用者看完仍能繼續其他工作,頁內 Alert 或 Banner 已經足夠;硬要他再按一次「我知道了」,只是在失敗之外附贈一次中斷。

比較適合 Alert Dialog 的情境是:

權限同步失敗,現在無法安全完成停用。請重新驗證,或取消這次操作。

使用者必須當場選擇,工作才能繼續。W3C 將 Alert Dialog 定義為會中斷流程、傳達重要訊息並取得回應的模態對話框;若訊息只需要被讀到、不需要立刻回應,通常應使用 Alert,而不是把背景一起鎖住。W3C WAI-ARIA APG:Alert Dialog PatternW3C WAI-ARIA APG:Alert Pattern

Alert Dialog 不是靠按鈕數量或紅色面積製造重要感。訊息、原因與下一步寫清楚,比多一顆「我知道了」更有用。

危險確認:對象、後果與取消出口都要在場

停用帳號、刪除專案、清空資料與覆蓋內容都會造成明確後果。Confirmation Dialog 元件頁讓使用者在動作前看見對象、影響與取消出口。

Vibe UI Atlas 的 Confirmation Dialog 實際 Demo:清楚顯示要停用的帳號、後果、取消與 Danger 動作

圖 8:對話框直接寫出要停用林子安、停用後的影響,以及「取消」與「停用帳號」兩條路。

不夠好的文案只有一句:

確定要繼續嗎?

使用者不知道「繼續」指什麼、影響誰,也不知道之後能不能救回來。Demo 改成:

停用林子安的帳號?停用後,林子安將無法登入 LumenDesk,目前的專案指派會保留。

按鈕也使用「停用帳號」,沒有只寫「確定」。紅色 Danger Token 可以提醒風險,真正幫助判斷的仍是具體對象與後果。

這個確認情境使用 Modal Dialog:初始焦點先停在「取消」,Escape 等同取消,背景不能被操作,關閉後焦點回到「停用成員帳號」。只有當訊息重要到必須中斷流程並立刻取得回應時,才改用 alertdialog

關閉方式也要依資料狀態決定

不少 Dialog 會同時提供右上角叉叉、Escape、點擊遮罩與取消按鈕。入口越多不一定越友善,它們必須承諾同一件事。

  • 只是閱讀補充資訊時,點擊外部關閉通常比較合理。
  • 已填入尚未儲存的資料時,點擊遮罩不能悄悄丟棄內容。
  • 危險確認的 Escape 可以視同取消,但不能視同執行。
  • 正在送出且不能安全中斷時,要說明為什麼暫時不能關閉。
  • 關閉後若原觸發元素已被刪除或不可用,焦點要回到下一個合理工作位置。

這些都屬於關閉政策。只寫「支援 Escape 和點外面關閉」,還沒有回答資料會不會消失。

改寫 Prompt:紅色按鈕之外,還要交代取消與焦點

在 LumenDesk 製作一個 Modal Dialog,用於確認是否停用「林子安」帳號。這是產品上的危險確認情境,不要自行發明新的 ARIA 角色。

標題與內文要寫出帳號名稱、停用後無法登入,以及目前的專案指派會保留。提供「取消」與使用紅色 Danger Token 的「停用帳號」按鈕;不要使用模糊的「確定」。

開啟時背景不可操作,初始焦點放在「取消」。Escape 視同取消,關閉後焦點回到開啟入口。點擊遮罩不執行停用;若 Dialog 內存在尚未儲存資料,也不得直接丟棄。

只有當流程必須因重要訊息立刻取得回應時,才改用 alertdialog。若訊息只需被看見而不阻止其他工作,改用頁內 Alert 或 Banner。

這是 Demo,不要真的變更帳號資料。

這段 Prompt 交代風險、文案、焦點、鍵盤行為與安全限制。AI 可以更換卡片樣式,卻不能把取消路徑和帳號後果一起換掉。

驗收 Dialog,沿著中斷與返回路徑走一次

交付前,我會依序確認:

  • 這個浮動介面真的需要中斷使用者嗎?
  • 若不需要,是否該用 Non-modal Dialog 或頁內提示?
  • Modal 開啟時,背景是否真的不能操作?
  • 初始焦點在哪裡?Tab 與 Shift + Tab 是否留在合理範圍?
  • Escape、取消、叉叉與點擊遮罩各代表什麼?
  • 有尚未儲存的資料時,關閉是否會造成意外遺失?
  • 關閉後焦點回到哪一個入口?若入口不存在,替代位置是什麼?
  • 高風險動作有沒有寫出對象、後果與可否復原?
  • 危險按鈕是否使用具體動詞,而不是「確定」?

使用者還沒做出決定時,系統不能偷偷替他越過那條線。這就是我先按 Escape,而不是先測紅色按鈕的原因。

取消停用後,成員資料卻把整張清單一起關燈

按下 Escape 後,帳號狀態沒有改變,Dialog 關閉,焦點也回到原本的「停用成員帳號」。開頭那句「漂亮彈窗」,現在多了可驗收的背景規則、焦點路徑、文案與取消行為。

不過管理員在決定停用以前,還想查看林子安的部門、角色與目前專案。需求也很直白:

點成員資料表的一列,顯示完整資料。

下面是依第一版需求重建的錯誤現場,不含真實帳號與個人資料:

成員詳細資料的錯誤第一版:林子安的資料顯示在置中 Modal,背景成員清單被遮罩鎖住,無法直接比較下一位

圖 9:林子安的資料出現了,其他成員列、部門與角色卻全部被遮罩壓在後面。想比較下一位,只能先關閉,再重新打開。

這次 Modal 沒有做壞,只是回答錯了問題。使用者不是要停下來完成獨立任務,而是想一邊查看詳細資料,一邊保留原本清單的脈絡。

明天,我們沿著這個問題認識 Drawer、Sheet 與 Bottom Sheet,看看詳細資料出現時,原本的清單到底該留下多少。

參考資料


上一篇
Day 17|資料有層級時,別只用縮排:Tree View、Nested List、Treegrid 與 Expandable Row
下一篇
Day 19|點資料表一列後,不一定要跳 Modal:Drawer、Sheet 與 Bottom Sheet
系列文
看得懂、叫得出、驗得過:30 天 VibeCoding UI 元件實戰23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言