UX 品質檢查
檢查變更觸及的 UI 表面是否符合 references/rules.md 中的規則。該文件中的每條規則都包含原因、程式碼檢查方式、瀏覽器檢查方式以及修正方法。文件頂部的表格說明各條規則適用於哪些類型的變更。
1. 找出變更
- 取得請求指定的差異檔:PR、分支、提交或未提交的變更。若未指定名稱,則使用未提交的變更。如果沒有任何未提交的變更,則使用當前分支與其合併基準(預設分支)之間的差異(
git diff $(git merge-base HEAD origin/HEAD)...HEAD)。如果分支就是預設分支,則使用最後一個提交。請在報告中說明檢查的是哪個差異檔。 - 列出已變更的 UI 檔案:元件、模板、樣式,以及它們渲染的字串和屬性。共用元件或設計代號的變更也屬於 UI 變更。
- 如果差異檔中沒有渲染 UI 的檔案(僅有伺服器程式碼、測試、設定或文件),則用一兩句話說明並停止。報告中應無任何發現。
2. 讀取專案自身的 UI 規則,並對應表面
專案的規則優先於目錄的預設值。
- 讀取專案的代理文件(
AGENTS.md、CLAUDE.md、設計系統的 README),尋找「UI 規則」或類似章節。記錄它們為某條規則指定的每個控制項、代號或元件,例如對話框輔助函數、非同步按鈕、類型代號或 AI 標記。修正方式應使用該元件名稱。 - 尋找專案自身的 UX 檢查:例如
make ux-check或ux:check目標、版面或無障礙腳本、lint 規則,或掃描原始碼以檢查 UI 規則的測試。執行所有涵蓋此變更的檢查,並將其輸出作為證據。
然後將每個變更的檔案對應到使用者看到的表面:路由、檢視和控制項。共用元件應對應到使用它的每個表面。以使用者找到該表面的方式命名表面(例如「評論頁面,新增評論表單」)。對於每個表面,請記錄:
- 類型。 根據
references/rules.md的圖例,為差異檔新增或編輯的表面標記每個類型:write、data、form、list、control、overlay、layout、route、copy、chart、style。新的懸停樣式屬於control和list。儲存按鈕屬於write。 - 狀態。 空白、載入中、待處理、錯誤、懸停、聚焦、已選取和已停用。大多數發現存在於作者未開啟的狀態中。
3. 執行檢查
對於每個表面,執行所有「適用於」類型與該表面類型相符的規則。在檢查之前,請先閱讀該規則的章節。記錄每條跳過的規則及其原因。
先閱讀程式碼。 每條規則的「程式碼檢查方式」會說明要尋找什麼。這能捕捉到大多數缺陷,而且不需要瀏覽器。在報告遺失的狀態之前,請閱讀程式碼呼叫的元件:包裝器(非同步按鈕、表單鉤子、傳遞 pending 屬性的父元件)通常會處理它。
然後,在可能的情況下,在瀏覽器中進行測量。 靜態 HTML 頁面可透過 file:// URL 從磁碟開啟。對於應用程式,請尋找正在執行的開發伺服器,或使用專案文件記錄的命令啟動一個。使用主機提供的瀏覽器工具:內建瀏覽器面板、Playwright 腳本或 headless Chrome。如果頁面要求登入,請要求使用者在該瀏覽器中登入。請勿自行輸入任何憑證。
將 scripts/measure.js 載入頁面。它定義了每條規則的「瀏覽器檢查方式」所命名的輔助函數,而 references/rules.md 中說明了每個函數的回傳值。每次頁面載入後都重新貼上它。檢查應用程式提供的每個主題和配色方案,以及至少一種手機寬度和桌面寬度。
同時也要測量每個已變更的行、卡片和控制項在其互動狀態下的表現。 懸停、聚焦或選取狀態通常會添加填色、邊框、陰影或控制項。這可能導致兩個盒狀項目互相碰觸、項目變大並推動相鄰項目,或僅在懸停時顯示的操作使計數偏離對齊線。對於表面上的每個列表、卡片群組或控制項群組:
- 在項目靜止時執行
snapshot(sel, "rest")和gaps(sel)。 - 使用瀏覽器工具懸停一個項目,然後再次執行
snapshot(sel, "hover")和gaps(sel)。對鍵盤焦點(按 Tab 鍵)以及選取項目旁邊有懸停項目的情況執行相同操作。 - 執行
moved("rest", "hover")。兩個盒狀項目之間的間距為 0px,或一個項目在另一個項目被懸停時移動,即為發現。
對每個會開啟選單、彈出視窗或面板的操作執行相同操作:擷取主要區塊的快照,開啟它,再次擷取快照,然後進行比較。在程式碼中,檢查每個 :hover、:focus-visible 和選取類別的規則,尋找會添加盒子或改變大小的屬性:background、border、box-shadow、padding、margin、width 和 display。
如果沒有瀏覽器,或沒有頁面可開啟,請報告程式碼發現,並列出未執行的瀏覽器檢查。
4. 檢查每個發現
在報告發現之前,請再次檢查:
- 程式碼發現。 確認使用者可以到達該狀態:分支正在執行、屬性已被傳遞,並且沒有包裝器或父元件處理它。
- 瀏覽器發現。 在重新載入後,於發現所指的狀態下再次測量。捨棄無法重現的值。
- 在變更中還是變更前。 差異檔新增或修改的行上的缺陷屬於此變更。同樣地,變更新增了一個狀態但沒有其對應狀態,即使缺少的行在其他地方,也屬於此變更:例如新的
:hover規則沒有對應的:focus-visible規則,或新的寫入操作沒有對應的待處理狀態。差異檔未觸及的行上的缺陷在變更前就已存在。請將其歸類為「既有缺陷」,與變更的發現分開,且僅當它出現在已變更的表面上時才報告。
如果發現無法通過檢查,則捨棄。如果某個發現無法檢查,則報告為「未確認」,並附上原因。
5. 報告發現
開頭用一行說明檢查的差異檔和表面。然後每個缺陷提供一個發現,嚴重性最高的優先。嚴重性:
- 高:使用者遺失資料或輸入、發送重複寫入、無法到達控制項,或無法閱讀文字。
- 中:控制項具有誤導性(圖示錯誤、僅以顏色表示狀態、缺少 AI 標記)或版面明顯破損。
- 低:與專案系統不一致(使用原始類型值、混用選取控制項、填充內容)。
每個發現包含四個部分:
| 部分 | 內容 |
|---|---|
| 表面 | 檢視和控制項,加上檔案和行號 (ReviewForm.tsx:42) |
| 規則 | 目錄中的規則 ID,或違反的專案規則 |
| 證據 | 你讀取或測量的內容:程式碼行、測量值、狀態、主題和寬度 |
| 修正 | 一兩句話說明修改方式,如果適用的話,使用專案的元件或代號名稱 |
範例:
表面: Stack 側邊欄,作者篩選列表 (
AuthorList.tsx:58) 規則:no-cramped-controls證據:gaps(".author-row")在 1440px 寬度下,第 2 行懸停時:第 1 行(已選取)和第 2 行之間的y: 0。靜止時間距也為 0,但只有已選取的行會繪製盒子。 修正: 在列表中添加gap: 2px,或將懸停填色向內縮進 2px。
然後添加以下章節:
- 既有缺陷:從步驟 4 中得出的、並非由此次變更引入的缺陷,每行一個。
- 未檢查:你跳過的規則及其原因,以及未執行的瀏覽器檢查。
當使用者要求修正時,進行修正,然後對相同的表面再次執行相同的檢查。