@cakejp/design-system 0.12.0 → 0.14.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 (49) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/CLAUDE.md +12 -5
  3. package/MIGRATION.md +45 -0
  4. package/UPDATING.md +13 -0
  5. package/bin/check-duplicates.mjs +133 -9
  6. package/bin/exports-parser.mjs +54 -0
  7. package/bin/init.js +3 -0
  8. package/contracts/components.json +504 -209
  9. package/contracts/composition.json +11 -8
  10. package/contracts/rules.json +354 -113
  11. package/contracts/screen-patterns.json +1 -1
  12. package/dist/index.css +1 -1
  13. package/dist/index.js +4285 -3422
  14. package/dist/types/components/ec/admin-shell.d.ts +30 -2
  15. package/dist/types/components/ec/product-detail-sidebar.d.ts +1 -1
  16. package/dist/types/components/foundations/card.d.ts +27 -3
  17. package/dist/types/components/foundations/field.d.ts +26 -3
  18. package/dist/types/components/foundations/input.d.ts +3 -1
  19. package/dist/types/components/foundations/social-icon.d.ts +33 -0
  20. package/dist/types/components/foundations/textarea.d.ts +3 -1
  21. package/dist/types/components/primitives/chat-composer.d.ts +87 -0
  22. package/dist/types/components/primitives/combobox.d.ts +24 -0
  23. package/dist/types/components/primitives/content-carousel.d.ts +7 -1
  24. package/dist/types/components/primitives/date-picker.d.ts +15 -3
  25. package/dist/types/components/primitives/funnel-shell.d.ts +2 -0
  26. package/dist/types/components/primitives/image-input.d.ts +119 -0
  27. package/dist/types/components/primitives/multi-select.d.ts +24 -0
  28. package/dist/types/components/primitives/notification-badge.d.ts +1 -1
  29. package/dist/types/components/primitives/number-input.d.ts +84 -0
  30. package/dist/types/components/primitives/section-header.d.ts +9 -2
  31. package/dist/types/components/primitives/section.d.ts +35 -2
  32. package/dist/types/components/primitives/social-login-button.d.ts +3 -1
  33. package/dist/types/components/primitives/timeline.d.ts +23 -0
  34. package/dist/types/components/primitives/workspace-shell.d.ts +2 -0
  35. package/dist/types/index.d.ts +25 -7
  36. package/dist/types/lib/pagination-range.d.ts +16 -0
  37. package/dist/types/lib/use-value-length.d.ts +31 -0
  38. package/eslint/deprecated.js +44 -0
  39. package/package.json +8 -3
  40. package/scripts/codemod/README.md +14 -0
  41. package/scripts/codemod/template.mjs +62 -0
  42. package/src/components/COMPONENT_LOOKUP.md +166 -0
  43. package/src/preset-standalone.css +16 -0
  44. package/src/preset.css +17 -0
  45. package/src/styles/typography.css +7 -0
  46. package/templates/AGENTS.md +4 -0
  47. package/templates/CLAUDE.md +4 -0
  48. package/tokens.json +933 -87
  49. package/dist/types/components/primitives/quantity-selector.d.ts +0 -50
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "meta": {
3
3
  "name": "Cake.jp Design System — Rules Contracts",
4
- "version": "0.1.0",
4
+ "version": "0.14.0",
5
5
  "description": "禁止パターン・アクセシビリティ要件・ライティングルールの構造化定義。lint-scratch.sh と check-drift.sh で自動検証。"
6
6
  },
7
7
  "prohibited": [
@@ -38,7 +38,14 @@
38
38
  "severity": "warning",
39
39
  "category": "typography",
40
40
  "pattern": "font-bold|font-semibold|font-medium|font-light",
41
- "excludes": [".stories.", "cva", "variants", "components/foundations/", "components/primitives/", "components/ec/"],
41
+ "excludes": [
42
+ ".stories.",
43
+ "cva",
44
+ "variants",
45
+ "components/foundations/",
46
+ "components/primitives/",
47
+ "components/ec/"
48
+ ],
42
49
  "message": "text-sm font-bold 等の個別クラス組み合わせ禁止",
43
50
  "fix": "typo-label-md 等 typo-* クラスを使う"
44
51
  },
@@ -63,7 +70,9 @@
63
70
  "severity": "warning",
64
71
  "category": "typography",
65
72
  "pattern": "text-\\[[0-9]+px\\]|leading-\\[[0-9.]+\\]",
66
- "excludes": [".stories."],
73
+ "excludes": [
74
+ ".stories."
75
+ ],
67
76
  "message": "px直書き・leading直書き禁止",
