@cakejp/design-system 0.11.0 → 0.12.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 (43) hide show
  1. package/CHANGELOG.md +42 -1
  2. package/CLAUDE.md +18 -1
  3. package/README.md +48 -0
  4. package/UPDATING.md +9 -0
  5. package/bin/check-duplicates.mjs +132 -0
  6. package/bin/init.js +8 -0
  7. package/contracts/components.json +175 -21
  8. package/contracts/rules.json +17 -1
  9. package/dist/index.css +1 -1
  10. package/dist/index.js +5266 -3354
  11. package/dist/types/components/ec/admin-shell.d.ts +10 -1
  12. package/dist/types/components/ec/mypage-shell.d.ts +10 -1
  13. package/dist/types/components/ec/product-card.d.ts +3 -1
  14. package/dist/types/components/ec/product-list-item.d.ts +8 -1
  15. package/dist/types/components/foundations/alert.d.ts +5 -1
  16. package/dist/types/components/foundations/button.d.ts +1 -1
  17. package/dist/types/components/foundations/card.d.ts +12 -2
  18. package/dist/types/components/foundations/chip-variants.d.ts +17 -0
  19. package/dist/types/components/foundations/field.d.ts +58 -0
  20. package/dist/types/components/foundations/file-input.d.ts +75 -0
  21. package/dist/types/components/foundations/icon-badge.d.ts +2 -2
  22. package/dist/types/components/foundations/input.d.ts +9 -1
  23. package/dist/types/components/foundations/radio-group.d.ts +12 -2
  24. package/dist/types/components/foundations/skip-link.d.ts +39 -0
  25. package/dist/types/components/foundations/textarea.d.ts +9 -1
  26. package/dist/types/components/primitives/chip.d.ts +2 -7
  27. package/dist/types/components/primitives/content-carousel.d.ts +52 -0
  28. package/dist/types/components/primitives/date-picker.d.ts +32 -0
  29. package/dist/types/components/primitives/error-state.d.ts +43 -16
  30. package/dist/types/components/primitives/funnel-shell.d.ts +10 -1
  31. package/dist/types/components/primitives/header.d.ts +15 -1
  32. package/dist/types/components/primitives/section-nav.d.ts +28 -2
  33. package/dist/types/components/primitives/share-buttons.d.ts +8 -2
  34. package/dist/types/components/primitives/standard-page-shell.d.ts +11 -1
  35. package/dist/types/components/primitives/workspace-shell.d.ts +19 -1
  36. package/dist/types/index.d.ts +66 -2
  37. package/package.json +1 -1
  38. package/src/preset-standalone.css +306 -4
  39. package/src/styles/semantic.css +7 -0
  40. package/src/styles/typography.css +8 -1
  41. package/templates/AGENTS.md +9 -0
  42. package/templates/CLAUDE.md +9 -0
  43. package/tokens.json +10 -1
@@ -5,10 +5,10 @@
5
5
  "description": "全コンポーネントの構造化定義。バリアント・アクセシビリティ要件・使用ルールを機械可読形式で管理。",
6
6
  "kind": "kind:\"shell\" は複数ページで再利用されるレイアウト枠(AdminShell / WorkspaceShell / MypageShell 等)。無印は部品コンポーネント。固有ページを組むときは該当 shell から始める。src/components/pages/ 配下のストーリーは特定ページ専用・非配布のため contracts の対象外。",
7
7
  "counts": {
8
- "foundations": 47,
9
- "primitives": 42,
8
+ "foundations": 50,
9
+ "primitives": 44,
10
10
  "ec": 24,
11
- "total": 113
11
+ "total": 118
12
12
  }
13
13
  },
