安安~我是ChiYu~
Loading 跑完後,LumenDesk 的「專案」頁面只剩一句:
目前沒有資料。
我當時給 AI 的需求也差不多簡短:
沒有資料時顯示「目前沒有資料」,並提供重新載入。
結果篩選零筆、API 失敗、離線、權限不足,甚至工作完成後的畫面,全都共用同一句話和同一顆「重新載入」。

圖 1:畫面只留下「目前沒有資料」與「重新載入」,五種原因因此共用同一個出口。
這顆按鈕看起來很熱心,實際上只擅長重送請求。它不能清除篩選、恢復網路、取得權限,也不能替已完成的工作補上下一步。
畫面空白,不代表資料不存在。可能只是目前條件找不到結果、請求失敗、裝置離線、使用者不能看,或上一個流程已經成功結束。
所以今天不替空白畫面換五張不同插圖,而是先查清楚五種原因:Empty、Error、Offline、Permission 與 Success State。
我把完整比較與操作放在 Vibe UI Atlas 的系統狀態比較頁。

圖 2:同樣沒有一般資料,下一步可能是清除條件、重試、檢查連線、申請權限,或繼續下一個工作。
原因說對,按鈕才有機會做對;否則五張不同插圖,只是讓使用者換五個姿勢繼續猜。
我先把五種空白配回原因:
| 使用者看見的狀況 | 真正原因 | 畫面要說清楚什麼 | 真正下一步 |
|---|---|---|---|
| 篩選後沒有專案 | 條件下確實沒有結果 | 目前套用了哪些條件 | 清除或調整篩選 |
| 清單暫時載入失敗 | 這次請求發生錯誤 | 哪一區失敗、舊內容是否保留 | 重新載入受影響區域,必要時查看支援資訊 |
| 裝置暫時無法同步 | 連線或服務可用性仍待確認 | 最後同步時間、快取是否可用、哪些動作暫停 | 保留輸入與快取,再重新檢查連線 |
| 看不到部門預算 | 使用者尚未取得權限 | 存取受限,而非資料不存在 | 申請權限或聯絡管理員 |
| 剛送出存取申請 | 工作已成功完成 | 完成了什麼、後續何時發生 | 回到專案、查看申請或等待通知 |
這張表最重要的不是五個英文名稱,而是每一列的原因和下一步。
同一個畫面也可能同時符合兩個條件,例如裝置離線,而且目前清單使用篩選。這時要先決定哪個狀態真正阻止工作。通常會優先顯示影響資料可信度或操作能力的狀態,再保留次要脈絡:例如顯示「目前離線,以下是 09:45 的快取結果」,同時留下原本篩選條件,而不是只顯示零筆 Empty State。
狀態不是五張互不相干的卡片,而是一套有優先順序的狀態機。
我先打開 Error State Demo。畫面寫的是「目前無法載入專案清單」,不是包山包海的「發生錯誤」;原本的篩選條件也沒有被清掉。
按下「重新載入」後,按鈕在處理期間不能重複點擊。完成時,錯誤卡被三筆專案取代,狀態文字改成「專案清單已恢復,顯示 3 筆專案」。重試只處理失敗區域,沒有把人踢回首頁,也沒有偷偷洗掉原本條件。

圖 3:專案清單讀取失敗時,畫面保留原本脈絡,並讓使用者只重新載入受影響的清單。
這條復原路徑實際操作後成立。不過,成立的是 Error State 的重試,不是「所有空白都放重試」這條萬用公式。篩選無結果時,重送同一條件還是零筆;權限不足時,重新整理十次也不會長出權限。
Empty State 代表資料區正常運作,只是目前沒有內容可以顯示。
它至少有兩種常見情境:
LumenDesk 這次測的是篩選無結果。畫面保留「指派給我、未結案」兩個條件,按下「清除篩選」後,列表重新出現三筆工作。