68
77
  "fix": "typo-body-md 等 typo-* クラスを使う"
69
78
  },
@@ -80,7 +89,12 @@
80
89
  "severity": "warning",
81
90
  "category": "color",
82
91
  "pattern": "text-gray-|text-orange-|text-red-|text-green-|text-blue-|bg-gray-|bg-orange-|bg-red-|bg-green-|bg-blue-",
83
- "excludes": [".stories.", "components/foundations/", "components/primitives/", "components/ec/"],
92
+ "excludes": [
93
+ ".stories.",
94
+ "components/foundations/",
95
+ "components/primitives/",
96
+ "components/ec/"
97
+ ],
84
98
  "message": "Tailwind標準色クラス禁止",
85
99
  "fix": "text-[var(--Text-High-Emphasis)] 等セマンティックトークンを使う"
86
100
  },
@@ -89,7 +103,12 @@
89
103
  "severity": "warning",
90
104
  "category": "color",
91
105
  "pattern": "bg-orange-[0-9]+|text-orange-[0-9]+",
92
- "excludes": [".stories.", "components/foundations/", "components/primitives/", "components/ec/"],
106
+ "excludes": [
107
+ ".stories.",
108
+ "components/foundations/",
109
+ "components/primitives/",
110
+ "components/ec/"
111
+ ],
93
112
  "message": "Primitiveカラー直接使用禁止",
94
113
  "fix": "bg-[var(--Brand-Cake-Orange)] 等セマンティックトークンを使う"
95
114
  },
@@ -98,7 +117,16 @@
98
117
  "severity": "warning",
99
118
  "category": "color",
100
119
  "pattern": "#[0-9A-Fa-f]{6}",
101
- "excludes": [".stories.", ".css", "shadow", "fill=\"", "stroke=\"", "components/foundations/", "components/primitives/", "components/ec/"],
120
+ "excludes": [
121
+ ".stories.",
122
+ ".css",
123
+ "shadow",
124
+ "fill=\"",
125
+ "stroke=\"",
126
+ "components/foundations/",
127
+ "components/primitives/",
128
+ "components/ec/"
129
+ ],
102
130
  "message": "HEXハードコード禁止(例外: サードパーティブランドロゴの SVG fill/stroke — 例 Amazon #FF9900、Google 4色。出典コメント推奨)",
103
131
  "fix": "var(--Brand-Cake-Orange) 等セマンティックトークンを使う"
104
132
  },
@@ -114,7 +142,9 @@
114
142
  "severity": "warning",
115
143
  "category": "color",
116
144
  "pattern": "text-black\\b",
117
- "excludes": [".stories."],
145
+ "excludes": [
146
+ ".stories."
147
+ ],
118
148
  "message": "text-black (#000) 禁止",
119
149
  "fix": "text-[var(--Text-High-Emphasis)](#1C1A1A)"
120
150
  },
@@ -123,7 +153,14 @@
123
153
  "severity": "warning",
124
154
  "category": "color",
125
155
  "pattern": "Border-High-Emphasis",
126
- "excludes": ["hover:", "focus:", "active:", "components/foundations/", "components/primitives/", "components/ec/"],
156
+ "excludes": [
157
+ "hover:",
158
+ "focus:",
159
+ "active:",
160
+ "components/foundations/",
161
+ "components/primitives/",
162
+ "components/ec/"
163
+ ],
127
164
  "message": "Border-High-Emphasis を静的なカード・コンテナに使用禁止",
128
165
  "fix": "通常枠は Border-Medium-Emphasis。hover時のみ hover:border-[var(--Border-High-Emphasis)]"
129
166
  },
@@ -168,7 +205,9 @@
168
205
  "severity": "warning",
169
206
  "category": "elevation",
170
207
  "pattern": "shadow-(xl|2xl)\\b",
171
- "excludes": [".stories."],
208
+ "excludes": [
209
+ ".stories."
210
+ ],
172
211
  "message": "DS定義外シャドウ禁止(shadow-xl/2xl)",
173
212
  "fix": "shadow-xs/sm/md/lg を使う(preset.css が --shadow-md/lg を DS 値に再定義済み)。オーバーレイは用途別トークン shadow-menu/tooltip/dialog/modal/overlay を推奨。フローティング UI の強い影(md/lg)は意図された正規仕様"
174
213
  },
@@ -185,7 +224,13 @@
185
224
  "severity": "error",
186
225
  "category": "component",
187
226
  "pattern": "<button\\b",
