iT邦幫忙

2026 iThome 鐵人賽

DAY 18
0
Vibe Coding

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

Day 24|畫面空白,不代表沒有資料:Empty、Error、Offline、Permission 與 Success State

  • 分享至 

  • xImage
  •  

安安~我是ChiYu~

Loading 跑完後,LumenDesk 的「專案」頁面只剩一句:

目前沒有資料。

我當時給 AI 的需求也差不多簡短:

沒有資料時顯示「目前沒有資料」,並提供重新載入。

結果篩選零筆、API 失敗、離線、權限不足,甚至工作完成後的畫面,全都共用同一句話和同一顆「重新載入」。

LumenDesk 專案頁將篩選零結果、API 失敗、任務完成、離線與權限不足都顯示成目前沒有資料

圖 1:畫面只留下「目前沒有資料」與「重新載入」,五種原因因此共用同一個出口。

這顆按鈕看起來很熱心,實際上只擅長重送請求。它不能清除篩選、恢復網路、取得權限,也不能替已完成的工作補上下一步。

畫面空白,不代表資料不存在。可能只是目前條件找不到結果、請求失敗、裝置離線、使用者不能看,或上一個流程已經成功結束。

所以今天不替空白畫面換五張不同插圖,而是先查清楚五種原因:Empty、Error、Offline、Permission 與 Success State

我把完整比較與操作放在 Vibe UI Atlas 的系統狀態比較頁

Vibe UI Atlas 的 Empty、Error、Success、Offline 與 Permission State 比較:沒有資料前要先查清原因

圖 2:同樣沒有一般資料,下一步可能是清除條件、重試、檢查連線、申請權限,或繼續下一個工作。

原因說對,按鈕才有機會做對;否則五張不同插圖,只是讓使用者換五個姿勢繼續猜。

先判斷「為什麼沒有資料」,再決定狀態卡要說什麼

我先把五種空白配回原因:

使用者看見的狀況 真正原因 畫面要說清楚什麼 真正下一步
篩選後沒有專案 條件下確實沒有結果 目前套用了哪些條件 清除或調整篩選
清單暫時載入失敗 這次請求發生錯誤 哪一區失敗、舊內容是否保留 重新載入受影響區域,必要時查看支援資訊
裝置暫時無法同步 連線或服務可用性仍待確認 最後同步時間、快取是否可用、哪些動作暫停 保留輸入與快取,再重新檢查連線
看不到部門預算 使用者尚未取得權限 存取受限,而非資料不存在 申請權限或聯絡管理員
剛送出存取申請 工作已成功完成 完成了什麼、後續何時發生 回到專案、查看申請或等待通知

這張表最重要的不是五個英文名稱,而是每一列的原因和下一步。

同一個畫面也可能同時符合兩個條件,例如裝置離線,而且目前清單使用篩選。這時要先決定哪個狀態真正阻止工作。通常會優先顯示影響資料可信度或操作能力的狀態,再保留次要脈絡:例如顯示「目前離線,以下是 09:45 的快取結果」,同時留下原本篩選條件,而不是只顯示零筆 Empty State。

狀態不是五張互不相干的卡片,而是一套有優先順序的狀態機。

Error State 實測:只重試專案清單,別把整頁一起洗掉

我先打開 Error State Demo。畫面寫的是「目前無法載入專案清單」,不是包山包海的「發生錯誤」;原本的篩選條件也沒有被清掉。

按下「重新載入」後,按鈕在處理期間不能重複點擊。完成時,錯誤卡被三筆專案取代,狀態文字改成「專案清單已恢復,顯示 3 筆專案」。重試只處理失敗區域,沒有把人踢回首頁,也沒有偷偷洗掉原本條件。

Error State:讀取失敗後可重試

圖 3:專案清單讀取失敗時,畫面保留原本脈絡,並讓使用者只重新載入受影響的清單。

這條復原路徑實際操作後成立。不過,成立的是 Error State 的重試,不是「所有空白都放重試」這條萬用公式。篩選無結果時,重送同一條件還是零筆;權限不足時,重新整理十次也不會長出權限。

Empty State:第一次沒有內容,和篩選後零筆不是同一件事

Empty State 代表資料區正常運作,只是目前沒有內容可以顯示。

它至少有兩種常見情境:

  • 首次使用: 系統真的還沒有專案,下一步可能是「建立第一個專案」。
  • 搜尋或篩選無結果: 原始資料可能存在,只是目前條件找不到,下一步應是清除或調整條件。

LumenDesk 這次測的是篩選無結果。畫面保留「指派給我、未結案」兩個條件,按下「清除篩選」後,列表重新出現三筆工作。

Empty State:清除篩選後回到工作清單

圖 4:目前條件找不到工作時,畫面保留篩選摘要;清除條件後,三筆工作重新出現。

我會選「清除篩選」,因為它直接移除造成零筆結果的條件。若改放「重新整理」,服務即使完全正常,使用者按完還是會看到同一片空白。

