ksk-design-system 1.48.3 → 1.49.1

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.
Files changed (57) hide show
  1. package/AGENTS.md +183 -11
  2. package/CLAUDE.md +187 -22
  3. package/DESIGN.md +106 -15
  4. package/MIGRATION.md +34 -0
  5. package/PUBLISHING.md +95 -28
  6. package/README.md +8 -2
  7. package/RELEASE.md +47 -8
  8. package/UPDATING.md +59 -1
  9. package/bin/check-duplicates.js +1 -0
  10. package/contracts/components.json +29 -15
  11. package/contracts/composition.json +5 -1
  12. package/contracts/rules.json +79 -14
  13. package/contracts/screen-patterns.json +5 -5
  14. package/contracts/token-hex-cache.json +16 -97
  15. package/dist/class-names.js +1 -1
  16. package/dist/index.js +2002 -1877
  17. package/dist/native/ui.js +481 -431
  18. package/dist/{native-BYLnbCN-.js → native-VkkXnB0e.js} +133 -260
  19. package/dist/native.js +1 -1
  20. package/dist/{server-variants-DF8guEvD.js → server-variants-usol4GK5.js} +3 -3
  21. package/dist/types/components/patterns/admin/data-table.d.ts +19 -8
  22. package/dist/types/components/patterns/bottom-sheet-frame.d.ts +5 -2
  23. package/dist/types/components/patterns/keyboard-aware-sheet-footer.d.ts +5 -2
  24. package/dist/types/components/patterns/mobile-app-header.d.ts +10 -2
  25. package/dist/types/components/patterns/sheet-surface.d.ts +4 -0
  26. package/dist/types/components/patterns/shells/admin-shell.d.ts +31 -0
  27. package/dist/types/components/patterns/side-drawer-frame.d.ts +5 -2
  28. package/dist/types/components/ui/alert-dialog.d.ts +1 -1
  29. package/dist/types/components/ui/icon-badge.d.ts +1 -1
  30. package/dist/types/components/ui/pill-toggle.d.ts +30 -3
  31. package/dist/types/components/ui/popover.d.ts +1 -1
  32. package/dist/types/components/ui/progress-ring.d.ts +10 -2
  33. package/dist/types/components/ui/progress.d.ts +1 -1
  34. package/dist/types/components/ui/sheet.d.ts +1 -1
  35. package/dist/types/components/ui/slider.d.ts +15 -1
  36. package/dist/types/index.d.ts +1 -1
  37. package/dist/types/lib/layer-coordination.d.ts +4 -0
  38. package/dist/types/lib/server-variants/button-variants.d.ts +1 -1
  39. package/dist/types/lib/utils.d.ts +26 -0
  40. package/dist/types/native/components/BottomSheetFrame.d.ts +3 -1
  41. package/dist/types/native/components/CardHeader.d.ts +13 -0
  42. package/dist/types/native/components/KeyboardAwareSheetFooter.d.ts +3 -1
  43. package/dist/types/native/components/index.d.ts +2 -1
  44. package/dist/types/tokens/native/scales.d.ts +0 -1
  45. package/dist/types/tokens/native/themes.d.ts +78 -204
  46. package/eslint/icon-button-aria-label.js +101 -0
  47. package/package.json +17 -4
  48. package/src/components/COMPONENT_LOOKUP.md +29 -27
  49. package/src/native/COMPONENT_LOOKUP.md +2 -1
  50. package/src/preset.css +96 -6
  51. package/src/styles/glass.css +5 -1
  52. package/src/styles/motion.css +86 -0
  53. package/src/styles/semantic.css +18 -33
  54. package/src/styles/source-safelist.css +1033 -0
  55. package/templates/AGENTS.md +2 -0
  56. package/templates/CLAUDE.md +2 -0
  57. package/tokens.json +27 -49
package/AGENTS.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # KSK Design System — 設計ルールブック(Codex向け)
2
2
 