188
- "excludes": ["data-slot", ".stories.", "components/foundations/", "components/primitives/", "components/ec/"],
227
+ "excludes": [
228
+ "data-slot",
229
+ ".stories.",
230
+ "components/foundations/",
231
+ "components/primitives/",
232
+ "components/ec/"
233
+ ],
189
234
  "message": "生の <button> 禁止",
190
235
  "fix": "<Button variant='...' size='...'> を使う"
191
236
  },
@@ -194,7 +239,15 @@
194
239
  "severity": "error",
195
240
  "category": "component",
196
241
  "pattern": "<input\\b",
197
- "excludes": ["data-slot", ".stories.", "type=\"search\"", "type=\"file\"", "components/foundations/", "components/primitives/", "components/ec/"],
242
+ "excludes": [
243
+ "data-slot",
244
+ ".stories.",
245
+ "type=\"search\"",
246
+ "type=\"file\"",
247
+ "components/foundations/",
248
+ "components/primitives/",
249
+ "components/ec/"
250
+ ],
198
251
  "message": "生の <input> 禁止",
199
252
  "fix": "<Input> コンポーネントを使う"
200
253
  },
@@ -218,7 +271,11 @@
218
271
  "severity": "warning",
219
272
  "category": "component",
220
273
  "pattern": "`\\$\\{.*\\?.*\\}`",
221
- "excludes": ["components/foundations/", "components/primitives/", "components/ec/"],
274
+ "excludes": [
275
+ "components/foundations/",
276
+ "components/primitives/",
277
+ "components/ec/"
278
+ ],
222
279
  "message": "テンプレートリテラルでclassNameを組み立てない",
223
280
  "fix": "cn(base, active && 'bg-red') を使う"
224
281
  },
@@ -234,7 +291,12 @@
234
291
  "severity": "warning",
235
292
  "category": "spacing",
236
293
  "pattern": "<Card(?:\\s[^>]*)?>\\s*(?:\\{/\\*[\\s\\S]*?\\*/\\}\\s*)?<[^>]*className\\s*=\\s*[\"'`][^\"'`]*(^|\\s)(mt|mb|my|space-y)-",
237
- "excludes": [".stories.", "components/foundations/", "components/primitives/", "components/ec/"],
294
+ "excludes": [
295
+ ".stories.",
296
+ "components/foundations/",
297
+ "components/primitives/",
298
+ "components/ec/"
299
+ ],
238
300
  "message": "Card直下の子に mt-/mb-/my-/space-y- を足さない(縦間隔はCard本体の flex-col gap-4=16px が一括管理。二重がけで間延びする)",
239
301
  "fix": "余白クラスを外し Card の gap-4 に委ねる。丸アイコンは IconBadge を使う(外側marginを持たない)",
240
302
  "note": "limitation: この正規表現はJSXソース文字列のみを見る。別CSS/module.cssファイルに書かれた margin(実バグの主因)は検出不可。あくまでJSXにTailwindで直書きした場合の補助で、本命は components.json の Card 縦間隔ルール(正典)と IconBadge 部品化"
@@ -244,7 +306,15 @@
244
306
  "severity": "error",
245
307
  "category": "image",
246
308
  "pattern": "<img\\b",
247
- "excludes": ["AspectRatio", "aspect-ratio", ".stories.", "components/foundations/", "components/primitives/", "components/ec/", "object-cover"],
309
+ "excludes": [
310
+ "AspectRatio",
311
+ "aspect-ratio",
312
+ ".stories.",
313
+ "components/foundations/",
314
+ "components/primitives/",
315
+ "components/ec/",
316
+ "object-cover"
317
+ ],
248
318
  "message": "裸の <img> 禁止(CLS発生)",
249
319
  "fix": "<AspectRatio ratio={1}> で囲む"
250
320
  },
@@ -260,7 +330,11 @@
260
330
  "severity": "warning",
261
331
  "category": "accessibility",
262
332
  "pattern": "alt=\"\"",
263
- "excludes": ["components/foundations/", "components/primitives/", "components/ec/"],
333
+ "excludes": [
334
+ "components/foundations/",
335
+ "components/primitives/",
336
+ "components/ec/"
337
+ ],
264
338
  "message": "alt='' 禁止(スクリーンリーダーが読めない)",
265
339
  "fix": "alt='苺のショートケーキ' のように日本語で内容を書く"
266
340
  },
@@ -291,7 +365,9 @@
291
365
  "severity": "error",
292
366
  "category": "component",
293
367
  "pattern": "<select\\b",
294
- "excludes": ["components/foundations/"],
368
+ "excludes": [
369
+ "components/foundations/"
370
+ ],
295
371
  "message": "HTMLネイティブの <select> 禁止",
296
372
  "fix": "<Select> コンポーネントを使う"
297
373
  },
