iT邦幫忙

2026 iThome 鐵人賽

DAY 18
0
Vibe Coding

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

Day 22|訊息可以自己消失嗎?Toast、Snackbar 與 Notification

  • 分享至 

  • xImage
  •  

安安~我是ChiYu~

訊息站對位置後,LumenDesk 接著發生三件事:

  • 成員角色儲存成功。
  • 「八月活動文案」被移除。
  • 有人送來新的專案申請。

我把三件事縮成一句:

儲存完成後跳一個通知;刪除草稿後也跳同一種。新的申請同樣顯示通知。

AI 很公平。三件事都被做成右上角的小框,出現四秒,再一起消失。

LumenDesk 的儲存成功、刪除草稿與專案申請都使用相同通知,並在四秒後消失

圖 1:儲存、刪除與待處理申請共用同一種通知和四秒倒數;看起來一視同仁,實際上是把三種工作一起草率結案。

儲存成功確實可以收掉;草稿的復原入口跟著不見;新的申請則像只是來打聲招呼,時間到就離開。

它們的外觀非常一致,工作遺失得也很一致。

所以今天不再問通知放在哪裡,而是把訊息放上時間軸:

訊息消失後,使用者會不會少掉一個還沒完成的動作?

這一題會分出 ToastSnackbarNotification。我也把三條時間線做成 Vibe UI Atlas 的比較頁

Vibe UI Atlas 的 Toast、Snackbar 與 Notification 比較:訊息能不能消失,要看後面還有沒有工作

圖 2:Toast 在告知完成後退場,Snackbar 等待立即操作,Notification 則留下可回看的紀錄。

這張圖沒有替每種訊息規定固定秒數。真正的分界是後面還有沒有工作;只要還有復原、審核或追蹤,就不能只靠倒數計時決定結束。

歷史第一版:計時器歸零,系統就當作事情完成

這篇最早保存的模糊 Prompt 是:

儲存或刪除後跳一個通知。

原始實驗在 2026 年 7 月 24 日使用 Codex Desktop 完成。當時沒有保存第一張畫面,所以我在 7 月 27 日用當日 GPT-5 系列模型重新執行,並刻意不告訴 AI 哪一則訊息需要復原、哪一則要稍後處理。

補跑畫面的第三個事件寫成「新的權限申請」;文章後面的 Demo 則使用專案申請。它們不是同一筆資料,但都在測同一件事:訊息需要稍後處理,不能在四秒後直接消失。

沒有訊息留存規則時,AI 把儲存、刪除與權限申請都做成 Toast

圖 3:儲存成功、草稿刪除與權限申請使用相同 Toast,四秒後一起收起。

這是歷史第一版的失敗,不是目前 Demo 仍存在的問題。它把「看過訊息」誤認成「事情已經處理完」。

我的選型從消失後會少掉什麼開始:

事件 訊息出現後還有工作嗎? 合理結局 選擇
儲存成員角色 沒有,只需知道成功 幾秒後收起 Toast
移除八月活動文案 有,使用者可能反悔 等待復原或關閉 Snackbar
收到專案申請 有,可能晚點才處理 留在通知清單 Notification
儲存失敗 有,必須修正問題 留在錯誤發生的位置 不交給這三種短暫回饋

同樣是一條小訊息,後續工作不同,生命週期就不能共用。

Toast:事情真的結束了,訊息才可以跟著退場

我先測最單純的儲存成功。

在網站 Demo 按下「儲存角色」後,Toast 顯示「已儲存成員角色」。裡面沒有 Undo、連結或新的待辦,鍵盤焦點仍留在儲存按鈕。

我真的等了四秒。Toast 自動收起,狀態文字改成:

儲存成功訊息已在 4 秒後收起

Toast 實際 Demo:儲存成功後的短暫提示

圖 4:成員角色儲存成功後顯示 Toast;沒有後續操作,約四秒後自動收起。

這次自動消失是合理的。訊息離開後,任務沒有少任何一步,使用者也不需要到通知中心把「儲存成功」標成已讀。

動態狀態訊息應讓輔助科技得知,又不必強迫使用者離開原本位置。W3C 的 status 角色WCAG 2.2 的 Status Messages 說明 都把重點放在可被程式辨識,而且不改變焦點。

在 LumenDesk,我把會自動消失的成功 Toast 限制成純訊息。這是這個產品的規則,不是所有設計系統都禁止 Toast 帶操作。Carbon 也允許含操作的 Toast,但這類通知會持續顯示,直到使用者操作或關閉;真正不能共存的是「重要工作還沒做完」和「時間到自動消失」。Carbon Notification pattern

Toast 不只要決定秒數,還要決定排隊規則

實務上最容易漏掉的不是第一則 Toast,而是第五則。

使用者連續儲存三筆資料時,如果每次都在右上角堆一張卡,畫面很快會長成通知停車場;如果後來的訊息直接覆蓋前一則,又可能讓失敗結果被成功訊息蓋掉。