14
14
  "foundations": [
@@ -26,9 +26,22 @@
26
26
  {
27
27
  "name": "Alert",
28
28
  "path": "src/components/foundations/alert.tsx",
29
+ "subcomponents": [
30
+ "AlertTitle",
31
+ "AlertDescription"
32
+ ],
29
33
  "variants": [
30
- "default",
31
- "destructive"
34
+ "success",
35
+ "info",
36
+ "error",
37
+ "warning",
38
+ "inline-info",
39
+ "inline-caution",
40
+ "inline-warning"
41
+ ],
42
+ "rules": [
43
+ "bordered variant(success/info/error/warning)は title/description/icon/action の prop-based API に対応(旧 Banner 相当)",
44
+ "inline variant(inline-info/inline-caution/inline-warning)も同じ prop-based API に対応(#109)。フォーム内・セクション内の軽量な補足情報用。アイコンは20pxで自動選択"
32
45
  ]
33
46
  },
34
47
  {
@@ -75,7 +88,8 @@
75
88
  "ghost",
76
89
  "link",
77
90
  "inverse",
78
- "ghost-inverse"
91
+ "ghost-inverse",
92
+ "overlay"
79
93
  ],
80
94
  "sizes": [
81
95
  "xs",
@@ -89,7 +103,8 @@
89
103
  "aria-label必須(アイコンのみの場合)"
90
104
  ],
91
105
  "rules": [
92
- "<button>を直接使わない。必ずButtonコンポーネントを使う"
106
+ "<button>を直接使わない。必ずButtonコンポーネントを使う",
107
+ "variant='overlay'は画像・メディアの上に載せる操作ボタン専用(半透過白のSurface-Overlay-Light下地+shadow-md+backdrop-blur-sm)。ImageCarousel矢印と同系の意匠。size='icon'+className='rounded-full'で円形にできる"
93
108
  ]
94
109
  },
95
110
  {
@@ -109,9 +124,16 @@
109
124
  "CardContent",
110
125
  "CardFooter"
111
126
  ],
127
+ "variants": {
128
+ "surface": [
129
+ "default",
130
+ "primary"
131
+ ]
132
+ },
112
133
  "rules": [
113
134
  "paddingはCard本体のp-4で一括管理。全幅コンテンツは-mx-4で突き破る",
114
- "子要素の縦間隔はCard本体のflex-col gap-4(16px)で一括管理。直下の子にmargin-top/bottom/space-yを足さない(gapと二重がけになり間延びする)。丸アイコンはIconBadgeを使う(外側marginを持たない)"
135
+ "子要素の縦間隔はCard本体のflex-col gap-4(16px)で一括管理。直下の子にmargin-top/bottom/space-yを足さない(gapと二重がけになり間延びする)。丸アイコンはIconBadgeを使う(外側marginを持たない)",
136
+ "surface='default'(既定)はbg-card(Surface-Secondary)。Surface-Tertiary系(グレーSection)の地の上ではコントラスト不足になるためsurface='primary'(白=Surface-Primary)を使う"
115
137
  ]
116
138
  },
117
139
  {
@@ -177,6 +199,23 @@
177
199
  "name": "DropdownMenu",
178
200
  "path": "src/components/foundations/dropdown-menu.tsx"
179
201
  },
202
+ {
203
+ "name": "Field",
204
+ "path": "src/components/foundations/field.tsx",
205
+ "subcomponents": [
206
+ "FieldSet",
207
+ "FieldLegend",
208
+ "FieldGroup",
209
+ "FieldDescription",
210
+ "FieldError",
211
+ "FieldSeparator"
212
+ ],
213
+ "rules": [
214
+ "フォーム全体の骨格を組む補助群。個々の入力欄は FormField を使う",
215
+ "余白は縦リズムに従う(FieldSet=gap-6 / FieldGroup=gap-4)。手で mt-/mb- を足さない",
216
+ "見出しは FieldLegend、グループ横断の区切りは FieldSeparator を使う"
217
+ ]
218
+ },
180
219
  {
181
220
  "name": "Form",
182
221
  "path": "src/components/foundations/form.tsx",
@@ -193,13 +232,14 @@
193
232
  "path": "src/components/foundations/icon-badge.tsx",
194
233
  "variants": [
195
234
  "md",
235
+ "ml",
196
236
  "lg"
197
237
  ],
198
238
  "rules": [
199
- "丸アイコンバッジ(md=44px/lg=72px)。アイコンを淡いアクセント背景の円で囲む装飾要素",
239
+ "丸アイコンバッジ(md=44px/ml=48px/lg=72px)。アイコンを淡いアクセント背景の円で囲む装飾要素",
200
240
  "外側marginを持たない。縦間隔は親Cardのflex-col gap-4(16px)に委ねる(二重がけ防止)",
201
241
  "アイコン色はcurrentColor(--Object-Accent-Primary)を継承。中のアイコンにcolorを渡さない",
202
- "アイコンサイズはバッジが固定(md=20px/lg=38px)。アイコン側にsizeを渡さない"
242
+ "アイコンサイズはバッジが固定(md=20px/ml=24px/lg=38px)。アイコン側にsizeを渡さない"
203
243
  ]
204
244
  },