@@ -307,7 +383,9 @@
307
383
  "severity": "error",
308
384
  "category": "modal",
309
385
  "pattern": "fixed inset-0",
310
- "excludes": ["components/foundations/"],
386
+ "excludes": [
387
+ "components/foundations/"
388
+ ],
311
389
  "message": "div.fixed.inset-0 で自作モーダル禁止",
312
390
  "fix": "<Dialog> or <Sheet> を使う(ESC・Tab・背景スクロールを自動処理)"
313
391
  },
@@ -352,7 +430,11 @@
352
430
  "severity": "warning",
353
431
  "category": "layout",
354
432
  "pattern": "position:\\s*absolute",
355
- "excludes": ["components/foundations/", "components/primitives/", "components/ec/"],
433
+ "excludes": [
434
+ "components/foundations/",
435
+ "components/primitives/",
436
+ "components/ec/"
437
+ ],
356
438
  "message": "position: absolute で要素を並べない",
357
439
  "fix": "Flexbox / Grid を使う"
358
440
  },
@@ -376,7 +458,12 @@
376
458
  "severity": "warning",
377
459
  "category": "component",
378
460
  "pattern": "border-l-4|border-t-4|border-r-4|border-b-4",
379
- "excludes": [".stories.", "components/foundations/", "components/primitives/", "components/ec/"],
461
+ "excludes": [
462
+ ".stories.",
463
+ "components/foundations/",
464
+ "components/primitives/",
465
+ "components/ec/"
466
+ ],
380
467
  "message": "トーストに左ボーダーで状態色を付けない",
381
468
  "fix": "背景色全体で状態を表現(!bg-[var(--Surface-Caution-Light)])"
382
469
  },
@@ -408,7 +495,11 @@
408
495
  "severity": "warning",
409
496
  "category": "accessibility",
410
497
  "pattern": "aria-label=\"[A-Z][a-z]",
411
- "excludes": ["components/foundations/", "components/primitives/", "components/ec/"],
498
+ "excludes": [
499
+ "components/foundations/",
500
+ "components/primitives/",
501
+ "components/ec/"
502
+ ],
412
503
  "message": "aria-labelを英語で書かない(cake.jpは日本語サービス)",
413
504
  "fix": "aria-label='閉じる'('Close'にしない)"
414
505
  },
@@ -417,7 +508,12 @@
417
508
  "severity": "error",
418
509
  "category": "accessibility",
419
510
  "pattern": "outline-none\\b",
420
- "excludes": ["focus-visible", "components/foundations/", "components/primitives/", "components/ec/"],
511
+ "excludes": [
512
+ "focus-visible",
513
+ "components/foundations/",
514
+ "components/primitives/",
515
+ "components/ec/"
516
+ ],
421
517
  "message": "outline-none でフォーカスリングを消す禁止",
422
518
  "fix": "focus-visible:ring-[3px] focus-visible:ring-[var(--Focus-High-Emphasis)]/50"
423
519
  },
@@ -426,78 +522,28 @@
426
522
  "severity": "error",
427
523
  "category": "accessibility",
428
524
  "pattern": "<div.*onClick|<span.*onClick",
429
- "excludes": ["components/foundations/", "components/primitives/", "components/ec/"],
525
+ "excludes": [
526
+ "components/foundations/",
527
+ "components/primitives/",
528
+ "components/ec/"
529
+ ],
430
530
  "message": "<div onClick> でクリック処理禁止",
431
531
  "fix": "<button> か <a> を使う"
432
532
  },
433
- {
434
- "id": "AI1",
435
- "severity": "warning",
436
- "category": "ai-pattern",
437
- "pattern": "border-t-4 border-.*-[0-9]+",
438
- "message": "AI生成パターン: カード上部カラーバー禁止",
439
- "fix": "border border-[var(--Border-Low-Emphasis)] で全周ボーダー"
440
- },
441
- {
442
- "id": "AI2",
443
- "severity": "warning",
444
- "category": "ai-pattern",
445
- "pattern": "border-l-4 border-.*-[0-9]+",
446
- "message": "AI生成パターン: 左端カラーストライプ禁止(Alert含む)",
447
- "fix": "border rounded-lg で全周ボーダー"
448
- },
449
533
  {
450
534
  "id": "B1",
451
535
  "severity": "error",
452
536
  "category": "component",
453
537
  "scope": "designSystemInternal",
454
- "appliesTo": ["components/foundations/", "components/primitives/", "components/ec/"],
538
+ "appliesTo": [
539
+ "components/foundations/",
540
+ "components/primitives/",
541
+ "components/ec/"
542
+ ],
455
543
  "pattern": "border 幅ユーティリティ(border / border-b / border-l 等)に色クラスが同居していない",
456
544
  "message": "DSコンポーネントで色指定のない border を使わない。Tailwind v4 の border-color 既定は currentColor。消費アプリが preset.css のグローバル base リセット(* { @apply border-border })を取り込まない場合、罫線が要素の文字色に化ける(例: テーブル行に text-[var(--Text-High-Emphasis)] を付けると罫線が黒 #1C1A1A になる)。コンポーネントはグローバルリセットに依存せず自前で border 色を持つこと。",
457
545
  "fix": "同じ className 内に border-[var(--Border-Medium-Emphasis)] 等を明示する(透明が意図なら border-transparent)。検査: npm run lint:border(scripts/check-border-color.mjs)"
458
546
  },
