@qijenchen/design-system 0.1.0-beta.72 → 0.1.0-beta.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -1
- package/ds-canonical/fork/governance.lock +106 -2
- package/ds-canonical/fork/launchers/inject_fork_governance_preamble.sh +8 -0
- package/ds-canonical/fork/manifest.json +15 -1
- package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +183 -0
- package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +65 -0
- package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +229 -0
- package/ds-canonical/fork/skills/delivery-handoff/references/flow-diagram.md +180 -0
- package/ds-canonical/fork/skills/delivery-handoff/references/handoff-template.md +177 -0
- package/ds-canonical/fork/skills/delivery-handoff/references/inventory-checklist.md +196 -0
- package/ds-canonical/fork/skills/performance-audit/SKILL.md +107 -0
- package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +232 -0
- package/ds-canonical/fork/skills/product-ui-audit/references/audit-checks.md +246 -0
- package/ds-canonical/fork/skills/product-ui-audit/references/common-misuses.md +329 -0
- package/ds-canonical/fork/skills/product-ui-audit/references/report-template.md +159 -0
- package/ds-canonical/fork/skills/propose-options/SKILL.md +177 -0
- package/ds-canonical/fork/skills/prototype/SKILL.md +244 -0
- package/ds-canonical/fork/skills/prototype/references/audit-checks.md +38 -0
- package/ds-canonical/fork/skills/prototype/references/benchmark-sources.md +94 -0
- package/ds-canonical/fork/skills/prototype/references/checkpoints.md +191 -0
- package/ds-canonical/fork/skills/prototype/references/evaluation-matrix.md +141 -0
- package/ds-canonical/fork/skills/prototype/references/ooux-template.md +198 -0
- package/ds-canonical/fork/skills/prototype/references/proposal-template.md +229 -0
- package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +200 -0
- package/ds-canonical/fork/skills/ux-audit/SKILL.md +130 -0
- package/ds-canonical/fork/skills/visual-audit/SKILL.md +247 -0
- package/ds-canonical/fork/skills/visual-audit/output/.gitkeep +0 -0
- package/ds-canonical/fork/skills/visual-audit/references/audit-architecture.md +101 -0
- package/ds-canonical/fork/skills/visual-audit/references/visual-checklist.md +297 -0
- package/ds-canonical/fork/skills/visual-audit/references/world-class-benchmarks.md +198 -0
- package/ds-canonical/hooks/check_plugin_fork_health.sh +2 -2
- package/ds-canonical/hooks/lib/_app_shell_primary_header_consistency.sh +36 -6
- package/ds-canonical/hooks/session_start_governance_check.sh +1 -1
- package/ds-canonical/hooks/tests/test_check_app_shell_primary_header_consistency.sh +58 -2
- package/ds-canonical/skills/design-system-audit/SKILL.md +2 -2
- package/llms-full.txt +1 -1
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/src/components/AppShell/_demo-helpers.tsx +25 -1
- package/src/components/AppShell/app-shell.principles.stories.tsx +3 -2
- package/src/components/AppShell/app-shell.spec.md +12 -7
- package/src/components/AppShell/app-shell.stories.tsx +6 -0
- package/src/components/Sidebar/sidebar.spec.md +2 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: product-ui-audit
|
|
3
|
+
description: Audit product / consumer UI code (非 design-system 本身) against DS usage discipline + mindset adherence. Catches element misuse / design principle violations / token leakage / geometry bugs / a11y gaps across 7 dimensions. Invoke via /product-ui-audit when user says「audit 這個 UI」「檢查 X feature 用對 DS 嗎」「這段 code 符合設計原則嗎」,or auto-invoked by /prototype Phase 3.5 gate.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
> **⚠️ Fork 工具註記(build 自動加)**:本 skill 提到的 `scripts/*.mjs` 或非標準 `npm run <audit>` 是 **DS-author repo 的機械工具,未隨 fork 套件附帶**(Claude Code 不掃 node_modules,fork 也無這些 executor + dep)。你的 product fork 用本 skill 的**方法論**(human / AI judgment)+ 既有 committed governance hook 的機械強制即可;要 mechanical 腳本層(截圖 / CI gate)請自行設置對應工具,或把該檢查 PR 回 DS repo 跑。
|
|
7
|
+
|
|
8
|
+
# Product UI Audit Workflow
|
|
9
|
+
|
|
10
|
+
Purpose: design-system-audit audits the **DS itself**(spec / cva / SSOT 三方漂移);product-ui-audit audits **consumer UI code**(不是 DS 本身,是 app / exploration / feature code — 即「consumer 用 DS 的地方」)。防止:
|
|
11
|
+
|
|
12
|
+
- 元件亂用(wrong variant / missing props / incorrect composition)
|
|
13
|
+
- 設計原則亂用(placeholder 文案 / 憑直覺創造 pattern / Mindset 違反)
|
|
14
|
+
- Token 逃逸(硬寫 hex / shadcn alias 回流 / shadow-sm 繞過 elevation)
|
|
15
|
+
- 幾何 bug(flex gap token 被 overflow 吃、slot box 不一致)
|
|
16
|
+
- A11y 缺口
|
|
17
|
+
|
|
18
|
+
## When to run
|
|
19
|
+
|
|
20
|
+
**明確觸發(直接 invoke)**:
|
|
21
|
+
- User 說「audit 這個 UI」「audit X feature」「檢查 /src/app/xxx」
|
|
22
|
+
- User 說「這段 code 符合設計原則嗎」「DS 用對了嗎」「有元件亂用嗎」
|
|
23
|
+
- `/prototype` Phase 3.5 自動 invoke(audit `src/explorations/{topic-slug}/`)
|
|
24
|
+
- PR review 前自我檢查
|
|
25
|
+
|
|
26
|
+
**不觸發**:
|
|
27
|
+
- 要 audit DS 本身 → 走 `/design-system-audit`(不同 scope)
|
|
28
|
+
- 要 audit token 定義 → 走 `design-system-audit`
|
|
29
|
+
- 只要求補 stories → 直接補,不需 audit
|
|
30
|
+
|
|
31
|
+
## 生態位
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
/design-system-audit audit DS 本身(設計系統內部)
|
|
35
|
+
/product-ui-audit audit consumer UI code(本 skill)
|
|
36
|
+
/prototype 呼叫本 skill 作 Phase 3.5 gate
|
|
37
|
+
/delivery-handoff 只在產品交付前執行(產 handoff 文件)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Preconditions
|
|
41
|
+
|
|
42
|
+
- User 指定 audit target(file path / folder / feature area)
|
|
43
|
+
- Target 是 consumer 層 UI code(`src/app/**` / `src/explorations/**` / `src/pages/**` / `src/features/**` / `apps/**`(含 DS repo 自家 `apps/template` + create-app 產物)等 — **不掃 `node_modules/@qijenchen/design-system/src/`**)
|
|
44
|
+
- CLAUDE.md 全讀(7 維 audit 都依此為基準)
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 7-Dimension Audit
|
|
49
|
+
|
|
50
|
+
每個 dimension 獨立檢查,產出 findings。詳細 grep pattern + rule 見 `references/audit-checks.md`。
|
|
51
|
+
|
|
52
|
+
### Dim 1 — Token 紀律(token hygiene)
|
|
53
|
+
|
|
54
|
+
- 硬寫 hex / rgb / rgba / hsl 色值
|
|
55
|
+
- shadcn compat alias(bg-popover / text-muted-foreground / bg-accent / bg-destructive / bg-background / bg-card / border-input / text-primary-foreground / text-accent-foreground / text-card-foreground / text-popover-foreground)**(完整 deny-list SSOT:`node_modules/@qijenchen/design-system/src/tokens/utility-registry.json`;此處 inline 為 grep 便利,新增 alias 改 registry)**
|
|
56
|
+
- Tailwind default shadow(shadow-sm / md / lg / xl / 2xl / inner)— 應走 elevation token
|
|
57
|
+
- Tailwind v4 `[--foo]` shorthand 靜默失效
|
|
58
|
+
- 硬寫 px 值當該用 token(`w-[48px]` 應改 token)
|
|
59
|
+
|
|
60
|
+
此維對齊既有 token 防線(`lib/_token_hygiene.sh` 5-check:shadcn alias / v4 shorthand / hardcoded shadow / primitive-color-as-utility / native overflow,由 `post_edit_dispatcher.sh` source;+ `check_opacity_token_usage.sh` 讀 utility-registry.json)+ 擴充硬色值 / 硬 px 檢查。
|
|
61
|
+
|
|
62
|
+
### Dim 2 — Layout primitive 消費(per CLAUDE.md 清單)
|
|
63
|
+
|
|
64
|
+
掃是否正確消費既有 layout primitives(非自 roll):
|
|
65
|
+
|
|
66
|
+
| 視覺 pattern | 應消費 | 違規 signal |
|
|
67
|
+
|------|---------|---------|
|
|
68
|
+
| icon+title+desc 垂直居中 | `<Empty>` | 自己寫 flex flex-col items-center 3-layer text |
|
|
69
|
+
| row prefix+content+suffix | `item-layout` | 自己寫 flex items-center gap-2 3-slot |
|
|
70
|
+
| overlay Header/Body/Footer | `overlay-surface` | 自己寫 border-b/border-t padding loose/tight |
|
|
71
|
+
| 橫向按鈕列 | `action-bar` pattern | 自己 flex gap-2 按鈕組 |
|
|
72
|
+
| 水平溢出 + fade mask | `horizontal-overflow` | 自己 overflow-x-auto + mask |
|
|
73
|
+
| 跨 OS 一致捲軸 | `ScrollArea` | native `overflow-(auto\|scroll)` |
|
|
74
|
+
| 圖像 / media 容器 | `AspectRatio` | 硬寫 `aspect-video` / `aspect-square` class |
|
|
75
|
+
| Field wrapper | `Field` + `fieldWrapperStyles` | 自己 border + padding + startIcon + endAction |
|
|
76
|
+
|
|
77
|
+
### Dim 3 — 元件使用正確性
|
|
78
|
+
|
|
79
|
+
- Button / Input / Select 等 variant / size / props 組合合理
|
|
80
|
+
- icon-only 有 `aria-label`
|
|
81
|
+
- Button primary 沒堆疊(一個 row 一個 primary)
|
|
82
|
+
- Input 外有 Field wrapper(非 standalone input)
|
|
83
|
+
- Composition 正確
|
|
84
|
+
- Popover 不放互動破壞(Dialog trigger in Popover content 避免)
|
|
85
|
+
- Accordion / Tabs / Carousel 不巢狀
|
|
86
|
+
- Radix API 用對
|
|
87
|
+
- Dialog 有 DialogTitle / DialogDescription for a11y
|
|
88
|
+
- DropdownMenu 不當 Select 用
|
|
89
|
+
|
|
90
|
+
### Dim 4 — Mindset adherence
|
|
91
|
+
|
|
92
|
+
對齊 CLAUDE.md 5 條 mindset:
|
|
93
|
+
|
|
94
|
+
- **M1 對標世界級**:新 pattern 有對標備註? 或找得到對應既有元件?
|
|
95
|
+
- **M2 不憑直覺發明**:新數值(gap / padding / font-size)前有 grep 既有?
|
|
96
|
+
- **M3 改一處看三處**:若改 DS 的 cva defaultVariants,spec / docblock / anatomy 三方同步?
|
|
97
|
+
- **M4 真實業務場景**:stories / examples 用真實場景 (Jira / Stripe / Notion...)?無 `Option A/B/C` / `按鈕一` / `Rule A`?
|
|
98
|
+
- **M5 猶豫就問**:code 裡有 TODO-未確認留白?
|
|
99
|
+
|
|
100
|
+
### Dim 5 — 視覺幾何(Mindset #1 視覺擴充 + node_modules/@qijenchen/design-system/ds-canonical/references/ui-dev-rules.md「同 flex 列互動 slot 幾何鐵律」)
|
|
101
|
+
|
|
102
|
+
- 同 flex 行的互動 slot box 尺寸一致(例:FileItem status / delete 都 h-field-sm)
|
|
103
|
+
- hover-bg / ring / focus outline 不溢出 box 吃 gap token
|
|
104
|
+
- padding 對稱正確
|
|
105
|
+
- Typography tier 正確(text-body / text-caption / etc.,不自造 `text-[13px]`)
|
|
106
|
+
|
|
107
|
+
### Dim 6 — A11y
|
|
108
|
+
|
|
109
|
+
- icon-only 元件有 `aria-label`
|
|
110
|
+
- interactive element `role` 正確
|
|
111
|
+
- Dialog / Popover / Sheet 有 title + description
|
|
112
|
+
- keyboard navigation 可用(Tab / Enter / Esc)
|
|
113
|
+
- color contrast(不用純 color 傳 state — 要 icon / label 配合)
|
|
114
|
+
|
|
115
|
+
詳見 `references/audit-checks.md`。
|
|
116
|
+
|
|
117
|
+
### Dim 7 — D6 設計原則自檢(consumer 是否牴觸 DS canonical)
|
|
118
|
+
|
|
119
|
+
chain `node_modules/@qijenchen/design-system/ds-canonical/skills/design-system-audit/references/principle-audit-protocol.md` 做 4 子維 scoped 對 consumer code:
|
|
120
|
+
|
|
121
|
+
- **D6a 合理性**:consumer 自己的設計判斷是否有 rationale(為什麼這樣用 DS 元件)
|
|
122
|
+
- **D6b 一致性**:跨 feature 同概念處理一致(同 team 兩頁面 dismiss 不應用不同方式)
|
|
123
|
+
- **D6c 無矛盾**:consumer 實作是否牴觸 DS spec 聲明(例:用 Button 作 dismiss 明顯違 item-anatomy SSOT)
|
|
124
|
+
- **D6d 完整性**:state 覆蓋(error / loading / empty)
|
|
125
|
+
|
|
126
|
+
判斷 auto vs STOP 依 protocol 公式。修 consumer code 一致化 = AUTO;建議修 DS canonical 本身 = STOP 提議。
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Workflow
|
|
131
|
+
|
|
132
|
+
### Phase 0 — Scope
|
|
133
|
+
|
|
134
|
+
確認 audit target:file / folder / feature area。提問 user 若模糊。禁止掃整個 repo(失焦)。
|
|
135
|
+
|
|
136
|
+
### Phase 1 — Parallel 6-dim audit
|
|
137
|
+
|
|
138
|
+
7 個維度各自獨立 grep + code review。可 parallelize。
|
|
139
|
+
|
|
140
|
+
### Phase 2 — Report
|
|
141
|
+
|
|
142
|
+
產出 report 表格:
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
| Dim | File:Line | Finding | Severity | Fix suggestion |
|
|
146
|
+
|-----|-----------|---------|----------|----------------|
|
|
147
|
+
| 1 Token | src/app/foo.tsx:42 | 硬寫 `#3b82f6` | P0 | 改 var(--primary) |
|
|
148
|
+
| 2 Layout | src/app/bar.tsx:87 | 自己寫 icon+title+desc 垂直堆疊 | P1 | 改用 `<Empty>` |
|
|
149
|
+
| 3 Component | src/app/baz.tsx:12 | icon-only Button 無 aria-label | P0 | 加 aria-label |
|
|
150
|
+
| ... |
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### ⚠️ Checkpoint 1 — Triage & fix decision
|
|
154
|
+
|
|
155
|
+
類似 design-system-audit 的 triage checkpoint:
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
🔍 Audit 結果
|
|
159
|
+
|
|
160
|
+
P0(必修,無爭議):N 項
|
|
161
|
+
P1(批次修 + review):M 項
|
|
162
|
+
P2(需討論):K 項
|
|
163
|
+
|
|
164
|
+
先修 P0?還是全給 user 看?
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
詳見 `references/report-template.md`。
|
|
168
|
+
|
|
169
|
+
### Phase 3 — Fix(optional)
|
|
170
|
+
|
|
171
|
+
若 user 同意 fix,surgical 修復。每批(Dim 1 / Dim 2 / ...)一個 commit。
|
|
172
|
+
|
|
173
|
+
### Phase 4 — Verify
|
|
174
|
+
|
|
175
|
+
- `npx tsc --noEmit` 通過
|
|
176
|
+
- re-run 本 skill(縮窄到原 findings)確認 zero regression
|
|
177
|
+
|
|
178
|
+
### Phase 5 — Visual audit(stakeholder-gate,mandatory on stakeholder-visible work)
|
|
179
|
+
|
|
180
|
+
對齊 **CLAUDE.md 稽核 canonical Tier 1 stakeholder-gate**:產品 UI 要給 stakeholder / end-user 看之前,**code + visual 雙層都要過**。Phase 1-4 是 code 層;本 Phase 補視覺層。
|
|
181
|
+
|
|
182
|
+
**Input**:Phase 4 verify 過關的產品 UI(screens / routes / embedded widgets)
|
|
183
|
+
|
|
184
|
+
**Process**:
|
|
185
|
+
1. 確認 user 有提供 **URL 清單**(產品 app routes)或 **Storybook scenario id**(若產品 stories 在 Storybook):
|
|
186
|
+
- URL mode:`npm run visual-audit -- --urls=<csv>`(例:`--urls=http://localhost:3000/inbox,http://localhost:3000/settings`)
|
|
187
|
+
- Storybook mode:`npm run visual-audit -- --scope=component:<topic>`
|
|
188
|
+
2. **Layer A mechanical**(auto):WCAG 對比度 + DOM 幾何 assertion + retina screenshot → `snapshots/`
|
|
189
|
+
3. **Layer B AI judgement**(chain `/visual-audit` skill):讀 `snapshots/*.png`,判斷設計合理性(視覺對齊 / 覆蓋限制 / 世界級對照 / typography hierarchy)
|
|
190
|
+
4. Violation 分級:
|
|
191
|
+
- Contrast AA 不過 → **P0**(a11y 強制)
|
|
192
|
+
- Geometry assertion fail → **P0**(機械規則違反)
|
|
193
|
+
- Layer B AI 視覺判斷 finding → 按嚴重度 P0 / P1 / P2
|
|
194
|
+
|
|
195
|
+
**Gate 規則**:P0 有 → 停下修,不放給 stakeholder;P1 / P2 走跟 Phase 2 Report 同樣 user-decision 流程。
|
|
196
|
+
|
|
197
|
+
**何時可跳**:內部 UI(只給 engineer / admin 看,非 stakeholder / end-user)→ user 明示 skip,但建議跑一次 Layer A 抓 a11y P0。
|
|
198
|
+
|
|
199
|
+
**為什麼 mandatory**:code audit 對 + spec 對,視覺仍可能錯(對比不夠、overlay 疊到文字、跨 OS 捲軸跑版)——這類 bug 只有視覺層抓得到。產品給 stakeholder / user 看時 = stakeholder-visible artifact,必過 Tier 1 gate。
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## 呼叫時的回答格式
|
|
204
|
+
|
|
205
|
+
audit 完畢報告應含:
|
|
206
|
+
1. **Scope**:audit 了什麼(path / file 數量)
|
|
207
|
+
2. **Summary**:per dimension 的 pass/fail 數
|
|
208
|
+
3. **Findings table**:具體 file:line + severity + fix
|
|
209
|
+
4. **Recommendations**:P0 優先 / 建議修順序
|
|
210
|
+
5. **Next step**:等 user Checkpoint 1 決策
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Non-goals
|
|
215
|
+
|
|
216
|
+
- 不 audit DS 本身(走 /design-system-audit)
|
|
217
|
+
- 不改 user 未同意的 P1/P2(僅 P0 可自動修,需 user 決策 P1+)
|
|
218
|
+
- 不 audit 業務邏輯正確性(本 skill 管 UI / DS consumption / design principles,不管 data flow 對不對)
|
|
219
|
+
- 不 replace code review(本 skill 是 pre-review self-check,不是 final QA)
|
|
220
|
+
|
|
221
|
+
## Common failure modes
|
|
222
|
+
|
|
223
|
+
- **Scope 太廣**:掃整個 repo 導致 findings 爆量,triage 崩潰 → 限制 scope 到 feature / folder
|
|
224
|
+
- **Dim 間互相矛盾**:Dim 2 建議用 Empty 但 Dim 3 說 Button 該在某處 — surface 而非自己選
|
|
225
|
+
- **P0/P1 分類偏誤**:把明確 bug 當 P1 / 把 style preference 當 P0 — 嚴格按 audit-checks.md 分類
|
|
226
|
+
- **AI 自行修 P2**:違反 checkpoint 精神,每個 P2 都是設計決策
|
|
227
|
+
|
|
228
|
+
## References
|
|
229
|
+
|
|
230
|
+
- [references/audit-checks.md](references/audit-checks.md) — 7 維度具體 grep pattern + rule
|
|
231
|
+
- [references/common-misuses.md](references/common-misuses.md) — 常見元件誤用 negative example 庫
|
|
232
|
+
- [references/report-template.md](references/report-template.md) — P0/P1/P2 severity 分類 + report 格式
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# Audit Checks — 7 維度 grep pattern + rule
|
|
2
|
+
|
|
3
|
+
每個維度的具體 check。AI Phase 1 parallel 執行時依此 grep + rule 判斷。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Dim 1 — Token 紀律
|
|
8
|
+
|
|
9
|
+
### Check 1.1: shadcn compat alias
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
grep -nE '\b(bg-popover|text-popover-foreground|text-muted-foreground|bg-accent|text-accent-foreground|bg-destructive|bg-background|bg-card|text-card-foreground|border-input|text-primary-foreground)\b' {target}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**Severity**: P0。**Fix**: 對映見 token 防線 `lib/_token_hygiene.sh` + `check_opacity_token_usage.sh`。
|
|
16
|
+
|
|
17
|
+
### Check 1.2: Tailwind default shadow
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
grep -nE '\bshadow-(sm|md|lg|xl|2xl|inner)\b' {target}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Severity**: P0。**Fix**: shadow-sm → shadow-[var(--elevation-100)] / shadow-md → shadow-[var(--elevation-200)] / shadow-lg → shadow-[var(--elevation-200)](elevation-300 不存在,最高 tier 200)。
|
|
24
|
+
|
|
25
|
+
### Check 1.3: Tailwind v4 `[--foo]` shorthand
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
grep -nE '\[--[a-z][a-z0-9-]*\]' {target} | grep -v '\[&'
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Severity**: P0(silent fail)。**Fix**: `[--foo]` → `[var(--foo)]`。
|
|
32
|
+
|
|
33
|
+
### Check 1.4: 硬寫 hex / rgb / hsl
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
grep -nE '#[0-9a-fA-F]{3,8}\b|rgb\(|rgba\(|hsl\(|hsla\(' {target}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Severity**: P0。**Exception**: `#fff` 在 Avatar / Tag 白字變體是 documented cva exception(object map 非 cva,per CLAUDE.md `cva 適用範圍`);anatomy inspector chrome 顏色 highlight(`bg: 'rgba(...)'` in `.anatomy.stories.tsx`)。**Fix**: 改 semantic token(`var(--primary)` / `bg-primary` 等)。
|
|
40
|
+
|
|
41
|
+
### Check 1.5: 硬寫 px 當應用 token
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
grep -nE 'w-\[\d+px\]|h-\[\d+px\]|text-\[\d+px\]|gap-\[\d+px\]|p-\[\d+px\]' {target}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Severity**: P1(需 case-by-case 判斷)。**Rule**: 若有對應 field-height / layout-space / icon-size token,應改 token;若是 genuinely unique 尺寸則保留 + spec 解釋。
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Dim 2 — Layout primitive 消費
|
|
52
|
+
|
|
53
|
+
### Check 2.1: icon+title+desc 垂直居中 → 應消費 Empty
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
# grep for potential misuse patterns
|
|
57
|
+
grep -nE 'flex.*flex-col.*items-center.*text-center' {target}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
對每 hit,檢查是否有:
|
|
61
|
+
- LucideIcon 置頂 + title + desc(3-layer vertical stack)
|
|
62
|
+
- 且 parent 是**空狀態 / 空目錄 / 無資料 / 拖放區 / 首次引導**等語境
|
|
63
|
+
|
|
64
|
+
**Severity**: P1。**Fix**: `<Empty icon={Icon} title="..." description="..." />`。
|
|
65
|
+
|
|
66
|
+
### Check 2.2: row prefix+content+suffix → 應消費 item-layout
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
grep -nE 'flex.*items-center.*gap-2' {target}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
對每 hit,檢查是否是:
|
|
73
|
+
- 單列 row with icon/avatar 左 + content 中 + action 右
|
|
74
|
+
- 且是 menu / list / tree / file 類項目
|
|
75
|
+
|
|
76
|
+
**Severity**: P1。**Fix**: 消費 `MenuItem` / `TreeItem` / `SidebarMenuButton` 等既有 row primitive(或組合 item-anatomy 的 slot components `<ItemIcon>` / `<ItemLabel>` / `<ItemSuffix>` 等)。
|
|
77
|
+
|
|
78
|
+
### Check 2.3: overlay Header/Body/Footer → 應消費 overlay-surface
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
grep -nE 'border-b border-divider.*px-\[var\(--layout-space-loose\)\]' {target}
|
|
82
|
+
grep -nE 'border-t border-divider.*px-\[var\(--layout-space-loose\)\]' {target}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
若在 Dialog / Popover / Sheet / Drawer consumer 重複寫這個 pattern → flag。
|
|
86
|
+
|
|
87
|
+
**Severity**: P1。**Fix**: 用 `<SurfaceHeader>` / `<SurfaceBody>` / `<SurfaceFooter>` 或 Dialog 的 sub-components。
|
|
88
|
+
|
|
89
|
+
### Check 2.4: native overflow-(auto|scroll) → 應用 ScrollArea
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
grep -nE '\boverflow-(auto|scroll|x-auto|x-scroll|y-auto|y-scroll)\b' {target} | grep -vE 'scrollbar-none|useOverflow|horizontal-overflow'
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Severity**: P1(跨 OS drift)。**Fix**: 改用 `<ScrollArea>`;若是刻意隱藏 + fade-mask 改用 `horizontal-overflow` pattern。
|
|
96
|
+
|
|
97
|
+
### Check 2.5: 硬寫 aspect-* → 應用 AspectRatio
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
grep -nE '\baspect-(video|square|\[[\d/]+\])' {target}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Exception**: icon-only Button 以 `aspect-square w-X` 形成正方形 hit area(如 Sidebar trigger)屬幾何 layout 不是 media container,保留。
|
|
104
|
+
|
|
105
|
+
**Severity**: P2(主要影響:未來 ratio 變化時漂移)。**Fix**: media/image container 改用 `<AspectRatio ratio={n}>`。
|
|
106
|
+
|
|
107
|
+
### Check 2.6: Field wrapper 缺失
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
grep -nE '<input(?![^>]*ref=)' {target}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
裸 `<input>` 未包 Field / fieldWrapperStyles → flag。
|
|
114
|
+
|
|
115
|
+
**Severity**: P1。**Fix**: 包 Field 或消費 Input 元件。
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Dim 3 — 元件使用正確性
|
|
120
|
+
|
|
121
|
+
### Check 3.1: icon-only 無 aria-label
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
grep -nE '(iconOnly|startIcon|ItemInlineAction)' {target}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
每 hit 檢查同行或附近有 `aria-label=` / `label=`。
|
|
128
|
+
|
|
129
|
+
**Severity**: P0(a11y 必要)。**Fix**: 加 `aria-label="..."`。
|
|
130
|
+
|
|
131
|
+
### Check 3.2: Primary Button 堆疊
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
grep -nE 'variant="primary"' {target}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
若同一 parent 出現多個 primary Button → flag(每 row 應只一個 primary action)。
|
|
138
|
+
|
|
139
|
+
**Severity**: P1。**Fix**: 次要 action 改 tertiary / secondary。
|
|
140
|
+
|
|
141
|
+
### Check 3.3: Dialog / Popover / Sheet 缺 title / description
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
grep -nE '<DialogContent>|<PopoverContent>|<SheetContent>' {target}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
每 hit 追蹤 children 是否含 DialogTitle / DialogDescription。
|
|
148
|
+
|
|
149
|
+
**Severity**: P0(Dialog a11y 必要)/ P1(Popover, 可選但建議)。**Fix**: 加 Title / Description(Radix 已提供)。
|
|
150
|
+
|
|
151
|
+
### Check 3.4: 巢狀 Accordion / Tabs / Carousel
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
grep -nE '<(Accordion|Tabs|Carousel)' {target}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
檢查是否有同名元件巢狀(兩層以上)。
|
|
158
|
+
|
|
159
|
+
**Severity**: P1(UX 使用者迷失)。**Fix**: flatten 結構或改用 TreeView。
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Dim 4 — Mindset adherence
|
|
164
|
+
|
|
165
|
+
### Check 4.1: placeholder 文案(M4 違反)
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
grep -nE '(Option [A-E]|按鈕[一二三四五]|Rule [A-E]|Variant [A-E]|Placeholder|Lorem ipsum|Foo|Bar|Test value)' {target}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**Severity**: P1(違反 Mindset #4 「真實業務場景」)。**Fix**: 改真實 SaaS 場景(Jira / Stripe / Notion / Linear / Figma)。
|
|
172
|
+
|
|
173
|
+
### Check 4.2: TODO-未確認留白(M5 違反)
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
grep -nE '(TODO:\s*待確認|TODO:\s*decide|FIXME|XXX)' {target}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**Severity**: P2(必討論)。**Fix**: 若是規格未定應 surface 給 user 決策,不在 code 留模糊 TODO。
|
|
180
|
+
|
|
181
|
+
### Check 4.3: cva defaultVariants 三方漂移(M3)
|
|
182
|
+
|
|
183
|
+
**適用情境**: 若 consumer 在 app 層 override cva 的 defaultVariants(罕見但發生過),檢查是否同步 spec / docblock / anatomy。
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Dim 5 — 視覺幾何
|
|
188
|
+
|
|
189
|
+
### Check 5.1: 同 flex 行互動 slot box 尺寸不一
|
|
190
|
+
|
|
191
|
+
**手動 review pattern**: 找 `flex items-center gap-*` 包含多個 interactive element(Button / ItemInlineActionButton / Link),確認他們的 box 尺寸一致。
|
|
192
|
+
|
|
193
|
+
例: FileItem `status slot(16px)` + `delete Button sm(28px)` = 不一致 → hover-bg 吃 gap。
|
|
194
|
+
|
|
195
|
+
**Severity**: P0(世界級 DS 鐵律違反,違反 node_modules/@qijenchen/design-system/ds-canonical/references/ui-dev-rules.md「同 flex 列的互動 slot 幾何鐵律」)。
|
|
196
|
+
|
|
197
|
+
### Check 5.2: 自造 typography tier
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
grep -nE 'text-\[\d+px\]' {target}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
用 `text-[13px]` 等自造尺寸 → flag。
|
|
204
|
+
|
|
205
|
+
**Severity**: P1。**Fix**: 改用 DS typography utility(text-caption / text-body / text-body-lg / h1 / h2 等)。
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Dim 6 — A11y
|
|
210
|
+
|
|
211
|
+
### Check 6.1: icon-only 無 aria-label(已含 Check 3.1)
|
|
212
|
+
|
|
213
|
+
### Check 6.2: 非 button 用 onClick
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
grep -nE '<(div|span)[^>]*onClick='
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
非 `<button>` 元素綁 onClick → flag(缺 keyboard / screen reader)。
|
|
220
|
+
|
|
221
|
+
**Severity**: P0。**Fix**: 改 `<button>` 或加 `role="button" tabIndex={0} onKeyDown={...}`。
|
|
222
|
+
|
|
223
|
+
### Check 6.3: color 作唯一 state signal
|
|
224
|
+
|
|
225
|
+
**手動 review**: 只用紅色 / 綠色 傳 error / success 無 icon 或 label → 色盲不可辨。
|
|
226
|
+
|
|
227
|
+
**Severity**: P1(WCAG 1.4.1 違反)。**Fix**: 色 + icon 雙通道(CheckCircle / XCircle 等)。
|
|
228
|
+
|
|
229
|
+
### Check 6.4: keyboard 陷阱
|
|
230
|
+
|
|
231
|
+
**手動 review**: Modal 內 focus 能 loop(tab 出去要能回來);esc 能關;Arrow keys 導航 list。
|
|
232
|
+
|
|
233
|
+
**Severity**: P0 若為 Modal / Dialog。**Fix**: 用 Radix primitives(已內建 focus trap)。
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## 合法例外(documented)
|
|
238
|
+
|
|
239
|
+
以下 hit 不是 bug,由既有 spec / CLAUDE.md 記錄為合理例外:
|
|
240
|
+
|
|
241
|
+
- **Avatar 白字**(`text: '#fff'`): cva 適用範圍例外(style prop 驅動用 object map 而非 cva),per `cva 適用範圍` 章節。
|
|
242
|
+
- **Anatomy inspector chrome**(`bg: 'rgba(...)'` in `.anatomy.stories.tsx`): dev-tool highlight 非 consumer UI token。
|
|
243
|
+
- **Rating yellow stars**(`bg-warning` 黃星): 世界級 convention(Amazon / Google / Yelp 皆黃),spec line 73 明文 documented exception。
|
|
244
|
+
- **uiSize icon-only button**(`aspect-square w-X`): 幾何性 square,非 media container,per uiSize.spec.md「calc 不用 aspect-square」主體邏輯。
|
|
245
|
+
|
|
246
|
+
遇到 hit 時檢查是否屬上述 documented exception,若是則不 flag,否則 flag。
|