Empty State 也不能偷偷丟掉查詢脈絡。搜尋「WebMCP」得到零筆時,畫面應保留搜尋字串,讓人知道這是搜尋結果,不是整個系統沒有資料。使用者清除條件後,排序、頁碼與其他可相容狀態要如何重設,也應先決定。

Carbon 的 Empty States Pattern也把首次使用、搜尋無結果與錯誤分開處理。樣式不必照抄,判斷值得留下:空狀態要取代原本資料區,並提供符合當下原因的下一步。

Error State:只有可能恢復的失敗,才值得放重新載入

Error State 表示系統原本應取得資料,這一次請求卻失敗。相同請求重新執行後可能恢復,這時重試才合理。

文案不能只剩「發生錯誤」。至少要交代:

  • 失敗的是哪一塊資料。
  • 舊內容與使用者輸入是否還在。
  • 重試會不會重複建立或送出資料。
  • 問題持續時,還有沒有支援或替代路徑。

對純讀取清單來說,重試通常安全;對「建立申請」「付款」「批次匯入」這類寫入工作,重試就要確認是否具備冪等或去重機制。按鈕只是再送一次請求,不代表後端不會建立兩筆一模一樣的資料。

錯誤若在頁面載入後才動態出現,還要讓輔助科技察覺,但不該硬把鍵盤焦點搶走。W3C 的 ARIA19 技術說明提供 role="alert" 或 live region 的做法。這是一種實作選項,不代表所有 Error State 都要使用最高強度的 Alert;嚴重度、出現時機與是否需要立即處理仍要一起判斷。

Offline State:顯示在線,不代表 API 一定可用

Offline State 要對不確定性誠實。斷網、API 無法連線、請求逾時與快取過期,都可能讓資料暫時無法更新,處理方式卻不完全相同。

MDN:Navigator.onLine特別提醒,navigator.onLine 只是網路狀態提示,不能保證特定服務真的可用。電腦連上 Wi-Fi,不代表 LumenDesk 的 API 一定連得到。

LumenDesk 的 Demo 因此保留快取資料與最後同步時間,同時提供「重新檢查連線」。

Offline State:保留快取資料並允許重新檢查

圖 5:無法同步時仍保留快取資料與最後同步時間,並讓使用者主動重新檢查連線。

離線畫面最重要的不是替雲朵圖示加一條斜線,而是不要弄丟使用者正在做的事。

正式產品還要明確標示:

  • 畫面顯示的是快取資料,最後更新時間為何。
  • 哪些操作仍可進行,哪些會暫存等待同步。
  • 離線期間的輸入如何保留。
  • 重新連線後若同一筆資料已被別人修改,要如何處理衝突。
  • 使用者重複按「重新檢查」時,是否會產生多個併發請求。

能離線編輯,不代表可以默默把衝突蓋掉。若系統無法安全合併,就應在恢復連線後顯示差異,讓使用者選擇保留哪一版。

Permission State:資料確實存在,也不能先露一點給你看

Permission State 不是 Empty,也不是一般 Error。資料可能好好地躺在系統裡,只是目前這個角色不能看。

LumenDesk 會說明「你尚未取得部門預算報表的檢視權限」,並提供申請權限或聯絡管理者的路徑。但說清楚不代表可以順手把機密資料、筆數、姓名或金額先塞進畫面,再補一句你沒有權限。

Permission State:送出申請,但不洩漏尚未授權的資料

圖 6:權限申請送出後,畫面只確認申請狀態,不透露受限制報表的內容、筆數或敏感欄位。

如果問題是「能不能看」,出口就該處理權限;重試讀取不會改變授權結果。

前端把內容藏起來只是在整理畫面,不等於完成授權。正式產品仍要由後端檢查權限,確保直接呼叫 API 也拿不到未授權資料。

有些系統為了避免透露資源是否存在,甚至不會明確區分「不存在」與「你沒有權限」。這是安全政策的一部分。Prompt 不應自行要求一定顯示專案名稱、筆數或擁有者;可透露到什麼程度,必須和後端授權及稽核策略一致。

權限申請也要有自己的生命週期:已送出、審核中、已核准、已拒絕,不能每次回來都只顯示同一顆「申請權限」。重複申請是否合併、誰會收到通知,也要先定義。

Success State:事情做完了,要把結果和下一步接住

Success State 在這篇不是固定 ARIA role,而是流程完成後保留結果的畫面狀態。它要說出剛完成什麼、必要時交代後續時間,並提供合理下一步。

例如使用者送出存取申請後,畫面可以顯示「已送出申請,通常會在一個工作天內回覆」,再提供「查看申請」或「回到專案」。

Success State:確認完成內容,提供下一個工作

圖 7:申請送出後,成功狀態說明回覆時間,並提供建立另一份申請的下一步。

這段訊息比 Toast 留得久,因為使用者可能需要確認結果;它也不必放一場大型慶祝動畫,把送出申請演成產品上市。

Success State 不能只寫「成功」。最好保留足以追蹤的資訊,例如申請名稱、送出時間或參考編號,但不要回顯不必要的敏感資料。重新整理頁面後,系統也應從後端狀態重新建立成功結果,而不是因為前端記憶消失,就讓使用者懷疑剛才到底有沒有送出。