459
- {
460
- "id": "AI5",
461
- "severity": "warning",
462
- "category": "ai-pattern",
463
- "message": "文脈非依存違反: text色/背景/アイコン色を明示せず親の継承や Tailwind v4 既定(border/ring/outline=currentColor)に委ねる。消費側が濃色テキストや色付き背景を敷くと文字・アイコン・枠が化ける。サーフェス(カード/オーバーレイ等)が bg 未指定だと親背景が透ける。",
464
- "fix": "テキスト要素に text-[var(--Text-*)]、サーフェスに bg-[var(--Surface-*)] を明示。Content/オーバーレイ系ラッパは text-popover-foreground 等で子を隔離する。Storybook ツールバーの『Hostile ctx』を loud にして漏れ(マゼンタ化・背景透け)を目視確認する。"
465
- },
466
- {
467
- "id": "AI3",
468
- "severity": "warning",
469
- "category": "ai-pattern",
470
- "pattern": "bg-gradient-to-",
471
- "excludes": [".stories.", "components/foundations/", "components/primitives/", "components/ec/"],
472
- "message": "AI生成パターン: グラデーション背景禁止",
473
- "fix": "セマンティックトークンの単色背景"
474
- },
475
- {
476
- "id": "AI4",
477
- "severity": "warning",
478
- "category": "ai-pattern",
479
- "pattern": "tracking-tight",
480
- "message": "AI生成パターン: tracking-tight禁止(日本語の可読性が著しく低下)",
481
- "fix": "typo-* クラスに含まれる値を使う"
482
- },
483
- {
484
- "id": "AI6",
485
- "severity": "warning",
486
- "category": "ai-pattern",
487
- "pattern": "animate-spin|animate-bounce|animate-ping",
488
- "excludes": [".stories.", "components/foundations/"],
489
- "message": "AI生成パターン: 常時ループアニメーション禁止",
490
- "fix": "スケルトンのpulseのみ許可"
491
- },
492
- {
493
- "id": "AI7",
494
- "severity": "warning",
495
- "category": "ai-pattern",
496
- "pattern": "rounded-(3xl|4xl)\\b|rounded-\\[[0-9]",
497
- "excludes": [".stories."],
498
- "message": "AI生成パターン: DS定義外の角丸禁止(rounded-3xl/4xl・任意値 rounded-[Npx])",
499
- "fix": "DSトークンスケールのみ使用: rounded-xs(2)/sm(6)/md(8)/lg(10)/xl(14)/2xl(18px)/full(--radius=10px 基準)。目安: メニュー・小型コントロール=md、ボタン・入力=lg(Button lg/xl は xl)、コンパクトカード=xl、標準カード・ダイアログ=2xl。例外は lint-scratch-allow コメントで理由を明記"
500
- },
501
547
  {
502
548
  "id": "R44",
503
549
  "severity": "warning",
@@ -549,7 +595,7 @@
549
595
  "category": "component",
550
596
  "pattern": "<input type=\"file\"|<input type='file'",
551
597
  "message": "ネイティブ <input type='file'> を直接使わない",
552
- "fix": "汎用の添付(PDF/CSV/画像混在)は <FileInput />(foundations)を使う。プレビュー付きの画像管理(並び替え・複数サムネイル)は <ImageUploader />(primitives)を使う"
598
+ "fix": "汎用の添付(PDF/CSV/画像混在)は <FileInput />(foundations)を使う。画像1枚の入力(プレビュー+形式/サイズ検証+値のバインド)は <ImageInput />(primitives)、複数枚のグリッド管理は <ImageUploader />(primitives)を使う"
553
599
  },