205
245
  {
@@ -209,7 +249,8 @@
209
249
  "必ずLabelと紐付ける"
210
250
  ],
211
251
  "rules": [
212
- "<input>を直接使わない。type='email'/'tel'を適切に指定する"
252
+ "<input>を直接使わない。type='email'/'tel'を適切に指定する",
253
+ "文字数カウンタは showCount + maxLength で有効化(右下に {現在}/{max}、上限で Text-Caution)。制御/非制御両対応"
213
254
  ]
214
255
  },
215
256
  {
@@ -247,8 +288,31 @@
247
288
  {
248
289
  "name": "RadioGroup",
249
290
  "path": "src/components/foundations/radio-group.tsx",
291
+ "variants": [
292
+ "tile",
293
+ "chip"
294
+ ],
250
295
  "accessibility": [
251
296
  "各RadioGroupItemにLabel必須"
297
+ ],
298
+ "rules": [
299
+ "variant='tile'(既定)=ラジオ丸+ラベル+補足説明+展開コンテンツのタイル型",
300
+ "variant='chip'=ラベルを内包したChoice Chip意匠の排他選択(タグ選択・絞り込み等)。ラジオ丸は描画せず、Chip本体と同じchipVariantsを再利用して選択状態をaccent意匠(静止=薄オレンジ/hover=ベタ塗り)で示す。description/expandedContentは持たない。Radixのキーボード操作・a11yは維持"
301
+ ]
302
+ },
303
+ {
304
+ "name": "FileInput",
305
+ "path": "src/components/foundations/file-input.tsx",
306
+ "accessibility": [
307
+ "idをLabel/FormFieldのhtmlForと揃えて紐付ける",
308
+ "ネイティブ<input type='file'>をvisually-hiddenで内包しキーボード・SR操作可能",
309
+ "エラー表示はaria-describedbyでFieldErrorと接続"
310
+ ],
311
+ "rules": [
312
+ "<input type='file'>を直接書かない。汎用の添付(PDF/CSV/画像混在)はFileInputを使う",
313
+ "プレビュー付きの画像管理(並び替え・複数サムネイル)はImageUploaderを使う",
314
+ "複数選択時(multiple)は選択済みを「n件選択」で集約表示",
315
+ "maxSize(バイト)超過ファイルは受理せずonErrorを呼ぶ"
252
316
  ]
253
317
  },
254
318
  {
@@ -293,6 +357,20 @@
293
357
  "アニメーションはpulseのみ許可"
294
358
  ]
295
359
  },
360
+ {
361
+ "name": "SkipLink",
362
+ "path": "src/components/foundations/skip-link.tsx",
363
+ "category": "navigation",
364
+ "accessibility": [
365
+ "WCAG 2.4.1(Bypass Blocks)対応。キーボード/SR ユーザーがヘッダーの反復リンクを飛ばして本文へ移動する",
366
+ "aria/文言は日本語(既定「コンテンツへ移動」)"
367
+ ],
368
+ "rules": [
369
+ "sr-only で常時視覚には出さず、フォーカス時のみ左上に可視化する(focus:not-sr-only)",
370
+ "スキップ先 <main id> は href(既定 #main-content)と一致させる",
371
+ "全シェル(StandardPageShell / FunnelShell / WorkspaceShell / AdminShell / MypageShell)が DOM 先頭に標準内蔵する。シェルを使う場合は個別に置かない(skipLink={false} で無効化)"
372
+ ]
373
+ },
296
374
  {
297
375
  "name": "Slider",
298
376
  "path": "src/components/foundations/slider.tsx"
@@ -336,6 +414,9 @@
336
414
  "path": "src/components/foundations/textarea.tsx",
337
415
  "accessibility": [
338
416
  "Label必須"
417
+ ],
418
+ "rules": [
419
+ "文字数カウンタは showCount + maxLength で有効化(右下に {現在}/{max}、上限で Text-Caution)。制御/非制御両対応"
339
420
  ]
340
421
  },