我會先定義:

  • 相同成功事件可以合併,例如「已儲存 3 筆變更」。
  • 錯誤不應被後來的成功 Toast 覆蓋,應回到可修正的位置。
  • 同時顯示的短暫訊息要有限制,超出的內容排隊或合併。
  • 計時應從使用者真正能讀到訊息時開始,不要在動畫進場前就偷跑。
  • 使用者偏好減少動態效果時,可以拿掉位移動畫,但不能拿掉訊息本身。

四秒只是 Demo 的選擇,不是通用答案。文字越長、語言越不同、使用者需要的閱讀時間也越不同;重要內容如果一定要靠精準秒數讀完,它大概就不該是自動消失的 Toast。

Snackbar:Undo 不是三秒反應力測驗

接著,我移除「八月活動文案」。

草稿先從清單消失,Snackbar 顯示「已移除八月活動文案」,並保留「復原」按鈕。按下復原後,草稿回到清單,鍵盤焦點也回到原本的「移除草稿」按鈕。

Snackbar 實際 Demo:刪除草稿後仍可復原

圖 5:移除草稿後,Snackbar 保留「復原」與「關閉」;復原成功時,草稿和焦點都回到原位。

有 Undo 卻讓 Snackbar 三秒後自動消失,等於把「能不能反悔」改成手速測驗。

這個 Demo 的規則很直接:只要復原仍有效,Snackbar 就不自動收起;使用者按下復原或主動關閉後,這段回饋才結束。其他產品可以有不同政策,但有效時間、資料何時永久刪除,以及逾時後去哪裡找,都要明確寫出來。

更重要的是,Undo 要和後端資料政策一致。

  • 若資料只是軟刪除,Snackbar 可以在有效期間送出復原。
  • 若後端已永久刪除,畫面就不能繼續展示一顆假的 Undo。
  • 若刪除請求仍在處理,應先顯示處理中,失敗時把項目放回並說明原因。
  • 使用者關閉 Snackbar 不一定等於放棄復原;兩者是否相同,要由產品規則決定。

多筆刪除也要有策略。連續移除三筆時,可以合併成「已移除 3 份草稿」並提供整批復原,或逐筆排隊;不能讓三張 Snackbar 互相蓋住,最後只剩最上面那一筆有機會回來。

Notification:留下紀錄,已讀不等於已經處理

新的專案申請又是另一條時間線。

使用者收到通知時,可能正在處理別的工作,晚點才有空審核。訊息至少要交代什麼事、和哪個項目有關、發生時間,以及可以去哪裡處理。

這種內容要留在通知中心、側欄或清單,不適合只在右上角閃一下。

Notification 實際 Demo:已讀後仍保留可追溯內容

圖 6:將專案申請標示已讀後,未讀數從 2 變成 1,通知內容仍保留在清單。

這個結果把「已讀」和「完成」分得很清楚。看過通知,只代表使用者知道有這件事;申請有沒有審核,是另一個任務狀態。若把兩者塞進同一個 Boolean,管理員點開通知的瞬間,系統就會很樂觀地宣布申請處理完畢。

Carbon 也把通知面板用在數量多、可能重複出現,而且日後需要回看的訊息。Carbon Notification usage

正式通知中心還要多處理幾件事:

  • 事件去重: 後端重送同一事件時,不要生出兩筆相同通知。
  • 深層連結: 點通知後前往正確申請或專案,而不是只回到首頁。
  • 權限變更: 使用者已失去權限時,連結不能繼續洩漏受限資料。
  • 跨裝置同步: 在手機標示已讀後,桌面未讀數也要一致。
  • 保存期限: 通知何時封存或刪除,要有產品政策,不是永遠累積。
  • 處理狀態: 已讀、待處理、處理中、已完成可以分開,不要只剩一顆未讀點。

Notification 是紀錄與入口,不應偷偷變成業務資料唯一來源。專案申請本身仍要有自己的狀態;通知即使被清除,申請也不能跟著消失。

訊息生命週期:消失、等待操作,或留下待辦

Toast、Snackbar 與 Notification 的訊息停留判斷圖

圖 7:純結果走向自動收起;需要立即復原時等待操作;需要稍後處理時留下通知紀錄。

如果「已儲存」被放進通知中心,使用者會多一項沒必要的待辦;如果「專案申請」只用 Toast 閃過,稍後處理的入口就消失;如果「刪除草稿」的復原按鈕會自動收起,Snackbar 只剩外觀還活著。

我在驗收時會問:訊息結束,是因為工作真的結束,還是只因為計時器歸零?

改寫 Prompt:先替三種訊息安排結局

請為 LumenDesk 管理後台實作三種不同的系統回饋,不要共用成同一個自動消失通知。

1. 儲存成員角色成功時使用 Toast:
   - 顯示「已儲存成員角色」。
   - 這是純成功結果,沒有按鈕,約 4 秒後自動收起。
   - 使用可被輔助科技辨識的 status 訊息宣布,但不要把鍵盤焦點移到 Toast。
   - 相同成功事件可合併;同時顯示數量要有限制,不能無限堆疊。