554
600
  {
555
601
  "id": "R55",
@@ -557,21 +603,60 @@
557
603
  "category": "component",
558
604
  "message": "画像・メディアの上に載せる操作ボタンを rgba 直書きの半透過下地で手組みしない",
559
605
  "fix": "<Button variant='overlay'>(半透過白 Surface-Overlay-Light + shadow-md + backdrop-blur-sm)を使う。ImageCarousel 矢印と同系の意匠。円形は size='icon' + className='rounded-full'"
606
+ },
607
+ {
608
+ "id": "R56",
609
+ "severity": "error",
610
+ "category": "component",
611
+ "pattern": "<Input[^>]+type=[\"']number[\"']",
612
+ "excludes": ["components/primitives/number-input.tsx"],
613
+ "message": "Input type='number' を直接使わない",
614
+ "fix": "数値入力はカート数量・価格・在庫すべて <NumberInput /> を使う(size=\"sm\" コンパクト型 / size=\"md\" サークル型)"
560
615
  }
561
616
  ],
562
617
  "accessibility": {
563
618
  "wcag": "2.1 AA",
564
619
  "requirements": [
565
- { "id": "A001", "rule": "通常テキスト(18px未満)のコントラスト比 4.5:1 以上" },
566
- { "id": "A002", "rule": "大テキスト(18px以上bold/24px以上normal)のコントラスト比 3:1 以上" },
567
- { "id": "A003", "rule": "UIコンポーネント境界・アイコンのコントラスト比 3:1 以上" },
568
- { "id": "A004", "rule": "フォーカスインジケーターのコントラスト比 3:1(隣接色との差)" },
569
- { "id": "A005", "rule": "フォーカスリング必須: focus-visible:ring-[3px] focus-visible:ring-[var(--Focus-High-Emphasis)]/50" },
570
- { "id": "A006", "rule": "アイコンのみボタンに日本語のaria-label必須" },
571
- { "id": "A007", "rule": "全フォーム入力に <Label> または aria-label を紐付ける" },
572
- { "id": "A008", "rule": "フォームエラーは aria-describedby でエラーメッセージを紐付ける" },
573
- { "id": "A009", "rule": "動的に変化する情報は aria-live='polite' で通知する" },
574
- { "id": "A010", "rule": "セマンティックHTML: nav/main/section/header/footer を適切に使用する" }
620
+ {
621
+ "id": "A001",
622
+ "rule": "通常テキスト(18px未満)のコントラスト比 4.5:1 以上"
623
+ },
624
+ {
625
+ "id": "A002",
626
+ "rule": "大テキスト(18px以上bold/24px以上normal)のコントラスト比 3:1 以上"
627
+ },
628
+ {
629
+ "id": "A003",
630
+ "rule": "UIコンポーネント境界・アイコンのコントラスト比 3:1 以上"
631
+ },
632
+ {
633
+ "id": "A004",
634
+ "rule": "フォーカスインジケーターのコントラスト比 3:1(隣接色との差)"
635
+ },
636
+ {
637
+ "id": "A005",
638
+ "rule": "フォーカスリング必須: focus-visible:ring-[3px] focus-visible:ring-[var(--Focus-High-Emphasis)]/50"
639
+ },
640
+ {
641
+ "id": "A006",
642
+ "rule": "アイコンのみボタンに日本語のaria-label必須"
643
+ },
644
+ {
645
+ "id": "A007",
646
+ "rule": "全フォーム入力に <Label> または aria-label を紐付ける"
647
+ },
648
+ {
649
+ "id": "A008",
650
+ "rule": "フォームエラーは aria-describedby でエラーメッセージを紐付ける"
651
+ },
652
+ {
653
+ "id": "A009",
654
+ "rule": "動的に変化する情報は aria-live='polite' で通知する"
655
+ },
656
+ {
657
+ "id": "A010",
658
+ "rule": "セマンティックHTML: nav/main/section/header/footer を適切に使用する"
659
+ }
575
660
  ]
576
661
  },