341
422
  {
@@ -366,6 +447,21 @@
366
447
  "name": "BannerCarousel",
367
448
  "path": "src/components/primitives/banner-carousel.tsx"
368
449
  },
450
+ {
451
+ "name": "ContentCarousel",
452
+ "path": "src/components/primitives/content-carousel.tsx",
453
+ "features": [
454
+ "scroll-snap",
455
+ "dots",
456
+ "arrows",
457
+ "autoPlay"
458
+ ],
459
+ "rules": [
460
+ "ReactNode スライド対応(slides: ReactNode[])。テキスト主体のヒーローバナー用",
461
+ "画像だけのバナーは ImageCarousel を使う",
462
+ "矢印・ドットの意匠は ImageCarousel と同一"
463
+ ]
464
+ },
369
465
  {
370
466
  "name": "StickyActionBar",
371
467
  "path": "src/components/primitives/sticky-action-bar.tsx",
@@ -411,6 +507,20 @@
411
507
  "Tagと違い押せる・削除できる"
412
508
  ]
413
509
  },
510
+ {
511
+ "name": "DatePicker",
512
+ "path": "src/components/primitives/date-picker.tsx",
513
+ "subcomponents": [
514
+ "DateTimePicker"
515
+ ],
516
+ "rules": [
517
+ "input type='date' 禁止ルールの実装済みの正解形。Popover+Calendar を毎回手組みしない",
518
+ "trigger の選択値は M月D日(曜日)表記、カレンダーは日本語ロケール",
519
+ "選択範囲は min/max、個別不可日は disabledDates で指定する",
520
+ "DateTimePicker は JST 前提で Date をそのまま扱う(TZ 変換しない)",
521
+ "FormField の children に置き、id を htmlFor と揃えて label/エラーと接続する"
522
+ ]
523
+ },
414
524
  {
415
525
  "name": "EmptyState",
416
526
  "path": "src/components/primitives/empty-state.tsx",
@@ -421,8 +531,19 @@
421
531
  {
422
532
  "name": "ErrorState",
423
533
  "path": "src/components/primitives/error-state.tsx",
534
+ "variants": {
535
+ "kind": [
536
+ "error",
537
+ "notFound"
538
+ ]
539
+ },
540
+ "subcomponents": [
541
+ "NotFoundIllustration"
542
+ ],
424
543
  "rules": [
425
- "色+アイコン+テキスト必須。リトライアクションを含める"
544
+ "kind='error'(既定)は色+アイコン+テキスト必須。リトライアクションを含める",
545
+ "kind='notFound' は 404 向け。イラスト・見出し・説明が既定で入るため action(トップへ戻る等)だけ渡せばよい",
546
+ "NotFoundIllustration は単体 export。consumer が独自レイアウトで使う場合に流用する"
426
547
  ]
427
548
  },
428
549
  {
@@ -618,12 +739,19 @@
618
739
  "name": "SectionNav",
619
740
  "path": "src/components/primitives/section-nav.tsx",
620
741
  "category": "navigation",
742
+ "variants": [
743
+ "vertical",
744
+ "horizontal"
745
+ ],
621
746
  "rules": [
622
747
  "ページ内セクション移動(アンカー/目次)専用。href=\"#section-id\" のページ内スクロールに使う",
623
748
  "ページ間遷移に使わない → SideNav を使う",
624
749
  "チェブロン・矢印を足さない(遷移アフォーダンスを持たせない。同一画面内の位置移動に見せる)",
625
750
  "WorkspaceShell の sectionNav にはこれを使う(SideNav を流用しない)",
626
- "固有幅・背景・境界を持たない(w-full)。パネル化・幅決定はシェル/利用側の責務"
751
+ "固有幅・背景・境界を持たない(w-full)。パネル化・幅決定はシェル/利用側の責務",
752
+ "orientation=\"vertical\"(既定)は縦積み目次。orientation=\"horizontal\" は Tabs アンダーバー式の横並び(ガイド・FAQ 等の長い静的ページのページ内ジャンプ、overflow-x-auto 対応)",
753
+ "sticky は内蔵しない。horizontal を貼り付ける場合は利用側が className=\"sticky top-14 …\" を付与し、ジャンプ先セクションに scroll-mt-* を付ける",
754
+ "IntersectionObserver は内包しない。activeKey は利用側が制御する(AnchorNav の新設は却下、本コンポーネントの variant で担う)"
627
755
  ]
628
756
  },
629
757
  {
@@ -637,20 +765,26 @@
637
765
  "あくまで枠。プロダクトのロゴ・タブ項目・ナビ項目・文言を焼き込まない。header / bottomTab は利用側(ec 層)が組み立てて渡す",
638
766
  "bottomTab を渡すと main の下余白(pb-20 相当)はシェルが管理する。ページ側で pb-20 を書かない(付け忘れ/二重がけの構造的防止)",
639
767
  "左右 padding は持たない(Container の責務)。中身は Section(全幅背景帯)+ Container(中央寄せ・左右余白)で組む",
640
- "管理画面は AdminShell、複数情報をまたぐ集中編集は WorkspaceShell、マイページ配下は MypageShell を使う"
768
+ "管理画面は AdminShell、複数情報をまたぐ集中編集は WorkspaceShell、マイページ配下は MypageShell を使う",
769
+ "a11y: DOM 先頭に SkipLink を標準内蔵し <main id> を制御できる(mainId 既定 main-content、SkipLink の飛び先と一致)。sr-only で視覚無影響。skipLink={false} で無効化。ページ側で手組みしない"
641
770
  ]
642
771
  },