3
+ ## CLAUDE.md / AGENTS.md の編集ルール
4
+
5
+ <!-- docs-sync-ignore -->
6
+ このファイルと `CLAUDE.md` は Claude Code 用 / Codex 用の対になる作業手順書で、
7
+ 共通で守るべき内容(実装前セルフチェック・セッション開始時に読み込むファイル・
8
+ ローカル二重実装ゲート・このDSについて・最大の特徴・技術スタック・AIモデルの
9
+ 使い分け方針・ドキュメント構成・ディレクトリ構成・カラートークン体系・
10
+ クイックスタート・コンポーネント追加時のチェックリスト)は**両ファイルで内容を
11
+ 同期させる**こと。
12
+
13
+ - 見出し名・本文は基本的に同一にする(ツール名など明確にツール固有の1行だけ
14
+ <!-- docs-sync-ignore --> マーカー(単独行、次の1行を対象から除外)で除外する)
15
+ - Codex 固有の付録(AGENTS.md 末尾の Codex PR Review Guidelines)のような
16
+ 完全にツール固有のブロックは BEGIN/END マーカーコメント(例:
17
+ 末尾が `codex-pr-review-guidelines` のマーカー)で囲み同期対象から除外する
18
+ - 片方だけ編集したら **`node scripts/check-agents-docs-sync.mjs`**(`npm run check` に
19
+ 組み込み済み)を実行し、乖離が無いことを確認する
20
+ - `templates/CLAUDE.md` / `templates/AGENTS.md`(postinstall で配布するテンプレート)も
21
+ 同じ仕組みで同期検査の対象
22
+
23
+ ## 実装前セルフチェック(AI必読・最優先)
24
+
25
+ UI を書く前に必ず確認すること:
26
+
27
+ - [ ] 画面の骨格は `contracts/screen-patterns.json` の decisionTree で選んだか
28
+ - [ ] 既存コンポーネントを `src/components/COMPONENT_LOOKUP.md` で確認したか(手書き・再定義は禁止)
29
+ - [ ] 色は semantic token(`var(--Surface-*)` / `var(--Brand-Primary)` 等)か。Tailwind標準色・生 `#hex` は禁止
30
+ - [ ] `border` は色を併記したか(`border-[var(--Border-Low-Emphasis)]` 等)。Tailwind v4 では無色 border は currentColor になり、消費側の濃色テキストで黒ずむ(preset.css の base layer が保険だが明示が原則)
31
+ - [ ] **文脈非依存**か(テキスト要素に `text-[var(--Text-*)]`、サーフェス/オーバーレイに `bg-[var(--Surface-*)]` を明示)。親の継承や currentColor に頼ると消費側の色文脈で崩れる。Storybook ツールバーの **Hostile ctx** を loud にして、文字/アイコンがマゼンタ化・背景が透けないか確認する
32
+ - [ ] typography は `typo-*` クラスか(`font-bold` 等の直書きは禁止)
33
+ - [ ] アニメーションは `duration-[var(--Motion-Duration-*)]` / `ease-[var(--Motion-Easing-*)]` か(`duration-200` や生 `cubic-bezier` の直書きは禁止。トークン参照でないと `prefers-reduced-motion` の一括制御から漏れる)
34
+ - [ ] 重なり順は `z-[var(--Z-*)]` か(`z-50` 一律だと Portal のマウント順で勝敗が決まる。`z-10` / `z-20` のコンポーネント内部の重なりは対象外。順序は DESIGN.md の Layering 節)
35
+ - [ ] アイコンは `iconsax-reactjs` か(`lucide-react` / `heroicons` は使わない)
36
+ - [ ] 生タグ(`<button>` / `<input>` / `<a href>`)でなく DS コンポーネントを使ったか
37
+ - [ ] CSS でベンダープレフィックス併記する場合、**`-webkit-` を先・標準形を後**に書いたか(消費側の minifier が同一プロパティとして dedupe し後勝ちのみ残すため。逆順だと Firefox で静かに無効化。`node scripts/check-prefix-order.mjs` が CI で検出)
38
+ - [ ] flex 行(flex-col でない flex)で shrink-0 の兄弟と可変テキストを並べるとき、テキスト側に `flex-1`(+ 必要なら `min-w-[...]` 下限)を付けたか(`min-w-0` だけだと 1 文字ずつ折り返すまで潰れる。issue #293。`node scripts/check-flex-shrink.mjs` が CI で検出、例外は `ksk-lint-ignore KFX001 -- 理由`)
39
+ - [ ] クラス名は**完全な文字列**で書いたか(`` `bg-${color}` `` のような動的合成は静的抽出できず消費側で CSS が生成されない。分岐は三項演算子か cva variant で。`scripts/generate-source-safelist.mjs` が検出)
40
+ - [ ] `.tsx` 編集後に `bash scripts/lint-scratch.sh`、コンポーネント増減時は `npm run check` を実行したか
41
+ - [ ] `FormField` を import する前にどちらか確認したか(react-hook-form の Controller と統合するなら `RhfFormField`=`ui/form` の `FormField` を index.ts で別名 export したもの。単純な label+error 表示は `patterns/form-field` の `FormField`。迷ったら後者)
42
+
43
+ ---
44
+
3
45
  ## このDSについて
4
46
 
5
47
  **KSK Design System** は、フリーランスデザイナー / エンジニア / PdM が **複数クライアント案件を1つのDSで高速に回す** ために設計された統合デザインシステムです。
@@ -38,6 +80,8 @@ UI コンポーネント・画面の生成/修正・レビューの前には、
38
80
 
39
81
  コンポーネントを新規作成する前に `COMPONENT_LOOKUP.md` で同等品がないか確認すること。
40
82
 
83
+ `FormField` は同名で2種類ある: react-hook-form の Controller と統合するなら `RhfFormField`(`ui/form` の `FormField` を index.ts で別名 export したもの)、単純な label+error 表示なら `FormField`(`patterns/form-field`)。迷ったら後者を使う。
84
+
41
85
  ### ローカル二重実装ゲート
42
86
 
43
87
  DS に無いと思っても consumer 側に別台帳を作らないこと。最初に `contracts/components.json` と
@@ -67,13 +111,49 @@ node scripts/check-prefix-order.mjs
67
111
  minifier が同一プロパティとして dedupe し後勝ちのみ残すため、逆順だと
68
112
  標準形が消えて Firefox で静かに無効化される)。
69
113
 
114
+ **新しい Tailwind クラスを使った後は必ず実行:**
115
+
116
+ ```bash
117
+ npm run generate:safelist
118
+ ```
119
+
120
+ DS 内部でしか出現しないクラスを消費側で確実に生成させるための safelist
121
+ (`src/styles/source-safelist.css`・自動生成)を更新する。未更新は
122
+ `npm run check` が検出する。クラス名は必ず完全な文字列で書くこと
123
+ (`` `bg-${color}` `` のような動的合成は静的抽出できず、同スクリプトがエラーにする)。
124
+
70
125
  **コンポーネントを追加・削除した後は必ず実行:**
71
126
 