W3C 的表單通知教學也建議成功與錯誤通知清楚、簡短,錯誤時提供可理解的解法。這個原則同樣適合所有會改變資料的後台流程。

狀態切換時,舊資料到底要保留、標舊,還是拿掉?

State 不只決定文案,也決定資料可信度。

從哪個狀態切換 資料處理原則
正常資料 → 重新載入 Error 若舊資料仍可參考,可以保留並標示更新失敗;不要無條件清空。
正常資料 → Offline 保留快取並顯示最後同步時間,禁止假裝是最新資料。
正常資料 → Permission 立即依授權政策移除受限內容,不能繼續把舊資料留在畫面上。
表單送出 → Success 保留必要結果與下一步,避免重複送出。
篩選結果 → Empty 保留查詢與篩選摘要,讓使用者知道零筆的原因。

這裡沒有一個「永遠保留舊資料」的答案。Error 和 Offline 可以保留帶有時間戳的舊內容;Permission 一旦生效,就必須優先遵守安全邊界。狀態名稱相近,資料政策卻完全不同。

改寫 Prompt:寫復原政策,不要指定插圖

請為 LumenDesk 的專案清單設計五種獨立狀態,不要共用同一段「暫無資料」。

- Empty State:區分首次使用與篩選無結果。篩選無結果時保留搜尋字串與條件,提供「清除篩選」並回到既有專案列表。
- Error State:說明「專案清單暫時無法載入」,保留仍可參考的舊資料與條件,提供只重試失敗區域的「重新載入」。寫入操作的重試必須有去重或冪等策略,避免建立重複資料。
- Offline State:顯示最後同步時間與快取摘要,保留未送出的輸入,說明哪些操作會排隊等待同步;不要只依 navigator.onLine 判定服務一定失敗。重新連線後要處理資料衝突。
- Permission State:說明使用者尚未被授權,提供申請權限;不得顯示未授權資料的內容、筆數或敏感欄位。前後端都要執行授權檢查,申請狀態需避免重複送出。
- Success State:說明剛完成的工作、送出時間或參考編號,提供查看結果或回到原工作區的下一步;不要用會自動消失的 Toast 取代流程完成頁。

狀態更新使用可被察覺的 live message,但不要任意移動焦點。手機 360px 寬度不得出現水平捲軸。

這份 Prompt 沒有規定插圖尺寸,也沒有要求「現代 SaaS 風格」。它把真正影響操作的事情交代清楚:何時清除條件、何時重試、何時保留或移除舊資料、哪些資訊不能透露,以及工作完成後怎麼繼續。

驗收五種 State,不要只確認卡片有出現

  1. 使用者能在幾秒內分辨資料是不存在、讀取失敗、離線、權限不足,還是剛完成操作嗎?
  2. Empty State 是否保留查詢與篩選條件,並提供能改變結果的操作?
  3. Error 的重試是否只影響失敗區域,而且不會重複建立資料?
  4. Offline 是否保留可用快取與輸入,並明確標示資料時間與同步限制?
  5. Permission 是否完全遵守防洩漏政策,前後端都無法取得未授權內容?
  6. Success 是否確認結果、避免重複送出,並提供合理下一步?
  7. 狀態切換後,舊資料是保留、標舊還是移除,是否符合該狀態的可信度與安全規則?

這輪實測裡,Error State 的重新載入通過:三筆專案重新出現,原本篩選條件仍然保留,完成文字也有更新。至於動態訊息能否被不同螢幕閱讀器正確讀出,目前還沒有完成實機驗證,不能因為畫面上看得到 aria-live 就先宣布過關。

五種空白終於會說人話,資料回來後卻又塞錯容器

現在 Empty 會帶人清除條件,Error 只重試失敗清單,Offline 保留快取與輸入,Permission 提供安全申請路徑,Success 則把完成結果和下一步接起來。

它們的差異不在插圖和顏色,而是使用者能不能從原因走回原本工作。

專案資料恢復後,我又丟了一句很容易讓 AI 自由發揮的需求:

請把近期專案做成現代、好看的 Card。

三筆專案都被做成 Card,里程碑日期卻散落在不同位置

圖 8:三張 Card 個別看都完整,但里程碑日期沒有站在同一條線上。要比較哪個專案最早,只能逐張卡片尋寶。

三筆資料還能硬找,到了三十筆、三百筆,圓角和陰影只會讓畫面更像成品,不會讓比較變快。Card 沒有壞,問題是我先指定了容器,卻沒有說清楚讀者要完成什麼任務。

明天就從同一張錯誤畫面繼續,拿這批專案資料分別放進 Card、List、Description List、Media Object 與 Metadata,看內容容器到底該怎麼選。

參考來源

資料查閱:2026-08-07。


上一篇
Day 23|Loading 不能只放一顆圈圈:五種等待狀態怎麼選
系列文
看得懂、叫得出、驗得過:30 天 VibeCoding UI 元件實戰24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言