643
772
  {
644
773
  "name": "WorkspaceShell",
645
774
  "path": "src/components/primitives/workspace-shell.tsx",
646
775
  "kind": "shell",
647
- "variants": [],
776
+ "variants": [
777
+ "headerLayout=start",
778
+ "headerLayout=center"
779
+ ],
648
780
  "rules": [
649
781
  "Focused Workspace(全画面集中編集)のシェル。編集ヘッダー(Header variant=back)+ 任意のセクションナビ + 編集本体で構成",
782
+ "headerLayout(既定 start): centerでヘッダーを左=戻る/中央=タイトル/右=primaryActionの3カラムgridに固定し、タイトルを真の中央に揃える(#112)。consumer 側の data-slot セレクタ上書きは不要",
650
783
  "グローバルナビ・パンくずを持たない(構造的に置けない)。集中を妨げる導線は出さない",
651
784
  "primaryActionはワークスペース全体の上位アクション(公開申請・承認依頼等)がある場合のみ。セクション/行単位の操作はコンテンツ内に置く",
652
785
  "標準の編集はAdminShellのStandard Page(Edit)(旧Form Page)。複雑・複数情報をまたぐ集中編集・没入執筆のみWorkspaceShellを使う",
653
- "sectionNavは編集内ナビ(アンカー/ステップ)のみ。PCでサイド表示・SPで非表示"
786
+ "sectionNavは編集内ナビ(アンカー/ステップ)のみ。PCでサイド表示・SPで非表示",
787
+ "a11y: DOM 先頭に SkipLink を標準内蔵し <main id> を制御できる(mainId 既定 main-content)。sr-only で視覚無影響。skipLink={false} で無効化"
654
788
  ]
655
789
  },