72
127
  ```bash
73
128
  bash scripts/check-drift.sh
74
- node scripts/generate-component-lookup.mjs
129
+ npm run generate:lookup
130
+ ```
131
+
132
+ **play 関数のあるコンポーネントを触った後は必ず実行:**
133
+
134
+ ```bash
135
+ npm run test:interaction
136
+ ```
137
+
138
+ 対象は Button / Dialog / AlertDialog / Sheet / Select / DropdownMenu /
139
+ Combobox / Tabs / Form / Toast。Storybook の play 関数を playwright chromium で
140
+ ヘッドレス実行する(設定は `vitest.storybook.config.ts`、対象は
141
+ `tags: ["interaction"]` を付けたストーリーのみ)。初回のみ
142
+ `npx playwright install chromium` が必要なため `npm run check` には含まれない。
143
+ CI では常時実行される。
144
+
145
+ **UI コンポーネントを追加・修正した後は `npm run test:a11y` も実行:**
146
+
147
+ ```bash
148
+ npm run test:a11y
75
149
  ```
76
150
 
151
+ axe-core による a11y 機械検証(issue #261)。`@storybook/addon-a11y` の
152
+ afterEach フックが全ストーリー(tags フィルタなし)に対して axe-core を
153
+ 実行する(設定は `vitest.a11y.config.ts`)。color-contrast ルールも有効
154
+ (AA 未達トークンの darken と opacity 減衰の廃止により全ストーリー通過。
155
+ トークンペアの正本チェックは `scripts/check-contrast.mjs`)。CI では常時実行される。
156
+
77
157
  エラーが出た場合は修正してから次に進むこと。
78
158
 
79
159
  ---
@@ -97,41 +177,55 @@ Brand色を差し替え(10行)→ Primitive Layer → Semantic Layer → Bri
97
177
 
98
178
  ## 技術スタック
99
179
 
100
- - React 19 + TypeScript / Vite / **Tailwind CSS v4**(`@import "tailwindcss"` 構文)
180
+ - React 19 + TypeScript / Vite / **Tailwind CSS v4**(`@import "tailwindcss"` 構文。`@tailwind base` 等の v3 構文は使わない)
101
181
  - shadcn/ui(Radix UI ベース) / CVA(バリアント管理)
102
- - **iconsax-reactjs**(アイコン。lucide-react や heroicons は使わない)
103
- - Storybook(ドキュメント)
104
-
105
- > **注意**: Tailwind CSS は v4 です。`@tailwind base` 等の v3 構文は使わないこと。
182
+ - **iconsax-reactjs**(アイコン。`lucide-react` / `heroicons` は使わない) / Storybook(ドキュメント)
106
183
 
107
184
  ---
108
185
 
109
186
  ## AIモデルの使い分け方針
110
187
 
188
+ (同一モデルで実装と検証を兼ねない — 同じバイアスを共有し独立検証にならない)
189
+
190
+ ### Fable 5 が使えるとき
191
+
111
192
  | モデル | 用途 |
112
193
  |--------|------|
113
194
  | `claude-fable-5` | 最難関の設計・長時間エージェント作業のみ(高コストのため温存) |
114
195
  | `claude-opus-4-8` | 通常のUI実装・レビュー・リファクタの既定 |
115
196
 
116
- **検証ループを使う場合:** 実装 = Fable 5 / 検証 = Opus 4.8 のように実装者と検証者で別モデルを使う(同一モデルは同じバイアスを共有し独立検証にならない)。
197
+ **検証ループ:** 実装 = Fable 5 / 検証 = Opus 4.8
117
198
 
118
199
  **Fable 5 使用時の注意:**
119
200
  - thinking は常時オン(パラメータ省略でデフォルトに任せる)
120
201
  - refusal 時は `fallbacks` で Opus 4.8 に自動フォールバック
121
202
  - 30日データ保持が必須
122
203
 
204
+ ### Fable 5 が使えないとき(アクセス終了・休止期間)
205
+
206
+ | モデル | 用途 |
207
+ |--------|------|
208
+ | `claude-opus-4-8` | 設計・UI実装・レビュー・リファクタの既定 |
209
+ | `claude-sonnet-5` | 機械的な一括修正・定型作業(トークン節約) |
210
+
211
+ **検証ループ:** 実装 = Opus 4.8 / 検証 = Sonnet 5
212
+
123
213
  ---
124
214
 
125
215
  ## ドキュメント構成
126
216
 
127
217
  | ファイル | 内容 |
128
218
  |---------|------|
129
- | **AGENTS.md**(本ファイル) | 概要・技術スタック・コマンド・クイックスタート |
219
+ <!-- docs-sync-ignore -->
220
+ | **CLAUDE.md** | 同上(Claude Code用) |
221
+ <!-- docs-sync-ignore -->
222
+ | **AGENTS.md**(本ファイル) | 概要・技術スタック・コマンド・クイックスタート(Codex用。Codex PR Review Guidelines を追記) |
130
223
  | **contracts/components.json** | 全コンポーネントの構造化定義(バリアント・アクセシビリティ要件。総数は meta.counts が正本) |
131
224
  | **contracts/rules.json** | 禁止パターン・AIアンチパターン・アクセシビリティ要件(正本: rules.json) |
132
225
  | **contracts/design-context.json** | `DESIGN.md` の役割・正本ファイル・外部 DESIGN.md 参照方針 |
133
226
  | **tokens.json** | カラー・スペーシング・シャドウトークンの機械可読定義 |
134
- | **src/components/COMPONENT_LOOKUP.md** | 全コンポーネントのバリアント・インポートパス(自動生成) |
227
+ | **contracts/token-hex-cache.json** | semantic トークンのデフォルトテーマ解決済み hex(テーマ依存キーは meta.themeDependentKeys 参照・自動生成) |
228
+ | **src/components/COMPONENT_LOOKUP.md** | 全コンポーネントのバリアント・インポートパス一覧(自動生成) |
135
229
  | **DESIGN.md** | AI エージェント向け視覚言語サマリ(トークン+意図・voice・motion) |
136
230
  | **contracts/screen-patterns.json** | 画面実装前にどのシェル/パターンを使うかを決める decisionTree・crudMatrix |
137
231
  | **contracts/composition.json** | 選んだパターン内部の並べ方(骨格構造・余白リズム・カード階層・テキスト階層・CTA優先度) |
@@ -153,7 +247,9 @@ src/
153
247
  ├── styles/
154
248
  │ ├── primitive.css # Layer 1: 原色パレット
155
249
  │ ├── semantic.css # Layer 2: 用途別トークン
156
- │ └── typography.css # typo-* ユーティリティ
250
+ │ ├── typography.css # typo-* ユーティリティ
251
+ │ ├── motion.css # duration / easing トークン(--Motion-*)
252
+ │ └── source-safelist.css # @source safelist(自動生成・手で編集しない / issue #258)
157
253
  ├── themes/ # default / orange / green / violet / blue
158
254
  ├── preset.css # 外部プロジェクト向けプリセット
159
255
  └── index.ts # Public API(全コンポーネント)
@@ -161,6 +257,72 @@ src/
161
257
 
162
258
  ---
163
259
 
260
+ ## コマンド
261
+
262
+ ```bash
263
+ # 開発サーバー(Storybook)
264
+ npm run storybook
265
+
266
+ # ビルド
267
+ npm run build-storybook
268
+
269
+ # スクラッチ検出(実装後に必ず実行)
270
+ bash scripts/lint-scratch.sh
271
+
272
+ # ドリフト検出(コンポーネント追加後に実行)
273
+ bash scripts/check-drift.sh
274
+
275
+ # COMPONENT_LOOKUP.md 再生成(コンポーネント追加後に実行)
276
+ npm run generate:lookup
277
+
278
+ # DESIGN.md contract 検査
279
+ npm run lint:design
280
+
281
+ # @source safelist 再生成(新しい Tailwind クラスを使ったら実行)
282
+ npm run generate:safelist
283
+
284
+ # 全チェック(tsc + lint + drift + lookup + safelist 一括)
285
+ npm run check
286
+
287
+ # interaction テスト(Storybook play 関数を playwright chromium で実行)
288
+ npm run test:interaction
289
+
290
+ # a11y 機械検証(axe-core。全ストーリー対象。issue #261)
291
+ npm run test:a11y
292
+ ```
293
+
294
+ **interaction テストについて(issue #256):**
295
+
296
+ - 実体は Storybook の play 関数。`@storybook/addon-vitest` + vitest browser mode(playwright chromium)で
297
+ ヘッドレス実行する。設定は `vitest.storybook.config.ts`。
298
+ - 対象は `tags: ["interaction"]` を付けたストーリーだけ(全ストーリーのスモークはしない)。
299
+ - 初回のみ `npx playwright install chromium` が必要。**この前提があるため `npm run check` /
300
+ `check:agent` には含めていない**(CI と、下記に該当する変更をしたときに手で回す)。
301
+ - 押下でレイアウトが沈む・入場アニメーション中に操作不能・フォーカストラップ崩れ、といった
302
+ v1.48.x で連続した種類の不具合をここで落とす。
303
+ - **play 関数のあるコンポーネント(Button / Dialog / AlertDialog / Sheet / Select /
304
+ DropdownMenu / Combobox / Tabs / Form / Toast)を触ったら `npm run test:interaction` を回すこと。**
305
+ - ビジュアル回帰(スクリーンショット差分)は未導入。`.claude/skills/audit-pages/SKILL.md` による
306
+ 手動の視覚監査が現状の代替。
307
+
308
+ **a11y 機械検証について(issue #261):**
309
+
310
+ - `@storybook/addon-a11y` の afterEach フック(axe-core)が全ストーリー(tags フィルタなし)に
311
+ 対して実行される。設定は `vitest.a11y.config.ts`、実行は `npm run test:a11y`。CI では常時実行。
312
+ - color-contrast ルールも有効(全ストーリー対象)。当初はトークン債務のため無効化していたが、
313
+ AA 未達トークンの darken(Success/Warning-Base・Text-Caution/Warning・Text-Low-Emphasis)と
314
+ opacity 減衰の廃止で解消済み。無効状態デモ等 WCAG 1.4.3 の inactive 例外だけ、ストーリー側で
315
+ 理由コメント付きの rule 除外を許可(`.storybook/preview.ts` 参照)。トークンペアの正本チェックは
316
+ `scripts/check-contrast.mjs`(`npm run check` 経由)。
317
+ - rules.json の `accessibility.requirements` に `machineVerified` / `verifiedBy` を追加済み。
318
+ axe でカバーできない項目(フォーカスリング視認・タッチターゲット実測・エラー表示の
319
+ 色+アイコン+テキスト3点セット等)は今後も目視レビューが必要。
320
+ - icon-only の `<Button size="icon*">` に `aria-label` が無いパターンは
321
+ `eslint/icon-button-aria-label.js`(`ksk-a11y/icon-button-aria-label`)で lint 時に検出する
322
+ (`.stories.tsx` は対象外)。
323
+
324
+ ---
325
+
164
326
  ## カラートークン体系(3層構造)
165
327
 
166
328
  ```
@@ -187,6 +349,16 @@ Layer 3 — Bridge : --primary / --secondary 等 (shadcn/ui 互換
187
349
  Brand に連動しない固定値で、カレンダー予定ドット・カテゴリ chip・グラフ系列など「N 番目のカテゴリ」を色で区別する用途専用。
188
350
  文字には必ず `-Bold` を使う(base は明色相だと白背景でコントラスト不足)。詳細・WCAG/CVD 注記は `src/styles/categorical.css`。
189
351
 
352
+ **モーション(`src/styles/motion.css`):**
353
+ `duration-[var(--Motion-Duration-{Fast,Base,Slow,Slower})]` /
354
+ `ease-[var(--Motion-Easing-{Standard,Emphasized,Decelerate,Bounce})]`。
355
+ 生の `duration-200` / `cubic-bezier(...)` は禁止(`prefers-reduced-motion` の一括制御から漏れる)。
356
+
357
+ **重なり順(`src/preset.css`):**
358
+ `z-[var(--Z-{Sticky,Nav,Overlay,Modal,Popover,Toast,Tooltip,SkipLink})]`。
359
+ `z-50` 一律だと Portal のマウント順で勝敗が決まる。`z-10` / `z-20` のコンポーネント内部の重なりは対象外。
360
+ いずれも詳細は DESIGN.md の Motion / Layering 節。
361
+
190
362
  ---
191
363
 
192
364
  ## クイックスタート(新規クライアント案件)
@@ -227,7 +399,7 @@ import { Button, Card, Input, FormField } from "ksk-design-system"
227
399
  - [ ] `contracts/components.json` の `meta.counts` を更新
228
400
  - [ ] `bash scripts/check-drift.sh` を実行して乖離がないことを確認
229
401
  - [ ] Storybook のストーリーファイル(`.stories.tsx`)を作成
230
- - [ ] `node scripts/generate-component-lookup.mjs` を実行して COMPONENT_LOOKUP.md を更新
402
+ - [ ] `npm run generate:lookup` を実行して COMPONENT_LOOKUP.md を更新
231
403
 
232
404
  <!-- BEGIN:codex-pr-review-guidelines -->
233
405
  ## Codex PR Review Guidelines
package/CLAUDE.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # KSK Design System — 設計ルールブック
2
2
 
3
+ ## CLAUDE.md / AGENTS.md の編集ルール
4
+
5
+ <!-- docs-sync-ignore -->
6
+ このファイルと `AGENTS.md` は Claude Code 用 / Codex 用の対になる作業手順書で、
7
+ 共通で守るべき内容(実装前セルフチェック・セッション開始時に読み込むファイル・
8
+ ローカル二重実装ゲート・このDSについて・最大の特徴・技術スタック・AIモデルの
9
+ 使い分け方針・ドキュメント構成・ディレクトリ構成・カラートークン体系・
10
+ クイックスタート・コンポーネント追加時のチェックリスト)は**両ファイルで内容を
11
+ 同期させる**こと。
12
+
13
+ - 見出し名・本文は基本的に同一にする(ツール名など明確にツール固有の1行だけ
14
+ <!-- docs-sync-ignore --> マーカー(単独行、次の1行を対象から除外)で除外する)
15
+ - Codex 固有の付録(AGENTS.md 末尾の Codex PR Review Guidelines)のような
16
+ 完全にツール固有のブロックは BEGIN/END マーカーコメント(例:
17
+ 末尾が `codex-pr-review-guidelines` のマーカー)で囲み同期対象から除外する
18
+ - 片方だけ編集したら **`node scripts/check-agents-docs-sync.mjs`**(`npm run check` に
19
+ 組み込み済み)を実行し、乖離が無いことを確認する
20
+ - `templates/CLAUDE.md` / `templates/AGENTS.md`(postinstall で配布するテンプレート)も
21
+ 同じ仕組みで同期検査の対象
22
+
3
23
  ## 実装前セルフチェック(AI必読・最優先)
4
24
 
5
25
  UI を書く前に必ず確認すること:
@@ -10,10 +30,121 @@ UI を書く前に必ず確認すること:
10
30
  - [ ] `border` は色を併記したか(`border-[var(--Border-Low-Emphasis)]` 等)。Tailwind v4 では無色 border は currentColor になり、消費側の濃色テキストで黒ずむ(preset.css の base layer が保険だが明示が原則)
11
31
  - [ ] **文脈非依存**か(テキスト要素に `text-[var(--Text-*)]`、サーフェス/オーバーレイに `bg-[var(--Surface-*)]` を明示)。親の継承や currentColor に頼ると消費側の色文脈で崩れる。Storybook ツールバーの **Hostile ctx** を loud にして、文字/アイコンがマゼンタ化・背景が透けないか確認する
12
32
  - [ ] typography は `typo-*` クラスか(`font-bold` 等の直書きは禁止)
33
+ - [ ] アニメーションは `duration-[var(--Motion-Duration-*)]` / `ease-[var(--Motion-Easing-*)]` か(`duration-200` や生 `cubic-bezier` の直書きは禁止。トークン参照でないと `prefers-reduced-motion` の一括制御から漏れる)
34
+ - [ ] 重なり順は `z-[var(--Z-*)]` か(`z-50` 一律だと Portal のマウント順で勝敗が決まる。`z-10` / `z-20` のコンポーネント内部の重なりは対象外。順序は DESIGN.md の Layering 節)
13
35
  - [ ] アイコンは `iconsax-reactjs` か(`lucide-react` / `heroicons` は使わない)
14
36
  - [ ] 生タグ(`<button>` / `<input>` / `<a href>`)でなく DS コンポーネントを使ったか
15
37
  - [ ] CSS でベンダープレフィックス併記する場合、**`-webkit-` を先・標準形を後**に書いたか(消費側の minifier が同一プロパティとして dedupe し後勝ちのみ残すため。逆順だと Firefox で静かに無効化。`node scripts/check-prefix-order.mjs` が CI で検出)
38
+ - [ ] flex 行(flex-col でない flex)で shrink-0 の兄弟と可変テキストを並べるとき、テキスト側に `flex-1`(+ 必要なら `min-w-[...]` 下限)を付けたか(`min-w-0` だけだと 1 文字ずつ折り返すまで潰れる。issue #293。`node scripts/check-flex-shrink.mjs` が CI で検出、例外は `ksk-lint-ignore KFX001 -- 理由`)
39
+ - [ ] クラス名は**完全な文字列**で書いたか(`` `bg-${color}` `` のような動的合成は静的抽出できず消費側で CSS が生成されない。分岐は三項演算子か cva variant で。`scripts/generate-source-safelist.mjs` が検出)
16
40
  - [ ] `.tsx` 編集後に `bash scripts/lint-scratch.sh`、コンポーネント増減時は `npm run check` を実行したか
41
+ - [ ] `FormField` を import する前にどちらか確認したか(react-hook-form の Controller と統合するなら `RhfFormField`=`ui/form` の `FormField` を index.ts で別名 export したもの。単純な label+error 表示は `patterns/form-field` の `FormField`。迷ったら後者)
42
+
43
+ ---
44
+
45
+ ## 必須: セッション開始時に読み込むファイル
46
+
47
+ コードを書く前に、以下を必ず読み込むこと:
48
+
49
+ ```
50
+ .claude/skills/ksk-design-system/SKILL.md # 判断Skill: 実装・レビューの判断基準(正本への索引)
51
+ contracts/rules.json # 禁止パターン・AIアンチパターン・a11y要件(件数・内容は rules.json が正本)
52
+ contracts/components.json # 全コンポーネントの定義・バリアント・ルール
53
+ contracts/design-context.json # DESIGN.md と正本ファイルの関係・AI向け検査方針
54
+ tokens.json # カラー・スペーシング・シャドウトークン
55
+ contracts/token-hex-cache.json # semantic トークンのデフォルトテーマ解決済み hex(テーマ依存キーは meta.themeDependentKeys 参照・自動生成)
56
+ src/components/COMPONENT_LOOKUP.md # バリアント・インポートパス一覧(自動生成)
57
+ contracts/screen-patterns.json # 画面実装前にどのシェル/パターンを使うかの decisionTree・crudMatrix
58
+ contracts/composition.json # 選んだパターン内部の並べ方(骨格構造・余白リズム・カード階層・テキスト階層・CTA優先度)
59
+ ```
60
+
61
+ 画面(ページ/ダイアログ等)を実装・修正する場合は、まず `contracts/screen-patterns.json` の
62
+ decisionTree でシェル/パターンを選び、`contracts/composition.json` で内部の並べ方を確認すること。
63
+
64
+ UI コンポーネント・画面の生成/修正・レビューの前には、必ず
65
+ `.claude/skills/ksk-design-system/SKILL.md` を読み、その判断基準に従うこと
66
+ (トークン選定・コンポーネント選択・レビュー優先順位・例外運用。迷ったら同ディレクトリの `references/` を参照)。
67
+
68
+ **必ず `contracts/rules.json` の `prohibited` と `aiPatterns` を確認してから実装すること。**
69
+ 特に `aiPatterns` は AI が典型的に犯すパターン集 — 自分が生成しようとしているコードと照合すること。
70
+
71
+ コンポーネントを新規作成する前に `COMPONENT_LOOKUP.md` で同等品がないか確認すること。
72
+
73
+ `FormField` は同名で2種類ある: react-hook-form の Controller と統合するなら `RhfFormField`(`ui/form` の `FormField` を index.ts で別名 export したもの)、単純な label+error 表示なら `FormField`(`patterns/form-field`)。迷ったら後者を使う。
74
+
75
+ ### ローカル二重実装ゲート
76
+
77
+ DS に無いと思っても consumer 側に別台帳を作らないこと。最初に `contracts/components.json` と
78
+ `COMPONENT_LOOKUP.md` を検索し、consumer では `npx ksk-ds check-duplicates ./src --strict` を実行する。
79
+ それでも不足する場合は DS 側に issue を登録する。やむを得ない一時実装には、削除条件と issue を
80
+ `// ksk-ds-local-fallback: DS に X が追加されたら削除 (issue #123)` の形式で残すこと。
81
+
82
+ Storybook 全体を横断で視覚監査する(定期監査・リリース前総点検)場合は `.claude/skills/audit-pages/SKILL.md` の手順に従うこと。
83
+
84
+ ---
85
+
86
+ ## 必須: ファイル編集後に実行するコマンド
87
+
88
+ **.tsx ファイルを作成・編集した後は必ず実行:**
89
+
90
+ ```bash
91
+ bash scripts/lint-scratch.sh
92
+ ```
93
+
94
+ **.css を編集した後は必ず実行:**
95
+
96
+ ```bash
97
+ node scripts/check-prefix-order.mjs
98
+ ```
99
+
100
+ ベンダープレフィックスは **`-webkit-` を先・標準形を後** に書く(消費側の
101
+ minifier が同一プロパティとして dedupe し後勝ちのみ残すため、逆順だと
102
+ 標準形が消えて Firefox で静かに無効化される)。
103
+
104
+ **新しい Tailwind クラスを使った後は必ず実行:**
105
+
106
+ ```bash
107
+ npm run generate:safelist
108
+ ```
109
+
110
+ DS 内部でしか出現しないクラスを消費側で確実に生成させるための safelist
111
+ (`src/styles/source-safelist.css`・自動生成)を更新する。未更新は
112
+ `npm run check` が検出する。クラス名は必ず完全な文字列で書くこと
113
+ (`` `bg-${color}` `` のような動的合成は静的抽出できず、同スクリプトがエラーにする)。
114
+
115
+ **コンポーネントを追加・削除した後は必ず実行:**
116
+
117
+ ```bash
118
+ bash scripts/check-drift.sh
119
+ npm run generate:lookup
120
+ ```
121
+
122
+ **play 関数のあるコンポーネントを触った後は必ず実行:**
123
+
124
+ ```bash
125
+ npm run test:interaction
126
+ ```
127
+
128
+ 対象は Button / Dialog / AlertDialog / Sheet / Select / DropdownMenu /
129
+ Combobox / Tabs / Form / Toast。Storybook の play 関数を playwright chromium で
130
+ ヘッドレス実行する(設定は `vitest.storybook.config.ts`、対象は
131
+ `tags: ["interaction"]` を付けたストーリーのみ)。初回のみ
132
+ `npx playwright install chromium` が必要なため `npm run check` には含まれない。
133
+ CI では常時実行される。
134
+
135
+ **UI コンポーネントを追加・修正した後は `npm run test:a11y` も実行:**
136
+
137
+ ```bash
138
+ npm run test:a11y
139
+ ```
140
+
141
+ axe-core による a11y 機械検証(issue #261)。`@storybook/addon-a11y` の
142
+ afterEach フックが全ストーリー(tags フィルタなし)に対して axe-core を
143
+ 実行する(設定は `vitest.a11y.config.ts`)。color-contrast ルールも有効
144
+ (AA 未達トークンの darken と opacity 減衰の廃止により全ストーリー通過。
145
+ トークンペアの正本チェックは `scripts/check-contrast.mjs`)。CI では常時実行される。
146
+
147
+ エラーが出た場合は修正してから次に進むこと。
17
148
 
18
149
  ---
19
150
 
@@ -85,8 +216,10 @@ Brand色を差し替え(10行)→ Primitive Layer → Semantic Layer → Bri
85
216
 
86
217
  | ファイル | 内容 |
87
218
  |---------|------|
219
+ <!-- docs-sync-ignore -->
88
220
  | **CLAUDE.md**(本ファイル) | 概要・技術スタック・コマンド・クイックスタート(Claude Code用) |
89
- | **AGENTS.md** | 同上(Codex用。セッション開始時の読み込み指示・編集後コマンドを明記) |
221
+ <!-- docs-sync-ignore -->
222
+ | **AGENTS.md** | 同上(Codex用。Codex PR Review Guidelines を追記) |
90
223
  | **contracts/components.json** | 全コンポーネントの構造化定義(バリアント・アクセシビリティ要件。総数は meta.counts が正本) |
91
224
  | **contracts/rules.json** | 禁止パターン・AIアンチパターン・アクセシビリティ要件(正本: rules.json) |
92
225
  | **contracts/design-context.json** | `DESIGN.md` の役割・正本ファイル・外部 DESIGN.md 参照方針 |
@@ -97,25 +230,6 @@ Brand色を差し替え(10行)→ Primitive Layer → Semantic Layer → Bri
97
230
  | **contracts/screen-patterns.json** | 画面実装前にどのシェル/パターンを使うかを決める decisionTree・crudMatrix |
98
231
  | **contracts/composition.json** | 選んだパターン内部の並べ方(骨格構造・余白リズム・カード階層・テキスト階層・CTA優先度) |
99
232
 
100
- **セッション開始時 / コードを書く前に必ず読む:**
101
- 1. `contracts/rules.json` の `prohibited` と `aiPatterns`(AIが典型的に犯すパターン集)を確認
102
- 2. `contracts/components.json` でコンポーネント定義・バリアントを確認
103
- 3. `contracts/design-context.json` で `DESIGN.md` と正本ファイルの関係を確認
104
- 4. `src/components/COMPONENT_LOOKUP.md` で既存コンポーネントを確認(手書き・再定義の防止)
105
- 5. `tokens.json` でカラー・余白・影・タイポのトークンを確認
106
- 6. 画面(ページ/ダイアログ等)を実装する場合は `contracts/screen-patterns.json` の decisionTree でシェル/パターンを選び、`contracts/composition.json` で内部の並べ方を確認
107
-
108
- ### ローカル二重実装ゲート
109
-
110
- DS に無いと思っても consumer 側に別台帳を作らないこと。最初に `contracts/components.json` と
111
- `COMPONENT_LOOKUP.md` を検索し、consumer では `npx ksk-ds check-duplicates ./src --strict` を実行する。
112
- それでも不足する場合は DS 側に issue を登録する。やむを得ない一時実装には、削除条件と issue を
113
- `// ksk-ds-local-fallback: DS に X が追加されたら削除 (issue #123)` の形式で残すこと。
114
-
115
- **`.tsx` を編集したら `bash scripts/lint-scratch.sh`、コンポーネント増減時は `npm run check` を実行すること。**
116
-
117
- Storybook 全体を横断で視覚監査する(定期監査・リリース前総点検・「全ページ確認して」)場合は `.claude/skills/audit-pages/SKILL.md` を使う。
118
-
119
233
  ---
120
234
 
121
235
  ## ディレクトリ構成
@@ -133,7 +247,9 @@ src/
133
247
  ├── styles/
134
248
  │ ├── primitive.css # Layer 1: 原色パレット
135
249
  │ ├── semantic.css # Layer 2: 用途別トークン
136
- │ └── typography.css # typo-* ユーティリティ
250
+ │ ├── typography.css # typo-* ユーティリティ
251
+ │ ├── motion.css # duration / easing トークン(--Motion-*)
252
+ │ └── source-safelist.css # @source safelist(自動生成・手で編集しない / issue #258)
137
253
  ├── themes/ # default / orange / green / violet / blue
138
254
  ├── preset.css # 外部プロジェクト向けプリセット
139
255
  └── index.ts # Public API(全コンポーネント)
@@ -162,10 +278,49 @@ npm run generate:lookup
162
278
  # DESIGN.md contract 検査
163
279
  npm run lint:design
164
280
 
165
- # 全チェック(tsc + lint + drift + lookup 一括)
281
+ # @source safelist 再生成(新しい Tailwind クラスを使ったら実行)
282
+ npm run generate:safelist
283
+
284
+ # 全チェック(tsc + lint + drift + lookup + safelist 一括)
166
285
  npm run check
286
+
287
+ # interaction テスト(Storybook play 関数を playwright chromium で実行)
288
+ npm run test:interaction
289
+
290
+ # a11y 機械検証(axe-core。全ストーリー対象。issue #261)
291
+ npm run test:a11y
167
292
  ```
168
293
 
294
+ **interaction テストについて(issue #256):**
295
+
296
+ - 実体は Storybook の play 関数。`@storybook/addon-vitest` + vitest browser mode(playwright chromium)で
297
+ ヘッドレス実行する。設定は `vitest.storybook.config.ts`。
298
+ - 対象は `tags: ["interaction"]` を付けたストーリーだけ(全ストーリーのスモークはしない)。
299
+ - 初回のみ `npx playwright install chromium` が必要。**この前提があるため `npm run check` /
300
+ `check:agent` には含めていない**(CI と、下記に該当する変更をしたときに手で回す)。
301
+ - 押下でレイアウトが沈む・入場アニメーション中に操作不能・フォーカストラップ崩れ、といった
302
+ v1.48.x で連続した種類の不具合をここで落とす。
303
+ - **play 関数のあるコンポーネント(Button / Dialog / AlertDialog / Sheet / Select /
304
+ DropdownMenu / Combobox / Tabs / Form / Toast)を触ったら `npm run test:interaction` を回すこと。**
305
+ - ビジュアル回帰(スクリーンショット差分)は未導入。`.claude/skills/audit-pages/SKILL.md` による
306
+ 手動の視覚監査が現状の代替。
307
+
308
+ **a11y 機械検証について(issue #261):**
309
+
310
+ - `@storybook/addon-a11y` の afterEach フック(axe-core)が全ストーリー(tags フィルタなし)に
311
+ 対して実行される。設定は `vitest.a11y.config.ts`、実行は `npm run test:a11y`。CI では常時実行。
312
+ - color-contrast ルールも有効(全ストーリー対象)。当初はトークン債務のため無効化していたが、
313
+ AA 未達トークンの darken(Success/Warning-Base・Text-Caution/Warning・Text-Low-Emphasis)と
314
+ opacity 減衰の廃止で解消済み。無効状態デモ等 WCAG 1.4.3 の inactive 例外だけ、ストーリー側で
315
+ 理由コメント付きの rule 除外を許可(`.storybook/preview.ts` 参照)。トークンペアの正本チェックは
316
+ `scripts/check-contrast.mjs`(`npm run check` 経由)。
317
+ - rules.json の `accessibility.requirements` に `machineVerified` / `verifiedBy` を追加済み。
318
+ axe でカバーできない項目(フォーカスリング視認・タッチターゲット実測・エラー表示の
319
+ 色+アイコン+テキスト3点セット等)は今後も目視レビューが必要。
320
+ - icon-only の `<Button size="icon*">` に `aria-label` が無いパターンは
321
+ `eslint/icon-button-aria-label.js`(`ksk-a11y/icon-button-aria-label`)で lint 時に検出する
322
+ (`.stories.tsx` は対象外)。
323
+
169
324
  ---
170
325
 
171
326
  ## カラートークン体系(3層構造)
@@ -194,6 +349,16 @@ Layer 3 — Bridge : --primary / --secondary 等 (shadcn/ui 互換
194
349
  Brand に連動しない固定値で、カレンダー予定ドット・カテゴリ chip・グラフ系列など「N 番目のカテゴリ」を色で区別する用途専用。
195
350
  文字には必ず `-Bold` を使う(base は明色相だと白背景でコントラスト不足)。詳細・WCAG/CVD 注記は `src/styles/categorical.css`。
196
351
 
352
+ **モーション(`src/styles/motion.css`):**
353
+ `duration-[var(--Motion-Duration-{Fast,Base,Slow,Slower})]` /
354
+ `ease-[var(--Motion-Easing-{Standard,Emphasized,Decelerate,Bounce})]`。
355
+ 生の `duration-200` / `cubic-bezier(...)` は禁止(`prefers-reduced-motion` の一括制御から漏れる)。
356
+
357
+ **重なり順(`src/preset.css`):**
358
+ `z-[var(--Z-{Sticky,Nav,Overlay,Modal,Popover,Toast,Tooltip,SkipLink})]`。
359
+ `z-50` 一律だと Portal のマウント順で勝敗が決まる。`z-10` / `z-20` のコンポーネント内部の重なりは対象外。
360
+ いずれも詳細は DESIGN.md の Motion / Layering 節。
361
+
197
362
  ---
198
363
 
199
364
  ## クイックスタート(新規クライアント案件)