577
662
  "darkMode": {
@@ -584,21 +669,89 @@
584
669
  "typography": {
585
670
  "rule": "必ず typo-* クラスを使用。text-sm font-bold 等の個別指定禁止。",
586
671
  "classes": [
587
- { "class": "typo-heading-4xl", "size": "32px", "weight": "bold" },
588
- { "class": "typo-heading-3xl", "size": "28px", "weight": "bold" },
589
- { "class": "typo-heading-2xl", "size": "24px", "weight": "bold" },
590
- { "class": "typo-heading-xl", "size": "21px", "weight": "bold" },
591
- { "class": "typo-heading-lg", "size": "18px", "weight": "bold" },
592
- { "class": "typo-heading-md", "size": "16px", "weight": "bold" },
593
- { "class": "typo-heading-sm", "size": "14px", "weight": "bold" },
594
- { "class": "typo-body-lg", "size": "16px", "weight": "normal" },
595
- { "class": "typo-body-md", "size": "14px", "weight": "normal" },
596
- { "class": "typo-body-sm", "size": "12px", "weight": "normal" },
597
- { "class": "typo-body-xs", "size": "10px", "weight": "normal" },
598
- { "class": "typo-label-lg", "size": "16px", "weight": "bold" },
599
- { "class": "typo-label-md", "size": "14px", "weight": "bold" },
600
- { "class": "typo-label-sm", "size": "12px", "weight": "semibold" },
601
- { "class": "typo-label-xs", "size": "10px", "weight": "semibold" }
672
+ {
673
+ "class": "typo-heading-5xl",
674
+ "size": "40px",
675
+ "weight": "bold",
676
+ "usage": "LP・マーケティング系ヒーローの PC 見出し限定"
677
+ },
678
+ {
679
+ "class": "typo-heading-4xl",
680
+ "size": "32px",
681
+ "weight": "bold",
682
+ "usage": "LP・マーケティング系ヒーローの PC 見出し限定(5xlより抑えた表現)"
683
+ },
684
+ {
685
+ "class": "typo-heading-3xl",
686
+ "size": "28px",
687
+ "weight": "bold",
688
+ "usage": "通常ページの主見出し・ページタイトル。LPではSP側にも使用"
689
+ },
690
+ {
691
+ "class": "typo-heading-2xl",
692
+ "size": "24px",
693
+ "weight": "bold"
694
+ },
695
+ {
696
+ "class": "typo-heading-xl",
697
+ "size": "21px",
698
+ "weight": "bold"
699
+ },
700
+ {
701
+ "class": "typo-heading-lg",
702
+ "size": "18px",
703
+ "weight": "bold"
704
+ },
705
+ {
706
+ "class": "typo-heading-md",
707
+ "size": "16px",
708
+ "weight": "bold"
709
+ },
710
+ {
711
+ "class": "typo-heading-sm",
712
+ "size": "14px",
713
+ "weight": "bold"
714
+ },
715
+ {
716
+ "class": "typo-body-lg",
717
+ "size": "16px",
718
+ "weight": "normal"
719
+ },
720
+ {
721
+ "class": "typo-body-md",
722
+ "size": "14px",
723
+ "weight": "normal"
724
+ },
725
+ {
726
+ "class": "typo-body-sm",
727
+ "size": "12px",
728
+ "weight": "normal"
729
+ },
730
+ {
731
+ "class": "typo-body-xs",
732
+ "size": "10px",
733
+ "weight": "normal"
734
+ },
735
+ {
736
+ "class": "typo-label-lg",
737
+ "size": "16px",
738
+ "weight": "bold"
739
+ },
740
+ {
741
+ "class": "typo-label-md",
742
+ "size": "14px",
743
+ "weight": "bold"
744
+ },
745
+ {
746
+ "class": "typo-label-sm",
747
+ "size": "12px",
748
+ "weight": "semibold"
749
+ },
750
+ {
751
+ "class": "typo-label-xs",
752
+ "size": "10px",
753
+ "weight": "semibold"
754
+ }
602
755
  ]
603
756
  },
604
757
  "tokens": {
@@ -610,12 +763,33 @@
610
763
  "touchTarget": {
611
764
  "rule": "タッチターゲット最小サイズを守ること",
612
765
  "values": [
613
- { "element": "Button(CTA)", "min": "40px", "recommended": "48px" },
614
- { "element": "Icon button", "min": "40px", "recommended": "44px" },
615
- { "element": "Text input", "min": "44px", "recommended": "48px" },
616
- { "element": "Chip/Filter", "min": "32px", "recommended": "36px" },
617
- { "element": "Navigation item", "min": "44px", "recommended": "48px" }
618
- ]
766
+ {
767
+ "element": "Button(CTA)",
768
+ "min": "40px",
769
+ "recommended": "48px"
770
+ },
771
+ {
772
+ "element": "Icon button",
773
+ "min": "40px",
774
+ "recommended": "44px"
775
+ },
776
+ {
777
+ "element": "Text input",
778
+ "min": "44px",
779
+ "recommended": "48px"
780
+ },
781
+ {
782
+ "element": "Chip/Filter",
783
+ "min": "32px",
784
+ "recommended": "36px"
785
+ },
786
+ {
787
+ "element": "Navigation item",
788
+ "min": "44px",
789
+ "recommended": "48px"
790
+ }
791
+ ],
792
+ "utility": "見た目が44px未満の小型操作部品をSPで使う場合は className=\"tap-target\" を付け、透明な疑似要素で実効操作領域を44×44px以上にする。隣接ターゲットと重なる密度では使わず親のgapを広げる"
619
793
  }
620
794
  },