656
790
  {
@@ -664,12 +798,25 @@
664
798
  "あくまで枠。ステップ定義(名前・数)・文言・商品データを焼き込まない。steps / activeStep は利用側(ドメイン)が渡す",
665
799
  "グローバルナビ・BottomTabBar・パンくずを持たない(構造的に置けない)。離脱を誘う導線を出さず購入に集中させる",
666
800
  "bottomAction(StickyActionBar 等)を渡すと本文の下余白はシェルが管理する。ページ側で pb を書かない(付け忘れ/二重がけの構造的防止)",
667
- "左右 padding は持たない(Container の責務)。管理画面の複雑な集中編集は WorkspaceShell を使う(EC 購入導線=FunnelShell)"
801
+ "左右 padding は持たない(Container の責務)。管理画面の複雑な集中編集は WorkspaceShell を使う(EC 購入導線=FunnelShell)",
802
+ "a11y: DOM 先頭に SkipLink を標準内蔵し <main id> を制御できる(mainId 既定 main-content)。sr-only で視覚無影響。skipLink={false} で無効化"
668
803
  ]
669
804
  },
670
805
  {
671
806
  "name": "Header",
672
- "path": "src/components/primitives/header.tsx"
807
+ "path": "src/components/primitives/header.tsx",
808
+ "variants": [
809
+ "logo",
810
+ "logo-center",
811
+ "back",
812
+ "back-search"
813
+ ],
814
+ "rules": [
815
+ "variant=\"logo\" の PC 行(@[768px]+)では searchSlot で navItems と actions の間に常設検索を inline 配置できる(flex-1 max-w-[400px] で伸縮)。navItems 無し+searchSlot だけでも PC 行を描画する",
816
+ "SP 行に searchSlot は出さない。SP の常設検索は従来どおり bottomSlot で運用する",
817
+ "bottomSlot はヘッダー下段の全幅スロット(ProductDetailBar 等)。PC 常設検索の置き場に使わない(PC 二段ヘッダーになる)",
818
+ "actions(HeaderAction)はカート・マイページ等の本来リンクである導線には href を指定する。href 指定時は Button asChild + <a> で描画され、中クリック/新規タブ・リンクコピーが効く。onClick と併用可(両方付与される)"
819
+ ]
673
820
  },
674
821
  {
675
822
  "name": "AdminSideNav",
@@ -703,7 +850,8 @@
703
850
  "navItems で既定メニューを差し替え可、headerActions でヘッダー右アクションを差し替え可",
704
851
  "戻る導線(onBack)はパンくずの上に置く。onBack を渡すとシェルが main 内・パンくずより上に戻るボタンを描画する(backLabel で文言変更・既定『戻る』)。子コンテンツ内に戻るリンクを手書きしない",
705
852
  "タイトル直下の上位アクション(AI商品作成・PDF出力等)は h1 と同じ左端に左寄せする。右端フロートにしない",
706
- "既定値は props で差し替え可能で、骨格(Header + SideNav + Main)自体は他事業(ジョブボードの管理画面等)でも再利用できる"
853
+ "既定値は props で差し替え可能で、骨格(Header + SideNav + Main)自体は他事業(ジョブボードの管理画面等)でも再利用できる",
854
+ "a11y: DOM 先頭に SkipLink を標準内蔵し <main id> を制御できる(mainId 既定 main-content)。sr-only で視覚無影響。skipLink={false} で無効化"
707
855
  ]
708
856
  },
709
857
  {
@@ -724,7 +872,8 @@
724
872
  "サイドナビは既定で ec/_mypage-menu-data の mypageMenuGroups を使用。activeMenu で現在ページを強調する",
725
873
  "既定値は props で差し替え可能(menuGroups / breadcrumbs / bottomNavItems / headerActions)で、骨格(ヘッダー+2カラム+BottomTabBar)自体は他事業(ジョブボードのマイページ等)でも再利用できる",
726
874
  "breadcrumbs 省略時は「ホーム > {ユーザー}さまのマイページ > {title}」を自動生成する",
727
- "マイページトップ(Dashboard)はメインカラムを白背景で持たずセクションごとにカード化する別パターンなので、この shell を使わない"
875
+ "マイページトップ(Dashboard)はメインカラムを白背景で持たずセクションごとにカード化する別パターンなので、この shell を使わない",
876
+ "a11y: DOM 先頭に SkipLink を標準内蔵し <main id> を制御できる(mainId 既定 main-content)。sr-only で視覚無影響。skipLink={false} で無効化"
728
877
  ]
