@qijenchen/design-system 0.1.0-beta.69 → 0.1.0-beta.71
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/ds-canonical/fork/governance.lock +112 -0
- package/ds-canonical/fork/hooks/block_prototype_imports.py +111 -0
- package/ds-canonical/fork/hooks/check_chrome_header_avatar_canonical.sh +95 -0
- package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +349 -0
- package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +132 -0
- package/ds-canonical/fork/hooks/check_escape_marker_abuse.sh +140 -0
- package/ds-canonical/fork/hooks/check_field_family_invariants.sh +250 -0
- package/ds-canonical/fork/hooks/check_fork_product_quality.sh +36 -0
- package/ds-canonical/fork/hooks/check_item_list_gap.sh +54 -0
- package/ds-canonical/fork/hooks/check_layout_space_magic_numbers.sh +96 -0
- package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +149 -0
- package/ds-canonical/fork/hooks/check_pattern_invariants.sh +196 -0
- package/ds-canonical/fork/hooks/check_sidebar_menu_button_implicit_wrap.sh +86 -0
- package/ds-canonical/fork/hooks/check_tailwind_wildcard_in_docs.sh +79 -0
- package/ds-canonical/fork/hooks/inject_deploy_url_after_push.sh +238 -0
- package/ds-canonical/fork/launchers/fork-governance-dispatcher.sh +44 -0
- package/ds-canonical/fork/launchers/inject_fork_governance_preamble.sh +46 -0
- package/ds-canonical/fork/launchers/settings-hooks.json +58 -0
- package/ds-canonical/fork/manifest.json +79 -0
- package/ds-canonical/fork/preamble.md +495 -0
- package/ds-canonical/hooks/check_consumer_app_invariants.sh +19 -0
- package/ds-canonical/references/scenario-definition.md +4 -4
- package/ds-canonical/skills/design-system-audit/SKILL.md +1 -1
- package/llms-full.txt +1 -1
- package/llms.txt +1 -1
- package/package.json +5 -1
- package/src/story-governance/category-matrix.json +132 -0
- package/src/tokens/utility-registry.json +124 -0
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
|
|
21
21
|
**用戶**:純做產品 / 不需看 DS source 的人
|
|
22
22
|
**入口**:`ajenchen/ds-product-template` GitHub「Use this template」(該 repo 內容 = mirror artifact,**非 SSOT**,by 自動 mirror workflow auto-generate from DS repo)
|
|
23
|
-
**他拿到**:scaffold + 治理 via
|
|
23
|
+
**他拿到**:scaffold + 治理 via C-prime committed-config(.claude hooks + SessionStart preamble 注入)+ DS + 治理本體 via npm
|
|
24
24
|
**DS 取得方式**:`@qijenchen/design-system` npm registry(`^X.Y.Z`)
|
|
25
|
-
**Governance
|
|
26
|
-
**E2E 流程**:`fork → npm install
|
|
25
|
+
**Governance 取得**:committed `.claude/settings.json`(dispatcher hooks + fail-open bootstrap)+ SessionStart 注入 npm-current preamble;本體在 npm `ds-canonical/fork`(`npm install` / `npm run sync-all` 同步)。**不需 /plugin install**(雲端不可靠 #62174/#63028)
|
|
26
|
+
**E2E 流程**:`fork → npm install(治理本體隨 npm + committed hook 自動生效,免 plugin)→ claude → npm run setup:netlify(Netlify env var 設 STORYBOOK_BASIC_AUTH = user:password,免費機制走 edge function basic-auth)→ npm run create-app order-dashboard → npm install → npm run storybook → git push`
|
|
27
27
|
**禁**:import `@qijenchen/design-system/src/**` 或 `/dist/**`(`lint:imports` 攔)
|
|
28
28
|
|
|
29
29
|
## 2. SSOT Architecture
|
|
@@ -93,7 +93,7 @@ ajenchen/ds-product-template (published repo) ← Mirror artifact ────
|
|
|
93
93
|
| B3 | Mirror workspaces apps-only | `jq '.workspaces' /tmp/mirror/package.json` |
|
|
94
94
|
| B4 | Mirror `.storybook/main.ts` apps-only glob | grep stories |
|
|
95
95
|
| B5 | Mirror 含 `check-plugin-installed.mjs` + `setup-netlify-access.mjs` + `create-app.mjs` | ls /tmp/mirror/scripts/ |
|
|
96
|
-
| B6 |
|
|
96
|
+
| B6 | C-prime committed 治理(免 plugin):`npm install` 後 `ds-canonical/fork` 本體就位 + SessionStart 注入設計紀律 preamble + dispatcher 跑 fork hooks;既有 fork `sync-all` 移除 obsolete plugin-era hook | `node scripts/test-fork-governance.mjs` + `node scripts/dogfood-prepublish-verify.mjs` |
|
|
97
97
|
| B7 | `npm run create-app` 同 Scenario A | run + ls |
|
|
98
98
|
|
|
99
99
|
### Mirror integrity(7 cases)
|
|
@@ -188,7 +188,7 @@ User 2026-05-15 verbatim 抓「DS 深度稽核漏 storybook content quality」+
|
|
|
188
188
|
| 68 | **Stories-vs-spec canonical drift**(2026-05-27 codify per user「DS 自己 stories 教錯 = consumer 抄 stories 抄錯」root cause)| 對每 component `*.stories.tsx` + `*.anatomy.stories.tsx` + `*.principles.stories.tsx` grep:含 `<SidebarHeader>` 內 `<ItemAvatar>` / 同類 spec 明文禁止的 pattern → 違反(DS 教 consumer 錯 pattern,類似 2026-05-27 sidebar 3 stories 在 WorkspaceBrand 用 ItemAvatar 違反 chrome header canonical)。**主防線 = R8 registry**(`.claude/references/story-baseline-registry.json` requiredHelpers / antiPatterns + `check_story_invariants.sh` R8/R9 機械攔)+ `check_chrome_header_avatar_canonical.sh` / `check_sidebar_menu_button_implicit_wrap.sh` 具體錨例 hook;`// @canonical-pattern:` / `// @anti-pattern:` 文字 marker **降格為建議性輔助**(2026-06-12 R2 拍板 — 全庫僅 sidebar.stories 2 處採用且無機械強制 = 紙防線,不再「必加」;存在時 audit 順驗其與 spec 一致)。配 Dim 53(spec-vs-code)+ 本 dim(spec-vs-stories)雙向 drift verify;系統性 stories drift audit run via design-system-audit Dim 68 batch sweep |
|
|
189
189
|
| 69 | **Consumer no-DS-catalog enforcement**(2026-05-27 M31 codex synthesis per user「眼不見為淨」+「做產品真的能使用跟 ds repo 一模一樣的元件做產品嗎?」)| 對 consumer `apps/**/*.stories.tsx` grep:basename 為 `EveryDsComponent` / `AllDsComponents` / catalog naming + `Object.keys(DS).map` iterate-render + mass hand-mock(≥5 distinct `<DS.X>` 單 file)→ 違反(DS catalog 是 DS Storybook 唯一 SSOT,consumer 重寫必 drift,2026-05-27 錨例 7 bug)。Hook `check_consumer_app_invariants.sh(r1,2026-06-11 merge)` PostToolUse Write/Edit BLOCKER,escape `// @consumer-catalog-allow:`。允許 portal proxy(iframe to DS Storybook)|
|
|
190
190
|
| 70 | **Consumer @story-baseline enforcement**(2026-05-27 M31 codex synthesis)| 對 consumer `apps/**/*.stories.tsx` grep:用高風險 DS primitive(DataTable / Dialog / Sheet / Popover / DropdownMenu / Tooltip / HoverCard / LinkInput / RadioGroup / CircularProgress / AppShell / Sidebar)但無 `// @story-baseline: <DS-story-path>#<exportName>` marker → 違反(consumer 必 reference DS canonical story 才 enable visual diff CI)。Hook `check_consumer_app_invariants.sh(r2,2026-06-11 merge)` PostToolUse BLOCKER,escape `// @story-baseline-allow:`。SSOT mapping → `ds-story-manifest.json`(DS package ship)|
|
|
191
|
-
| 71 | **Consumer DS primitive misuse anti-pattern**(2026-05-27 per user「做產品真的要能使用跟 ds repo 一模一樣的元件」)| 對 consumer `apps/**/*.{tsx,ts}` production + stories grep:`<CircularProgress size={N}>` literal number 覆蓋 default 24 / `<RadioGroupItem>` 無 `<SelectionItem control={...}>` wrap / `<DataTable columns={[single-col]}>` minimal / `<LinkInput placeholder=...>` 無 `value` prop / `<Empty title=...>` 無 icon AND 無 description / Overlay story 無 `defaultOpen` 視覺 snapshot 看不到 content / **硬寫色值-字級-shadow 繞 token(`bg-[#hex]` / `text-[14px]` / `shadow-md`,2026-06-02 Pattern 8,CF conformance-model 主防線)** / **AppShell slot 餵 raw element(`sidebar={<div>}` 等,2026-06-12 Pattern 9,app-shell.spec:296-299)**。**判斷層補掃(2026-06-12 fork 四不像 + 先驗滲漏 anchor;hook 零誤判原則不上 regex)**:(a) page-level entry 手拼 raw 殼而無 `<DS.AppShell>`(對照 app-shell.spec「何時用/不用」表;愈不用 DS 愈不觸 hook = 反直覺洞)(b) 手刻 right panel(`w-[Npx] border-l` div,該走 `aside={<AppShellAside>}`)(c) ChromeHeader/頁頂 tabs 沒走 `withTabs` lockstep(header-canonical.spec「withTabs 連動」段)(d) BulkActionBar 內 primary 鈕 / 浮層 shadow(bulk-action-bar.spec 禁止事項 — regex 無法 bound 到 actions slot,判斷層接)(e) FileViewer toolbar 加鈕不走 `onCapabilitiesChange`(file-viewer.spec:183-194;R9 skip-list 豁免該家族故無寫入網)(f) chrome 面(ChromeHeader/SidebarFooter)title 下第二行(registry 簽名涵蓋 stories;fork production code 由本 dim 接)。Hook `check_consumer_app_invariants.sh(r3,2026-06-11 merge)` BLOCKER。Per-violation cite spec.md file:line。Escape `// @ds-misuse-allow:` |
|
|
191
|
+
| 71 | **Consumer DS primitive misuse anti-pattern**(2026-05-27 per user「做產品真的要能使用跟 ds repo 一模一樣的元件」)| 對 consumer `apps/**/*.{tsx,ts}` production + stories grep:`<CircularProgress size={N}>` literal number 覆蓋 default 24 / `<RadioGroupItem>` 無 `<SelectionItem control={...}>` wrap / `<DataTable columns={[single-col]}>` minimal / `<LinkInput placeholder=...>` 無 `value` prop / `<Empty title=...>` 無 icon AND 無 description / Overlay story 無 `defaultOpen` 視覺 snapshot 看不到 content / **硬寫色值-字級-shadow 繞 token(`bg-[#hex]` / `text-[14px]` / `shadow-md`,2026-06-02 Pattern 8,CF conformance-model 主防線)** / **AppShell slot 餵 raw element(`sidebar={<div>}` 等,2026-06-12 Pattern 9,app-shell.spec:296-299)** / **手刻 RAW primitive 取代 DS 元件(raw `<table>`+`<thead>`/`<th>`→`<DataTable>` / `<img rounded-full>`→`<Avatar>` / native `<select>`→`<Select>` / `<hr>`→`<Separator>`,2026-06-16 Pattern 10,user 抓 fork prototype 手刻 table 不用 DataTable;反 pattern 由 `build-ui-canonicals.md` ❌→✅ 對照表 SSOT 驅動;落實「優先消費既有元件」大原則機械閘 — 補 Pattern 1-9 只抓「DS 元件用錯」、漏「根本沒用 DS 元件亂刻 raw HTML」之洞;`@ds-misuse-allow:` 有理由可豁免)**。**判斷層補掃(2026-06-12 fork 四不像 + 先驗滲漏 anchor;hook 零誤判原則不上 regex)**:(a) page-level entry 手拼 raw 殼而無 `<DS.AppShell>`(對照 app-shell.spec「何時用/不用」表;愈不用 DS 愈不觸 hook = 反直覺洞)(b) 手刻 right panel(`w-[Npx] border-l` div,該走 `aside={<AppShellAside>}`)(c) ChromeHeader/頁頂 tabs 沒走 `withTabs` lockstep(header-canonical.spec「withTabs 連動」段)(d) BulkActionBar 內 primary 鈕 / 浮層 shadow(bulk-action-bar.spec 禁止事項 — regex 無法 bound 到 actions slot,判斷層接)(e) FileViewer toolbar 加鈕不走 `onCapabilitiesChange`(file-viewer.spec:183-194;R9 skip-list 豁免該家族故無寫入網)(f) chrome 面(ChromeHeader/SidebarFooter)title 下第二行(registry 簽名涵蓋 stories;fork production code 由本 dim 接)。Hook `check_consumer_app_invariants.sh(r3,2026-06-11 merge)` BLOCKER。Per-violation cite spec.md file:line。Escape `// @ds-misuse-allow:` |
|
|
192
192
|
| 72 | **DS API surface tightening**(2026-05-27 — 治標 vs 治本)| Hook 71 偵測 anti-pattern 是 lint 層攔截;治本要 DS API design 強到 misuse 即 fail tsc。Audit:逐 component review API surface — `size?: number` 該改 `'sm'\|'md'\|'lg'` enum / `columns: Column[]` 該加 min length runtime check / `title` + `description` 該有 type-level XOR / Overlay primitive `defaultOpen` 該 require explicit。配套 codify in `tightening-roadmap.md`(若存在;不存在則以 `props-naming.md` + 各 spec API 段為準,對齊 audit-prompts.md dim 72),分 quarter ship。對應 Dim 71 是攔當前 misuse,本 dim 是消除未來 misuse 可能 |
|
|
193
193
|
| 73 | **Full-story visual+interaction sweep enforce**(2026-05-27 codex M31 P0 finding)| Audit report JSON `storyResults.length === manifest.totalStories`(916)。Sample < 916 = reject(per user「不准抽樣」)。Hook `check_full_story_visual_interaction_sweep.sh` PostToolUse audit-report.json BLOCKER。Escape `"_sampling_allowed": "<rationale>"`(極罕見)|
|
|
194
194
|
| 74 | **Overlay open/focus/Escape probe**(2026-05-27 codex M31 P0 finding + user 7-bug 錨點「overlay 沒彈出」)| Consumer story 用 Tooltip / Popover / Dialog / Sheet / DropdownMenu / HoverCard Trigger 必含 `defaultOpen` OR `open={true}` OR `play()` interaction click。Trigger-only catalog = reject(visual snapshot 看不到 content)。Hook `check_overlay_open_focus_escape_probe.sh` BLOCKER。HoverCard exception via `@story-trait-allow: missing-opensnapshot` per codex |
|
package/llms-full.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @qijenchen/design-system — 完整設計參考(llms-full)
|
|
2
2
|
|
|
3
|
-
> 全 component / pattern 的 variants / sizes / 禁止事項。build-time 從 spec.md frontmatter 生成,禁手改。v0.1.0-beta.
|
|
3
|
+
> 全 component / pattern 的 variants / sizes / 禁止事項。build-time 從 spec.md frontmatter 生成,禁手改。v0.1.0-beta.71。
|
|
4
4
|
|
|
5
5
|
# Components
|
|
6
6
|
|
package/llms.txt
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @qijenchen/design-system
|
|
2
2
|
|
|
3
3
|
> World-class React design system(Radix/shadcn + Tailwind v4 + 自訂 design token)。
|
|
4
|
-
> 54 components + 4 public patterns + design tokens。v0.1.0-beta.
|
|
4
|
+
> 54 components + 4 public patterns + design tokens。v0.1.0-beta.71。
|
|
5
5
|
|
|
6
6
|
本檔由 source(spec.md frontmatter + Storybook index)build-time 自動生成,**禁手改**(CI --check drift gate 守)。
|
|
7
7
|
每元件 / pattern 的完整 variants / sizes / 禁止事項 全文見 [llms-full.txt](./llms-full.txt)。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qijenchen/design-system",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.71",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "World-class design system — components, patterns, tokens, hooks (single source of truth for team distribution).",
|
|
6
6
|
"type": "module",
|
|
@@ -9,11 +9,15 @@
|
|
|
9
9
|
"dist",
|
|
10
10
|
"src/**/*.{tsx,ts,css}",
|
|
11
11
|
"src/**/*.spec.md",
|
|
12
|
+
"src/**/*.json",
|
|
12
13
|
"!src/**/*.spec.ts",
|
|
13
14
|
"!src/**/*.test.ts",
|
|
14
15
|
"README.md",
|
|
15
16
|
"CLAUDE.md",
|
|
16
17
|
"ds-canonical",
|
|
18
|
+
"!ds-canonical/.claude",
|
|
19
|
+
"!**/__pycache__",
|
|
20
|
+
"!**/*.pyc",
|
|
17
21
|
"cli-init.mjs",
|
|
18
22
|
"ds-story-manifest.json",
|
|
19
23
|
"llms.txt",
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_doc": "Storybook 分類治理 SSOT(2026-06-05 RFC P1)。每個 DS 單元屬哪 category + 每 category 該守什麼 storybook 規矩。消費者:storybook-config(runtime sidebar order)+ governance scripts/hooks(稽核)+ /story-writing(產生器)。改規矩只改這裡。",
|
|
3
|
+
"_decisionTree": [
|
|
4
|
+
"1. 是原子設計值(色/字/間距/圓角/陰影)? → token",
|
|
5
|
+
"2. 沒有可 render 的件,只是『怎麼組多個元件解決情境』的指南? → pattern",
|
|
6
|
+
"3. 是 fork consumer 的 app scaffold? → template",
|
|
7
|
+
"4. end-user 直接 import 來用(在 root barrel 前門 export + spec frontmatter 無 internal 旗標)? → component",
|
|
8
|
+
"5. 其餘(spec frontmatter 標 internal 旗標 / 只被 DS 內部 wrap 消費、不在 root 前門) → internal"
|
|
9
|
+
],
|
|
10
|
+
"categories": {
|
|
11
|
+
"token": {
|
|
12
|
+
"goal": "全 DS 設計決策的單一來源",
|
|
13
|
+
"titlePrefix": "Design System/Tokens",
|
|
14
|
+
"titleParts": 3,
|
|
15
|
+
"visibility": "public",
|
|
16
|
+
"sidebarOrder": 1,
|
|
17
|
+
"requiredStories": "swatch",
|
|
18
|
+
"renderDemo": "swatch",
|
|
19
|
+
"autodocs": true,
|
|
20
|
+
"anatomyDiagram": "n/a",
|
|
21
|
+
"propsApiTable": false,
|
|
22
|
+
"stateComboMatrix": "n/a",
|
|
23
|
+
"a11yTabTest": "exempt",
|
|
24
|
+
"visualRegression": "swatch",
|
|
25
|
+
"usageDoDont": "thin",
|
|
26
|
+
"codeSnippet": "token",
|
|
27
|
+
"responsiveRtlDensity": "swatch",
|
|
28
|
+
"contentUxWriting": "n/a",
|
|
29
|
+
"openSnapshotCoverable": "n/a",
|
|
30
|
+
"traitShape": false,
|
|
31
|
+
"classification": "n/a-css",
|
|
32
|
+
"rootBarrel": "n/a",
|
|
33
|
+
"universalGuard": true
|
|
34
|
+
},
|
|
35
|
+
"component": {
|
|
36
|
+
"goal": "可直接 render、end-user 直接用的 public 建構塊",
|
|
37
|
+
"titlePrefix": "Design System/Components",
|
|
38
|
+
"titleParts": 4,
|
|
39
|
+
"visibility": "public",
|
|
40
|
+
"sidebarOrder": 2,
|
|
41
|
+
"requiredStories": "three-layer",
|
|
42
|
+
"renderDemo": "required",
|
|
43
|
+
"autodocs": true,
|
|
44
|
+
"anatomyDiagram": "required",
|
|
45
|
+
"propsApiTable": true,
|
|
46
|
+
"stateComboMatrix": "required",
|
|
47
|
+
"a11yTabTest": "required",
|
|
48
|
+
"visualRegression": "full",
|
|
49
|
+
"usageDoDont": "required",
|
|
50
|
+
"codeSnippet": "single",
|
|
51
|
+
"responsiveRtlDensity": "conditional",
|
|
52
|
+
"contentUxWriting": "conditional",
|
|
53
|
+
"openSnapshotCoverable": "required",
|
|
54
|
+
"traitShape": true,
|
|
55
|
+
"classification": "mechanical=public",
|
|
56
|
+
"rootBarrel": "include",
|
|
57
|
+
"universalGuard": false
|
|
58
|
+
},
|
|
59
|
+
"pattern": {
|
|
60
|
+
"goal": "跨元件『如何組合解決情境』的指南 blueprint(非單一 render 件)",
|
|
61
|
+
"titlePrefix": "Design System/Patterns",
|
|
62
|
+
"titleParts": 3,
|
|
63
|
+
"visibility": "public",
|
|
64
|
+
"sidebarOrder": 3,
|
|
65
|
+
"requiredStories": "guidance",
|
|
66
|
+
"renderDemo": "composed-example",
|
|
67
|
+
"autodocs": true,
|
|
68
|
+
"anatomyDiagram": "n/a",
|
|
69
|
+
"propsApiTable": false,
|
|
70
|
+
"stateComboMatrix": "n/a",
|
|
71
|
+
"a11yTabTest": "per-example",
|
|
72
|
+
"visualRegression": "composed",
|
|
73
|
+
"usageDoDont": "core",
|
|
74
|
+
"codeSnippet": "composed",
|
|
75
|
+
"responsiveRtlDensity": "composed",
|
|
76
|
+
"contentUxWriting": "guidance",
|
|
77
|
+
"openSnapshotCoverable": "composed",
|
|
78
|
+
"traitShape": false,
|
|
79
|
+
"classification": "guidance-no-component",
|
|
80
|
+
"rootBarrel": "n/a",
|
|
81
|
+
"universalGuard": true
|
|
82
|
+
},
|
|
83
|
+
"internal": {
|
|
84
|
+
"goal": "只被 DS 內部其他元件 wrap/compose 的 primitive",
|
|
85
|
+
"titlePrefix": "Design System/Internal",
|
|
86
|
+
"titleParts": 4,
|
|
87
|
+
"visibility": "filtered",
|
|
88
|
+
"sidebarOrder": 5,
|
|
89
|
+
"requiredStories": "reference",
|
|
90
|
+
"renderDemo": "reference-only",
|
|
91
|
+
"autodocs": false,
|
|
92
|
+
"anatomyDiagram": "optional",
|
|
93
|
+
"propsApiTable": true,
|
|
94
|
+
"stateComboMatrix": "optional",
|
|
95
|
+
"a11yTabTest": "required",
|
|
96
|
+
"visualRegression": "full",
|
|
97
|
+
"usageDoDont": "thin",
|
|
98
|
+
"codeSnippet": "import-note",
|
|
99
|
+
"responsiveRtlDensity": "conditional",
|
|
100
|
+
"contentUxWriting": "thin",
|
|
101
|
+
"openSnapshotCoverable": "required",
|
|
102
|
+
"traitShape": "optional",
|
|
103
|
+
"classification": "mechanical=internal",
|
|
104
|
+
"rootBarrel": "exclude",
|
|
105
|
+
"universalGuard": false
|
|
106
|
+
},
|
|
107
|
+
"template": {
|
|
108
|
+
"goal": "fork consumer 的 app scaffold(消費端起手式)",
|
|
109
|
+
"titlePrefix": "Apps",
|
|
110
|
+
"titleParts": "apps",
|
|
111
|
+
"visibility": "consumer",
|
|
112
|
+
"sidebarOrder": 9,
|
|
113
|
+
"requiredStories": "app-scenario",
|
|
114
|
+
"renderDemo": "app",
|
|
115
|
+
"autodocs": false,
|
|
116
|
+
"anatomyDiagram": "n/a",
|
|
117
|
+
"propsApiTable": false,
|
|
118
|
+
"stateComboMatrix": "n/a",
|
|
119
|
+
"a11yTabTest": "per-example",
|
|
120
|
+
"visualRegression": "opt",
|
|
121
|
+
"usageDoDont": "n/a",
|
|
122
|
+
"codeSnippet": "scaffold",
|
|
123
|
+
"responsiveRtlDensity": "consumer",
|
|
124
|
+
"contentUxWriting": "n/a",
|
|
125
|
+
"openSnapshotCoverable": "n/a",
|
|
126
|
+
"traitShape": false,
|
|
127
|
+
"classification": "scaffold",
|
|
128
|
+
"rootBarrel": "n/a",
|
|
129
|
+
"universalGuard": true
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./utility-registry.schema.json",
|
|
3
|
+
"_meta": {
|
|
4
|
+
"purpose": "Single SSOT for Tailwind utility allow/block — extracted from typography/radius/opacity/elevation/color spec.md 禁止 lists. Hook reads this(not grep spec.md)to enforce token-first discipline. New token additions or removals → update here first, spec.md cite registry.",
|
|
5
|
+
"owner": "packages/design-system/src/tokens/utility-registry.json",
|
|
6
|
+
"consumed_by": [
|
|
7
|
+
".claude/hooks/check_opacity_token_usage.sh",
|
|
8
|
+
".claude/skills/design-system-audit/references/audit-prompts.md Dim 5"
|
|
9
|
+
],
|
|
10
|
+
"spec_sources": [
|
|
11
|
+
"packages/design-system/src/tokens/typography/typography.spec.md L91-105",
|
|
12
|
+
"packages/design-system/src/tokens/radius/radius.spec.md L57-71",
|
|
13
|
+
"packages/design-system/src/tokens/opacity/opacity.spec.md L53-57",
|
|
14
|
+
"packages/design-system/src/tokens/color/color.spec.md(hardcoded hex/rgb canonical)",
|
|
15
|
+
"packages/design-system/src/tokens/elevation/elevation.spec.md(shadow-{sm,md,lg,xl,2xl} 禁)"
|
|
16
|
+
],
|
|
17
|
+
"rationale": "World-class DS(Atlassian @atlaskit/tokens / Carbon @carbon/themes / Ant ConfigProvider / Polaris polaris-tokens)用 registry + lint, 不靠 grep 各處 spec.md。Rule-of-3 violation 已存在(典型禁止 list 在 3 個 spec.md 各寫一份)— 本檔抽 SSOT。",
|
|
18
|
+
"exceptions": {
|
|
19
|
+
"_added": "2026-05-17 per audit Dim 47 codex 比稿後 codify;補 anatomy stories Inspector panel UI 跟 DS surface 分層 carve-out",
|
|
20
|
+
"anatomy_stories_inspector": {
|
|
21
|
+
"scope": "*.anatomy.stories.tsx — Inspector panel / Side legend / Section H3 decoration UI",
|
|
22
|
+
"allowed_utilities": ["tracking-wider", "font-semibold", "text-[10px]", "text-[11px]", "text-[12px]", "leading-none"],
|
|
23
|
+
"rationale": "Anatomy stories Inspector panel 是 storybook-internal 教學工具 UI(展示元件結構的 side legend / footnote / uppercase header),非 DS component surface。需視覺辨識(uppercase label + 寬 letter-spacing / 小字 metadata)跟 DS 主元件 typography 分層。對齊 Carbon storybook addon、Material storybook addon 共識:tool UI 不受 token-first 約束。`leading-none` 2026-05-21 D1 codex 抓 badge.anatomy L117/118 後加入(10-11px monospace inspector label 需要緊湊 line-height,跟 DS body/body-lg `leading-compact 1.3` 場景分層)。",
|
|
24
|
+
"audit_dim_53_fix": "Dim 47 sub-agent 抓 anatomy stories tracking-wider / font-semibold / text-[NN] / leading-none 多處違反 = false positive(本例外段 codify 後豁免)"
|
|
25
|
+
},
|
|
26
|
+
"token_stories_section_label": {
|
|
27
|
+
"scope": "packages/design-system/src/tokens/**/*.stories.tsx — SectionLabel helper(uppercase + wider tracking section header)",
|
|
28
|
+
"allowed_utilities": ["tracking-wider", "font-semibold"],
|
|
29
|
+
"rationale": "Token stories(color / typography / radius / elevation / opacity / uiSize / layoutSpace / density)是 token 展示 storybook,用 SectionLabel(`uppercase + tracking-wider`)分區 swatch 群組,跟 anatomy stories Inspector panel 同 storybook-internal teaching UI 性質,非 DS component surface。Phase A audit 2026-05-21 codify。"
|
|
30
|
+
},
|
|
31
|
+
"principles_stories_codepre": {
|
|
32
|
+
"scope": "*.principles.stories.tsx — <pre><code> code sample blocks",
|
|
33
|
+
"allowed_utilities": ["text-xs", "text-sm"],
|
|
34
|
+
"rationale": "Code sample 區塊用 <pre><code> + monospace font,需小字呈現程式碼 — 跟 DS prose 不同層級。Polaris / Carbon storybook code blocks 同樣使用 smaller font。"
|
|
35
|
+
},
|
|
36
|
+
"icon_as_text_and_numeric_in_circle": {
|
|
37
|
+
"scope": "Production tsx — icon-as-text / numeric-in-circle / single-line short text in fixed-h container",
|
|
38
|
+
"allowed_utilities": ["leading-none"],
|
|
39
|
+
"rule_one_liner": "icon-as-text / numeric-in-circle 一律用 `leading-none`(不用 `leading-compact`)",
|
|
40
|
+
"rationale": "2026-05-23 Path B codify per user verbatim「或是其實根本不用分?」+「照你建議」:統一 leading-none,不分 fixed-box vs derived-h。對齊 Material UI Avatar `line-height: 1` / Polaris Badge `line-height: 1` / Carbon Tag(不顯式設,等效 1)世界級共識。視覺驗證:固定高度容器 + items-center 主導,line-height 1.0 vs 1.3 vs 1.5 視覺零差別(playwright probe `scripts/probe-leading-migration.mjs` Steps step-number box delta = 0px)。廢除原 2026-05-21 F1 Badge 從 leading-none → leading-compact migration(over-engineered,違 mindset #1 不取巧不發明)+ 原 production_layout_positioning_anchor exception(改 affirmative canonical 不需 exception)。",
|
|
41
|
+
"current_consumers": [
|
|
42
|
+
"Badge/badge.tsx — count badge in fixed h-4 circle",
|
|
43
|
+
"Avatar/avatar.tsx — initial letter in fixed w-N h-N circle",
|
|
44
|
+
"OverflowIndicator/overflow-indicator.tsx — `+N` numeric in fixed h-5/h-6 circle",
|
|
45
|
+
"Steps/steps.tsx — step-number in fixed-diameter circle",
|
|
46
|
+
"Button/button.tsx:465 — overlayBadge inline-block positioning anchor(documented 2026-04-20)",
|
|
47
|
+
"Chart/chart.tsx:247 — recharts tooltip tight flex layout"
|
|
48
|
+
],
|
|
49
|
+
"non_goal": "本 canonical 不適用 body / paragraph / heading typography(那些走 typography.allow `leading-compact` / `leading-normal` token)"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"typography": {
|
|
54
|
+
"allow": [
|
|
55
|
+
"text-h1", "text-h2", "text-h3", "text-h4", "text-h5", "text-h6",
|
|
56
|
+
"text-body", "text-caption", "text-helper", "text-label",
|
|
57
|
+
"leading-compact", "leading-normal",
|
|
58
|
+
"font-normal", "font-medium", "font-bold",
|
|
59
|
+
"tracking-shortcut"
|
|
60
|
+
],
|
|
61
|
+
"block": {
|
|
62
|
+
"size_raw": ["text-xs", "text-sm", "text-base", "text-lg", "text-xl", "text-2xl", "text-3xl", "text-4xl", "text-5xl", "text-6xl", "text-7xl", "text-8xl", "text-9xl"],
|
|
63
|
+
"weight_raw": ["font-thin", "font-extralight", "font-light", "font-semibold", "font-extrabold", "font-black"],
|
|
64
|
+
"leading_numeric": "leading-{N}(use leading-compact / leading-normal token)",
|
|
65
|
+
"tracking_raw": ["tracking-tighter", "tracking-tight", "tracking-wide", "tracking-wider", "tracking-widest"],
|
|
66
|
+
"tracking_raw_rationale": "Block raw Tailwind tracking-* utility(unscoped letter-spacing leaks 跨元件不一致)。需要 wider letter-spacing 場景必 codify role-specific semantic utility — 例如 `tracking-shortcut`(鍵盤快捷鍵 hint,0.1em,對應 --tracking-shortcut token)。新 role 必走 typography.css 新增 `--tracking-<role>` + `@utility tracking-<role>`,再 allow 進本 registry。",
|
|
67
|
+
"inline_style": "style={{ fontSize: ..., lineHeight: ... }}",
|
|
68
|
+
"rationale_path": "packages/design-system/src/tokens/typography/typography.spec.md L91-105"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"radius": {
|
|
72
|
+
"allow": ["rounded-xs", "rounded-sm", "rounded-md", "rounded-lg", "rounded-full"],
|
|
73
|
+
"block": {
|
|
74
|
+
"out_of_range": ["rounded-xl", "rounded-2xl", "rounded-3xl"],
|
|
75
|
+
"ambiguous_default": "rounded(use rounded-md explicit)",
|
|
76
|
+
"arbitrary_value": ["rounded-[6px]", "rounded-[var(--radius-md)]"],
|
|
77
|
+
"inline_style": "style={{ borderRadius: ... }}",
|
|
78
|
+
"rationale_path": "packages/design-system/src/tokens/radius/radius.spec.md L57-71"
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"opacity": {
|
|
82
|
+
"allow": ["opacity-0", "opacity-100", "opacity-disabled"],
|
|
83
|
+
"block": {
|
|
84
|
+
"numeric_tier": ["opacity-5", "opacity-10", "opacity-20", "opacity-25", "opacity-30", "opacity-40", "opacity-50", "opacity-60", "opacity-70", "opacity-75", "opacity-80", "opacity-90", "opacity-95"],
|
|
85
|
+
"arbitrary_value": "opacity-[0.N](use --opacity-disabled or token swap)",
|
|
86
|
+
"rationale_path": "packages/design-system/src/tokens/opacity/opacity.spec.md L53-57",
|
|
87
|
+
"philosophy": "Single semantic token(0.45)vs Tailwind multi-tier(對齊 Polaris / Material / Apple 單值哲學)"
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"elevation": {
|
|
91
|
+
"allow": ["shadow-[var(--elevation-100)]", "shadow-[var(--elevation-100-hover)]", "shadow-[var(--elevation-200)]", "shadow-[var(--elevation-200-hover)]"],
|
|
92
|
+
"block": {
|
|
93
|
+
"tailwind_size": ["shadow-sm", "shadow", "shadow-md", "shadow-lg", "shadow-xl", "shadow-2xl", "shadow-inner"],
|
|
94
|
+
"rationale_path": "packages/design-system/src/tokens/elevation/elevation.spec.md",
|
|
95
|
+
"philosophy": "DS 採 2-tier elevation(100 / 200)語意而非 Tailwind size ladder"
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"spacing": {
|
|
99
|
+
"allow_canonical": "對齊 spec(gap-2/3/4/6/8 等;layout-space token via var())",
|
|
100
|
+
"warn": {
|
|
101
|
+
"micro_gap": ["gap-px", "gap-0.5", "gap-1.5"],
|
|
102
|
+
"rationale": "<4px gap 通常違反 item-anatomy slot 幾何。Allow exception in spec.md(Skeleton bone / inline action 等)but flag for human review."
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"sizing": {
|
|
106
|
+
"warn": {
|
|
107
|
+
"fraction": ["w-1/3", "w-2/3", "w-1/4", "w-3/4", "w-1/5", "w-2/5", "w-3/5", "w-4/5", "w-1/6", "w-5/6", "w-1/12", "w-5/12", "w-7/12", "w-11/12"],
|
|
108
|
+
"rationale": "Fraction width 通常 inside DS component = layout SSOT 漂移。Allow if component spec owns layout(eg. Field labelWidth 比例)but flag。"
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"shadcn_alias": {
|
|
112
|
+
"block": {
|
|
113
|
+
"color_alias": ["bg-popover", "text-popover-foreground", "text-muted-foreground", "bg-accent", "text-accent-foreground", "bg-destructive", "bg-background", "text-background", "border-input"],
|
|
114
|
+
"rationale": "shadcn compat alias 不聯動 DS dark mode。改用 direct token(--surface-raised / --fg-muted / --error 等)",
|
|
115
|
+
"rationale_path": "CLAUDE.md `# 失敗記憶索引` shadcn compat alias 回流"
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"primitive_color_as_utility": {
|
|
119
|
+
"block": {
|
|
120
|
+
"primitive_class": ["bg-neutral-1", "bg-neutral-2", "text-blue-6", "text-red-7", "border-blue-3"],
|
|
121
|
+
"rationale": "primitive 色名作 utility = 越過 semantic 層。用 semantic utility(bg-surface / text-fg-secondary 等)或 var() bracket(bg-[var(--color-blue-6)])"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|