ksk-design-system 1.48.2 → 1.49.0

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