621
795
  "writing": {
@@ -627,5 +801,72 @@
627
801
  "お届け日: M月D日(曜日)(例: 8月1日(木))",
628
802
  "価格: ¥{数字,区切り}(税込)(例: ¥3,980(税込))"
629
803
  ]
804
+ },
805
+ "aiPatterns": {
806
+ "description": "AI生成コードで繰り返し発生する禁止パターン。絶対禁止ルールとは分けて診断する。",
807
+ "patterns": [
808
+ {
809
+ "id": "AI1",
810
+ "name": "カード上部カラーバー",
811
+ "pattern": "border-t-4 border-.*-[0-9]+",
812
+ "description": "AI生成パターン: カード上部カラーバー禁止",
813
+ "fix": "border border-[var(--Border-Low-Emphasis)] で全周ボーダー"
814
+ },
815
+ {
816
+ "id": "AI2",
817
+ "name": "左端カラーストライプ",
818
+ "pattern": "border-l-4 border-.*-[0-9]+",
819
+ "description": "AI生成パターン: 左端カラーストライプ禁止(Alert含む)",
820
+ "fix": "border rounded-lg で全周ボーダー"
821
+ },
822
+ {
823
+ "id": "AI5",
824
+ "name": "文脈非依存違反: text色/背景/アイコン色を明示せず親の継承や Tailwind v4 既定(border/ring/outline=currentColor)に委ねる。消費側が濃色テキストや色付き背景を敷くと文字・アイコン・枠が化ける。サーフェス(カード/オーバーレイ等)が bg 未指定だと親背景が透ける。",
825
+ "pattern": "",
826
+ "description": "文脈非依存違反: text色/背景/アイコン色を明示せず親の継承や Tailwind v4 既定(border/ring/outline=currentColor)に委ねる。消費側が濃色テキストや色付き背景を敷くと文字・アイコン・枠が化ける。サーフェス(カード/オーバーレイ等)が bg 未指定だと親背景が透ける。",
827
+ "fix": "テキスト要素に text-[var(--Text-*)]、サーフェスに bg-[var(--Surface-*)] を明示。Content/オーバーレイ系ラッパは text-popover-foreground 等で子を隔離する。Storybook ツールバーの『Hostile ctx』を loud にして漏れ(マゼンタ化・背景透け)を目視確認する。"
828
+ },
829
+ {
830
+ "id": "AI3",
831
+ "name": "グラデーション背景",
832
+ "pattern": "bg-gradient-to-",
833
+ "description": "AI生成パターン: グラデーション背景禁止",
834
+ "fix": "セマンティックトークンの単色背景",
835
+ "excludes": [
836
+ ".stories.",
837
+ "components/foundations/",
838
+ "components/primitives/",
839
+ "components/ec/"
840
+ ]
841
+ },
842
+ {
843
+ "id": "AI4",
844
+ "name": "tracking-tight",
845
+ "pattern": "tracking-tight",
846
+ "description": "AI生成パターン: tracking-tight禁止(日本語の可読性が著しく低下)",
847
+ "fix": "typo-* クラスに含まれる値を使う"
848
+ },
849
+ {
850
+ "id": "AI6",
851
+ "name": "常時ループアニメーション",
852
+ "pattern": "animate-spin|animate-bounce|animate-ping",
853
+ "description": "AI生成パターン: 常時ループアニメーション禁止",
854
+ "fix": "スケルトンのpulseのみ許可",
855
+ "excludes": [
856
+ ".stories.",
857
+ "components/foundations/"
858
+ ]
859
+ },
860
+ {
861
+ "id": "AI7",
862
+ "name": "DS定義外の角丸",
863
+ "pattern": "rounded-(3xl|4xl)\\b|rounded-\\[[0-9]",
864
+ "description": "AI生成パターン: DS定義外の角丸禁止(rounded-3xl/4xl・任意値 rounded-[Npx])",
865
+ "fix": "DSトークンスケールのみ使用: rounded-xs(2)/sm(6)/md(8)/lg(10)/xl(14)/2xl(18px)/full(--radius=10px 基準)。目安: メニュー・小型コントロール=md、ボタン・入力=lg(Button lg/xl は xl)、コンパクトカード=xl、標準カード・ダイアログ=2xl。例外は lint-scratch-allow コメントで理由を明記",
866
+ "excludes": [
867
+ ".stories."
868
+ ]
869
+ }
870
+ ]
630
871
  }
631
872
  }