圖 4:目前條件找不到工作時,畫面保留篩選摘要;清除條件後,三筆工作重新出現。
我會選「清除篩選」,因為它直接移除造成零筆結果的條件。若改放「重新整理」,服務即使完全正常,使用者按完還是會看到同一片空白。
Empty State 也不能偷偷丟掉查詢脈絡。搜尋「WebMCP」得到零筆時,畫面應保留搜尋字串,讓人知道這是搜尋結果,不是整個系統沒有資料。使用者清除條件後,排序、頁碼與其他可相容狀態要如何重設,也應先決定。
Carbon 的 Empty States Pattern也把首次使用、搜尋無結果與錯誤分開處理。樣式不必照抄,判斷值得留下:空狀態要取代原本資料區,並提供符合當下原因的下一步。
Error State 表示系統原本應取得資料,這一次請求卻失敗。相同請求重新執行後可能恢復,這時重試才合理。
文案不能只剩「發生錯誤」。至少要交代:
對純讀取清單來說,重試通常安全;對「建立申請」「付款」「批次匯入」這類寫入工作,重試就要確認是否具備冪等或去重機制。按鈕只是再送一次請求,不代表後端不會建立兩筆一模一樣的資料。
錯誤若在頁面載入後才動態出現,還要讓輔助科技察覺,但不該硬把鍵盤焦點搶走。W3C 的 ARIA19 技術說明提供 role="alert" 或 live region 的做法。這是一種實作選項,不代表所有 Error State 都要使用最高強度的 Alert;嚴重度、出現時機與是否需要立即處理仍要一起判斷。
Offline State 要對不確定性誠實。斷網、API 無法連線、請求逾時與快取過期,都可能讓資料暫時無法更新,處理方式卻不完全相同。
MDN:Navigator.onLine特別提醒,navigator.onLine 只是網路狀態提示,不能保證特定服務真的可用。電腦連上 Wi-Fi,不代表 LumenDesk 的 API 一定連得到。
LumenDesk 的 Demo 因此保留快取資料與最後同步時間,同時提供「重新檢查連線」。

圖 5:無法同步時仍保留快取資料與最後同步時間,並讓使用者主動重新檢查連線。
離線畫面最重要的不是替雲朵圖示加一條斜線,而是不要弄丟使用者正在做的事。
正式產品還要明確標示:
能離線編輯,不代表可以默默把衝突蓋掉。若系統無法安全合併,就應在恢復連線後顯示差異,讓使用者選擇保留哪一版。
Permission State 不是 Empty,也不是一般 Error。資料可能好好地躺在系統裡,只是目前這個角色不能看。
LumenDesk 會說明「你尚未取得部門預算報表的檢視權限」,並提供申請權限或聯絡管理者的路徑。但說清楚不代表可以順手把機密資料、筆數、姓名或金額先塞進畫面,再補一句你沒有權限。

圖 6:權限申請送出後,畫面只確認申請狀態,不透露受限制報表的內容、筆數或敏感欄位。
如果問題是「能不能看」,出口就該處理權限;重試讀取不會改變授權結果。
前端把內容藏起來只是在整理畫面,不等於完成授權。正式產品仍要由後端檢查權限,確保直接呼叫 API 也拿不到未授權資料。
有些系統為了避免透露資源是否存在,甚至不會明確區分「不存在」與「你沒有權限」。這是安全政策的一部分。Prompt 不應自行要求一定顯示專案名稱、筆數或擁有者;可透露到什麼程度,必須和後端授權及稽核策略一致。
權限申請也要有自己的生命週期:已送出、審核中、已核准、已拒絕,不能每次回來都只顯示同一顆「申請權限」。重複申請是否合併、誰會收到通知,也要先定義。
Success State 在這篇不是固定 ARIA role,而是流程完成後保留結果的畫面狀態。它要說出剛完成什麼、必要時交代後續時間,並提供合理下一步。
例如使用者送出存取申請後,畫面可以顯示「已送出申請,通常會在一個工作天內回覆」,再提供「查看申請」或「回到專案」。