2. 移除「八月活動文案」時使用 Snackbar:
   - 顯示「已移除八月活動文案」,提供「復原」與「關閉」。
   - 復原有效期間不得自動收起;畫面狀態要和後端軟刪除或復原政策一致。
   - 按「復原」後,把草稿放回原排序位置,並把鍵盤焦點還給原本的「移除草稿」按鈕。
   - 刪除失敗時,自動把項目放回並顯示可持續閱讀的錯誤。

3. 專案申請與權限檢查使用 Notification 清單:
   - 每筆通知要有事件 ID、主旨、說明、時間、未讀/已讀與處理狀態。
   - 標示已讀後保留內容,只更新未讀數;已讀不等於已完成。
   - 通知能連到正確處理頁,並處理事件去重、跨裝置同步與權限變更。

360px 手機版不得出現水平捲動;所有操作都要能用鍵盤完成。使用者偏好減少動態效果時,移除不必要動畫,但保留訊息與狀態變化。

這份 Prompt 沒有要求三種不同配色。它先決定成功何時退場、復原要等多久,以及哪一則訊息必須留下紀錄,AI 才知道畫面相近不代表行為也能共用。

第二版實測:四秒收起、復原成功、通知仍然找得到

改寫 Prompt 後,我沿著三條時間線重新操作。

Toast 只回報已完成、沒有後續工作的結果

圖 8:Toast 只顯示「已儲存成員角色」,焦點留在原按鈕,沒有附加操作。

Snackbar 保留復原,Notification 留下可回看的紀錄

圖 9:Snackbar 等待使用者復原或關閉;Notification 標示已讀後,仍留在清單。

實測結果如下:

  • 按下「儲存角色」後,Toast 出現時焦點仍在原按鈕,4.2 秒後收起。
  • 移除「八月活動文案」後,Snackbar 持續保留復原;按下後草稿回到清單。
  • Notification 標示已讀後,未讀數由 2 變成 1,內容沒有被刪除。

歷史第一版「三件事一起四秒後消失」的問題,在目前 Demo 已經修正。第二版不只換了元件名稱,三個事件也真的走到不同結局。

目前證據與尚未驗證的範圍

這輪網站操作、360px 手機寬度與 Console 檢查都通過。

目前仍未納入:

  • 真正跨頁、跨裝置的通知中心同步。
  • 真實後端事件去重、保存期限與權限變更。
  • 不同螢幕閱讀器對動態訊息的完整實聽。
  • 多則 Toast/Snackbar 連續發生時的壓力測試。

現在的證據能確認三種生命週期分工成立,也能確認網站 Demo 的焦點、復原和留存結果。它不能證明正式產品的通知基礎設施已經完工,這條界線要留著。

交付前,沿著三條生命週期各走一次

生命週期 驗收動作 必須成立的結果
消失 儲存角色後等待 Toast 收起 焦點留在原按鈕;可得知成功結果;不留下待辦
復原 移除草稿後先等待,再按「復原」 Snackbar 不會先消失;草稿回到原位置;焦點回到移除按鈕
留存 把專案申請標示已讀,再離開頁面回來 未讀數更新;通知仍可追溯,也能前往對應處理頁
阻礙 模擬欄位驗證失敗 問題不塞進短暫 Toast,而是留在能修正的位置
連續事件 快速完成三次儲存與兩次刪除 訊息不無限堆疊,成功可合併,Undo 不互相蓋住

只截通知剛出現的畫面,三種元件可能都會過關。要看到差異,得等它消失、按下復原,再離開頁面回來找一次。

三則訊息都有結局,下一個待辦卻只剩一顆圈圈

重走流程後,角色儲存的 Toast 在告知完成後收起;草稿移除的 Snackbar 等待復原;專案申請則留在 Notification 清單。

使用者不會再因為計時器歸零,就失去尚未完成的工作。

下一個待辦正好來自通知清單:管理員要匯入 24 位成員。這不是一瞬間完成的動作,但我交給 AI 的 Loading 需求只有一句:

資料載入時先放一個轉圈圈。

LumenDesk 匯入 24 位成員時只顯示轉圈圈,沒有工作名稱、完成數量與離開影響

圖 10:系統知道要匯入 24 位成員,畫面卻只剩「資料載入中」;三個問號分別是處理對象、完成數量與現在能不能離開。

這顆 Spinner 很努力,情報量卻跟沒說差不多。使用者不知道正在處理哪一批、完成幾位,也不知道現在關掉頁面會不會讓前面全部白等。

明天就從這段等待開始,把 Spinner、Progress Bar、Skeleton 與其他 Loading 狀態拆開。這次不能只驗收「有沒有在轉」,還得一路走到完成、失敗與重試。

今日元件入口

參考資料


上一篇
Day 21|重要訊息到底該放在哪裡?Alert、Banner 與 Callout
下一篇
Day 23|Loading 不能只放一顆圈圈:五種等待狀態怎麼選
系列文
看得懂、叫得出、驗得過:30 天 VibeCoding UI 元件實戰23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言