729
878
  },
730
879
  {
@@ -788,6 +937,9 @@
788
937
  "favorite",
789
938
  "discount-badge",
790
939
  "rating"
940
+ ],
941
+ "rules": [
942
+ "captionは規格・仕様の短い自由記述(例: \"1kg / 冷蔵\")。価格表示の直下にtypo-body-xs / Text-Medium-Emphasisで表示。tags(配送方法等のenum variant)とは別物で代替不可"
791
943
  ]
792
944
  },
793
945
  {
@@ -884,7 +1036,9 @@
884
1036
  "path": "src/components/ec/product-list-item.tsx",
885
1037
  "category": "display",
886
1038
  "rules": [
887
- "カート/注文履歴/レビュー variant を持つ商品リスト行"
1039
+ "カート/注文履歴/レビュー variant を持つ商品リスト行",
1040
+ "captionは規格・仕様の短い自由記述(例: \"1kg / 冷蔵\")。価格表示の直下にtypo-body-xs / Text-Medium-Emphasisで表示。tags(配送方法等のenum variant)とは別物",
1041
+ "subtotal/subtotalLabel(既定\"小計\")はcart variant専用。数量セレクタ行の右側(収まらなければ下に折り返し)に¥{カンマ区切り}で表示。BtoB/法人ECのロット購入等、商品ごとの単価×数量の内訳を明示したい場合に使う"
888
1042
  ]
889
1043
  }
890
1044
  ]
@@ -527,7 +527,7 @@
527
527
  "category": "component",
528
528
  "pattern": "<input type=\"date\"|<input type='date'",
529
529
  "message": "input type='date' のネイティブ日付ピッカー禁止",
530
- "fix": "<Popover> + <Calendar> でDS準拠の日付ピッカーを組む"
530
+ "fix": "実装済みの正解形 <DatePicker />(日付)/ <DateTimePicker />(日時)を使う(内部で Popover+Calendar を DS 意匠で組み済み・M月D日(曜日)表記・日本語カレンダー)。特殊要件で手組みが要る場合のみ <Popover> + <Calendar>"
531
531
  },
532
532
  {
533
533
  "id": "R51",
@@ -542,6 +542,21 @@
542
542
  "category": "component",
543
543
  "message": "管理画面のテーブルをui/tableで組まない",
544
544
  "fix": "<DataTable> を使う(ソート・選択行・アクションメニュー対応)"
545
+ },
546
+ {
547
+ "id": "R54",
548
+ "severity": "error",
549
+ "category": "component",
550
+ "pattern": "<input type=\"file\"|<input type='file'",
551
+ "message": "ネイティブ <input type='file'> を直接使わない",
552
+ "fix": "汎用の添付(PDF/CSV/画像混在)は <FileInput />(foundations)を使う。プレビュー付きの画像管理(並び替え・複数サムネイル)は <ImageUploader />(primitives)を使う"
553
+ },
554
+ {
555
+ "id": "R55",
556
+ "severity": "warning",
557
+ "category": "component",
558
+ "message": "画像・メディアの上に載せる操作ボタンを rgba 直書きの半透過下地で手組みしない",
559
+ "fix": "<Button variant='overlay'>(半透過白 Surface-Overlay-Light + shadow-md + backdrop-blur-sm)を使う。ImageCarousel 矢印と同系の意匠。円形は size='icon' + className='rounded-full'"
545
560
  }
546
561
  ],
547
562
  "accessibility": {
@@ -569,6 +584,7 @@
569
584
  "typography": {
570
585
  "rule": "必ず typo-* クラスを使用。text-sm font-bold 等の個別指定禁止。",
571
586
  "classes": [
587
+ { "class": "typo-heading-4xl", "size": "32px", "weight": "bold" },
572
588
  { "class": "typo-heading-3xl", "size": "28px", "weight": "bold" },
573
589
  { "class": "typo-heading-2xl", "size": "24px", "weight": "bold" },
574
590
  { "class": "typo-heading-xl", "size": "21px", "weight": "bold" },