圖 7:申請送出後,成功狀態說明回覆時間,並提供建立另一份申請的下一步。
這段訊息比 Toast 留得久,因為使用者可能需要確認結果;它也不必放一場大型慶祝動畫,把送出申請演成產品上市。
Success State 不能只寫「成功」。最好保留足以追蹤的資訊,例如申請名稱、送出時間或參考編號,但不要回顯不必要的敏感資料。重新整理頁面後,系統也應從後端狀態重新建立成功結果,而不是因為前端記憶消失,就讓使用者懷疑剛才到底有沒有送出。
W3C 的表單通知教學也建議成功與錯誤通知清楚、簡短,錯誤時提供可理解的解法。這個原則同樣適合所有會改變資料的後台流程。
State 不只決定文案,也決定資料可信度。
| 從哪個狀態切換 | 資料處理原則 |
|---|---|
| 正常資料 → 重新載入 Error | 若舊資料仍可參考,可以保留並標示更新失敗;不要無條件清空。 |
| 正常資料 → Offline | 保留快取並顯示最後同步時間,禁止假裝是最新資料。 |
| 正常資料 → Permission | 立即依授權政策移除受限內容,不能繼續把舊資料留在畫面上。 |
| 表單送出 → Success | 保留必要結果與下一步,避免重複送出。 |
| 篩選結果 → Empty | 保留查詢與篩選摘要,讓使用者知道零筆的原因。 |
這裡沒有一個「永遠保留舊資料」的答案。Error 和 Offline 可以保留帶有時間戳的舊內容;Permission 一旦生效,就必須優先遵守安全邊界。狀態名稱相近,資料政策卻完全不同。
請為 LumenDesk 的專案清單設計五種獨立狀態,不要共用同一段「暫無資料」。
- Empty State:區分首次使用與篩選無結果。篩選無結果時保留搜尋字串與條件,提供「清除篩選」並回到既有專案列表。
- Error State:說明「專案清單暫時無法載入」,保留仍可參考的舊資料與條件,提供只重試失敗區域的「重新載入」。寫入操作的重試必須有去重或冪等策略,避免建立重複資料。
- Offline State:顯示最後同步時間與快取摘要,保留未送出的輸入,說明哪些操作會排隊等待同步;不要只依 navigator.onLine 判定服務一定失敗。重新連線後要處理資料衝突。
- Permission State:說明使用者尚未被授權,提供申請權限;不得顯示未授權資料的內容、筆數或敏感欄位。前後端都要執行授權檢查,申請狀態需避免重複送出。
- Success State:說明剛完成的工作、送出時間或參考編號,提供查看結果或回到原工作區的下一步;不要用會自動消失的 Toast 取代流程完成頁。
狀態更新使用可被察覺的 live message,但不要任意移動焦點。手機 360px 寬度不得出現水平捲軸。
這份 Prompt 沒有規定插圖尺寸,也沒有要求「現代 SaaS 風格」。它把真正影響操作的事情交代清楚:何時清除條件、何時重試、何時保留或移除舊資料、哪些資訊不能透露,以及工作完成後怎麼繼續。
這輪實測裡,Error State 的重新載入通過:三筆專案重新出現,原本篩選條件仍然保留,完成文字也有更新。至於動態訊息能否被不同螢幕閱讀器正確讀出,目前還沒有完成實機驗證,不能因為畫面上看得到 aria-live 就先宣布過關。
現在 Empty 會帶人清除條件,Error 只重試失敗清單,Offline 保留快取與輸入,Permission 提供安全申請路徑,Success 則把完成結果和下一步接起來。
它們的差異不在插圖和顏色,而是使用者能不能從原因走回原本工作。
專案資料恢復後,我又丟了一句很容易讓 AI 自由發揮的需求:
請把近期專案做成現代、好看的 Card。

圖 8:三張 Card 個別看都完整,但里程碑日期沒有站在同一條線上。要比較哪個專案最早,只能逐張卡片尋寶。
三筆資料還能硬找,到了三十筆、三百筆,圓角和陰影只會讓畫面更像成品,不會讓比較變快。Card 沒有壞,問題是我先指定了容器,卻沒有說清楚讀者要完成什麼任務。
明天就從同一張錯誤畫面繼續,拿這批專案資料分別放進 Card、List、Description List、Media Object 與 Metadata,看內容容器到底該怎麼選。
資料查閱:2026-08-07。