@cakejp/design-system 0.6.0 → 0.7.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.
package/CHANGELOG.md CHANGED
@@ -7,12 +7,52 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ---
9
9
 
10
+ ## [Unreleased]
11
+
12
+ ---
13
+
14
+ ## [0.7.0] - 2026-06-19
15
+
16
+ ### ✨ Added
17
+
18
+ - **IconBadge**(foundations・新規): 丸いアイコンバッジ(`md`=44px / `lg`=72px、内部アイコン 20px / 38px)を部品化。淡いアクセント背景(`Surface-Accent-Primary-Light`)の円にアイコンを `currentColor`(`Object-Accent-Primary`)で中央配置。**外側 margin を持たない**設計で、`Card` の `flex-col gap-4`(16px) との「縦余白の二重がけ」を構造的に防ぐ。`import { IconBadge } from "@cakejp/design-system"` で利用可。Storybook に md/lg 両サイズ+Card 内使用例を追加
19
+ - **Container / Section**(primitives・新規): ページレイアウトの責務を分離する薄い2部品。`Container`(`size`: page/narrow/wide/fluid、`gutter`: default/tight/none)が**左右余白と中央寄せの唯一の担い手**、`Section`(`spacing`: sm/md/lg/xl、`background`: none/subtle/accent-subtle)が**全幅の縦リズムと背景帯**を持つ。背景は Section・左右 padding は Container と分担することで「背景帯は画面端まで・コンテンツは中央寄せ」を**左右 padding の二重がけなし**で成立させる(consumer の `.section`/`.section-inner` 手書きで起きていた構造バグの恒久対策)。Storybook に推奨パターン例を追加
20
+ - **SectionHeader**: `align="center"` と `eyebrow` スロットを追加。ランディング/ガイド系の中央寄せ大見出し(Eyebrow Badge + Title + Subtitle)に対応。`align` 無指定は `start`(従来の左寄せ+もっと見る)で**既存の使い方は無変更**
21
+ - **セクション余白トークン `--Space-Section-*`**: `xs`〜`2xl`(32/40/48/56/64/80px・8の倍数)を `preset.css` / `preset-standalone.css`(`./preset-standalone` エントリ)/ `tokens.json`(`spacing.section`) に追加。`spacing.scale`(最大24px)を超えるセクション縦リズム用の意味的トークンで、Tailwind を使わない入口でも参照可能。生CSS/HTML モックの rem 直書きの置換先になる
22
+
23
+ ### 🛡 Internal
24
+
25
+ - **Card の縦間隔ルールを明文化(二重がけ防止)**: 子要素の縦間隔は Card 本体の `flex-col gap-4`(16px) が一括所有し、直下の子に `margin-top/bottom`・`space-y-*` を足さない旨を `contracts/components.json` の Card ルールに追記(正典)。`AGENTS.md` の「書く前ゲート」にも同趣旨を反映
26
+ - **R18c(補助 lint)**: JSX 直書きの `<Card>` 直下の子の `mt-/mb-/my-/space-y-*` を warning で検出。`contracts/rules.json` + `scripts/lint-scratch.sh` に実装(`CardContent` 等ネストの子は誤検知しないガード込み)し、vitest 回帰テストを追加。別 CSS/module.css の margin は正規表現では検出不可な旨を `note` に明記(本命は上記 Card ルールと IconBadge)
27
+ - **生CSS の rem 直書き lint(R11b/R12b)**: `padding`/`gap`(`padding-inline/block` 等の複合プロパティ含む)の rem 直書きを `contracts/rules.json` に追加し、`lint-scratch.sh` に DS 自身の `src/**/*.css`(および引数で渡した CSS)を対象とした CSS スキャンを配線(`var()` 参照・カスタムプロパティ定義は除外)。R11/R12 は Tailwind 任意値 `[Npx]` しか見ずすり抜けていた経路を補強し、vitest 回帰テストを追加。限界(consumer リポジトリの CSS には届かない)を `note` に明記
28
+
29
+ ### 🐛 Fixed
30
+
31
+ - **Toast(Sonner)**: ダークモードで状態トースト(success/error/warning/info)の説明文がほぼ不可視になる問題を修正。背景は primitive の明色で固定なのに説明文が semantic(ダークで白に反転)だったため。説明文・cancel ボタンをモード非依存の primitive 色に固定し、error の見出し・アイコンの低コントラストも同時に解消
32
+
33
+ ### 🎨 Changed
34
+
35
+ - **角丸の統一(#18 シャープ化の追随)**: ProductCard カートボタン / CouponCard CTA / ReviewCard「参考になった」/ Toast(Sonner) アクションボタンの角丸を Button のサイズ対応に統一(`rounded-xl`→`lg`、`rounded-[18px]`→`xl`)。#18 が Button 本体をシャープ化した際に取り残されたボタン風 CTA のコピーを追随させたもの
36
+
37
+ ### 🛡 Internal
38
+
39
+ - **角丸・シャドウのルールをトークン実態と整合**: `rounded-md`(8px)/`rounded-xl`(14px) と `shadow-md/lg` は preset.css/tokens.json の正規トークンのため許可に変更(禁止は `rounded-3xl/4xl`・任意値・`shadow-xl/2xl` のみに)。SVG ブランド色(fill/stroke 内)と %・fr・vw のコンテナ比率値の例外を明文化(contracts/rules.json AI7 改訂・R53 新設・R8/R11/R12 / lint-scratch.sh / CLAUDE.md・CLAUDE_DEV.md)
40
+ - **lint-scratch に `--components` ティア追加**: foundations/primitives/ec のコンポーネント定義にトークン系チェック(HEX/任意px/角丸/シャドウ)を適用。`npm run check`・pre-commit・PostToolUse hook に配線。例外は `lint-scratch-allow` コメントで明示
41
+ - **tokens.json を preset.css と同期**: radius.2xl〜4xl 追加、shadow.* の値ドリフト解消、overlay 追加
42
+ - 任意値の同値正規化(視覚変化なし): Button xl `rounded-[14px]`→`rounded-xl`、Tooltip 矢印 `rounded-[2px]`→`rounded-xs`、BottomTabBar `rounded-[18px]`→`rounded-full`、SideNav `pl-[14px]`→`pl-3.5`、AdminLayout `pl-[72px]`→`pl-18` ほか
43
+
44
+ ---
45
+
10
46
  ## [0.6.0] - 2026-06-11
11
47
 
12
48
  ### ✨ Added
13
49
 
14
50
  - **ListItem**: インタラクティブ(`href` / `onClick`)な行に hover 背景(`Surface-Tertiary`)と focus-visible リング(`Focus-High-Emphasis`)を追加。`onClick` のみの場合は `role="button"` + Enter / Space キー操作にも対応。表示専用行(href/onClick なし)は変化なし (#21)
15
51
 
52
+ ### 🎨 Changed
53
+
54
+ - **Button**: 角丸を全サイズで -4px してシャープ化(よりキリッとした印象に) (#18)
55
+
16
56
  ### 🐛 Fixed
17
57
 
18
58
  - **border(全コンポーネント)**: 色指定のない `border` を持つ 16 コンポーネントに border 色を明示し、Tailwind v4 のグローバル base reset 非依存に。消費側がリセットを取り込まないと罫線が要素の文字色へ化ける問題を防止。回帰防止 lint(`scripts/check-border-color.mjs`)と「`dist/index.css` import 必須」の明記を追加 (#20)
@@ -23,6 +63,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
23
63
 
24
64
  - **lint**: `check-border-color` が CVA 定義内の border も走査するよう拡張(色なし border の回帰防止を強化) (#24)
25
65
  - **Storybook**: 「Hostile ctx」検出ツールが Radix Portal(Dialog/Popover 等)の継承漏れも検出できるよう body へのスタイル適用に対応 (#24)
66
+ - **docs**: CLAUDE.md を利用者向け / 開発者向け(CLAUDE_DEV.md)に分離 (#17)
26
67
 
27
68
  ---
28
69
 
package/CLAUDE.md CHANGED
@@ -31,9 +31,10 @@ PdM や社長が AI(Claude 等)で HTML モックを作る際、このパッ
31
31
  | 追加しようとしているもの | DSで確認すること |
32
32
  |------------------------|----------------|
33
33
  | `::before` / `::after` で装飾(色付きバー・ドット・矢印等) | SectionHeader, Chip, Badge, ListItem の variants |
34
- | カスタムカラー(`rgba(...)` / `#xxxxxx` / ハードコード) | `tokens.json` のトークン名を使う。存在しないトークンは使わない |
35
- | カスタムシャドウ(`box-shadow: ...`) | `tokens.json` の `shadow.*` を使う |
36
- | カスタムボーダー半径(`border-radius: ...px`) | `tokens.json` の `radius.*` を使う |
34
+ | カスタムカラー(`rgba(...)` / `#xxxxxx` / ハードコード) | `tokens.json` のトークン名を使う。存在しないトークンは使わない。例外: サードパーティブランドロゴの SVG `fill=`/`stroke=` 内のみ HEX 直書き可(出典コメント必須) |
35
+ | カスタムシャドウ(`box-shadow: ...`) | `shadow-xs/sm/md/lg`(preset.css が DS 値に再定義済み)または用途別 `shadow-menu/tooltip/dialog/modal/overlay`。`shadow-xl/2xl` 禁止。オーバーレイの `md/lg` は正規仕様 |
36
+ | カスタムボーダー半径(`border-radius: ...px` / `rounded-[Npx]`) | `rounded-xs/sm/md/lg/xl/2xl/full` のみ(= `tokens.json` の `radius.*`、`--radius`=10px 基準で 2/6/8/10/14/18px)。`rounded-3xl` 以上・任意値は禁止 |
37
+ | コンテナ比率の任意値(`px-[22.25%]` 等) | 4px グリッドは px 値のみ対象。%・fr・vw は理由コメント付きで許可 |
37
38
  | カスタムフォントサイズ・ウェイト | `tokens.json` の `typography.*` を使う |
38
39
  | 新しい `<div>` ラッパーでレイアウト構造を作る | Card, Section, Stack 等のコンポーネントに置き換えられないか確認 |
39
40
  | 生の `<button>` `<input>` `<select>` `<textarea>` `<table>` | DS の Button / Input / Select / Textarea / DataTable を使う |
@@ -4,10 +4,10 @@
4
4
  "version": "0.1.0",
5
5
  "description": "全コンポーネントの構造化定義。バリアント・アクセシビリティ要件・使用ルールを機械可読形式で管理。",
6
6
  "counts": {
7
- "foundations": 46,
8
- "primitives": 34,
7
+ "foundations": 47,
8
+ "primitives": 36,
9
9
  "ec": 23,
10
- "total": 103
10
+ "total": 106
11
11
  }
12
12
  },
13
13
  "foundations": [
@@ -109,7 +109,8 @@
109
109
  "CardFooter"
110
110
  ],
111
111
  "rules": [
112
- "paddingはCard本体のp-4で一括管理。全幅コンテンツは-mx-4で突き破る"
112
+ "paddingはCard本体のp-4で一括管理。全幅コンテンツは-mx-4で突き破る",
113
+ "子要素の縦間隔はCard本体のflex-col gap-4(16px)で一括管理。直下の子にmargin-top/bottom/space-yを足さない(gapと二重がけになり間延びする)。丸アイコンはIconBadgeを使う(外側marginを持たない)"
113
114
  ]
114
115
  },
115
116
  {
@@ -185,6 +186,20 @@
185
186
  "name": "HoverCard",
186
187
  "path": "src/components/foundations/hover-card.tsx"
187
188
  },
189
+ {
190
+ "name": "IconBadge",
191
+ "path": "src/components/foundations/icon-badge.tsx",
192
+ "variants": [
193
+ "md",
194
+ "lg"
195
+ ],
196
+ "rules": [
197
+ "丸アイコンバッジ(md=44px/lg=72px)。アイコンを淡いアクセント背景の円で囲む装飾要素",
198
+ "外側marginを持たない。縦間隔は親Cardのflex-col gap-4(16px)に委ねる(二重がけ防止)",
199
+ "アイコン色はcurrentColor(--Object-Accent-Primary)を継承。中のアイコンにcolorを渡さない",
200
+ "アイコンサイズはバッジが固定(md=20px/lg=38px)。アイコン側にsizeを渡さない"
201
+ ]
202
+ },
188
203
  {
189
204
  "name": "Input",
190
205
  "path": "src/components/foundations/input.tsx",
@@ -526,11 +541,41 @@
526
541
  "flex"
527
542
  ]
528
543
  },
544
+ {
545
+ "name": "Container",
546
+ "path": "src/components/primitives/container.tsx",
547
+ "variants": [
548
+ "size: page | narrow | wide | fluid",
549
+ "gutter: default | tight | none"
550
+ ],
551
+ "rules": [
552
+ "ページ最大幅と左右paddingの唯一の担い手。これを使う親(Section等)は自身で左右paddingを持たない(二重がけ防止)",
553
+ "縦余白・背景色は持たない(Sectionの責務)"
554
+ ]
555
+ },
556
+ {
557
+ "name": "Section",
558
+ "path": "src/components/primitives/section.tsx",
559
+ "variants": [
560
+ "spacing: sm | md | lg | xl",
561
+ "background: none | subtle | accent-subtle"
562
+ ],
563
+ "rules": [
564
+ "全幅の縦リズム+背景帯。左右paddingを持たない(左右余白はContainerが唯一の担い手)",
565
+ "背景色はSection(全幅)が持ち中央寄せはContainerが持つ → 背景帯は画面端まで・コンテンツは中央寄せが二重がけなしで成立",
566
+ "縦余白はSP/PCペアで --Space-Section-* トークンを消費(rem直書き撲滅)"
567
+ ]
568
+ },
529
569
  {
530
570
  "name": "SectionHeader",
531
571
  "path": "src/components/primitives/section-header.tsx",
572
+ "variants": [
573
+ "size: 3xl | 2xl | xl | lg | md | sm",
574
+ "align: start | center"
575
+ ],
532
576
  "rules": [
533
- "タイトル+もっと見るボタンをCardTitle+Button手書き禁止。SectionHeaderを使う"
577
+ "タイトル+もっと見るボタンをCardTitle+Button手書き禁止。SectionHeaderを使う",
578
+ "中央寄せ大見出し(ランディング/ガイド系)は align=\"center\" を使う。eyebrow プロップに Badge 等を載せられる。手書きの中央寄せ見出し禁止"
534
579
  ]
535
580
  },
536
581
  {
@@ -98,8 +98,8 @@
98
98
  "severity": "warning",
99
99
  "category": "color",
100
100
  "pattern": "#[0-9A-Fa-f]{6}",
101
- "excludes": [".stories.", ".css", "shadow", "components/foundations/", "components/primitives/", "components/ec/"],
102
- "message": "HEXハードコード禁止",
101
+ "excludes": [".stories.", ".css", "shadow", "fill=\"", "stroke=\"", "components/foundations/", "components/primitives/", "components/ec/"],
102
+ "message": "HEXハードコード禁止(例外: サードパーティブランドロゴの SVG fill/stroke — 例 Amazon #FF9900、Google 4色。出典コメント推奨)",
103
103
  "fix": "var(--Brand-Cake-Orange) 等セマンティックトークンを使う"
104
104
  },
105
105
  {
@@ -132,16 +132,45 @@
132
132
  "severity": "warning",
133
133
  "category": "spacing",
134
134
  "pattern": "p-\\[[0-9]*[13579]px\\]|m-\\[[0-9]*[13579]px\\]",
135
- "message": "4pxグリッド外の余白値禁止",
136
- "fix": "p-3(12px)等4の倍数のTailwindクラスを使う"
135
+ "message": "4pxグリッド外の余白値禁止(対象は px 任意値のみ。%・fr・vw 等のコンテナ比率はレイアウト都合で許可=理由コメント必須)",
136
+ "fix": "p-3(12px)等4の倍数のTailwindクラスを使う。やむを得ない固有値は lint-scratch-allow コメントで理由を明記"
137
137
  },
138
138
  {
139
139
  "id": "R12",
140
140
  "severity": "warning",
141
141
  "category": "spacing",
142
142
  "pattern": "gap-\\[[0-9]*[13579]px\\]",
143
- "message": "4pxグリッド外のgap値禁止",
144
- "fix": "gap-1.5(6px)or gap-2(8px)"
143
+ "message": "4pxグリッド外のgap値禁止(対象は px 任意値のみ)",
144
+ "fix": "gap-1.5(6px)or gap-2(8px)。Figma 由来のやむを得ない固有値は lint-scratch-allow コメントで理由を明記"
145
+ },
146
+ {
147
+ "id": "R11b",
148
+ "severity": "warning",
149
+ "category": "spacing",
150
+ "target": "css",
151
+ "pattern": "(padding|padding-(top|bottom|left|right|inline|block)[a-z-]*)\\s*:\\s*[0-9.]+rem",
152
+ "message": "生CSSで padding を rem 直書き禁止(R11/R12 の Tailwind 任意値検査をすり抜ける経路)",
153
+ "fix": "spacing トークン(var(--spacing-*))を使う。セクション縦余白は var(--Space-Section-*) を使う",
154
+ "note": "limitation: lint-scratch.sh の CSS スキャンは引数で指定したCSS、または引数なし実行時の DS 自身の src/**/*.css が対象。consumer リポジトリの CSS(実バグの front-site.css 等)には届かない=consumer が DS lint を導入しない限り補助どまり。カスタムプロパティ定義(--Foo: 2rem)はトークン定義なので対象外"
155
+ },
156
+ {
157
+ "id": "R12b",
158
+ "severity": "warning",
159
+ "category": "spacing",
160
+ "target": "css",
161
+ "pattern": "gap\\s*:\\s*[0-9.]+rem",
162
+ "message": "生CSSで gap を rem 直書き禁止",
163
+ "fix": "spacing トークン(var(--spacing-*))を使う",
164
+ "note": "limitation: R11b と同様、DS 自身の src/**/*.css のみが対象。var() 参照は除外"
165
+ },
166
+ {
167
+ "id": "R53",
168
+ "severity": "warning",
169
+ "category": "elevation",
170
+ "pattern": "shadow-(xl|2xl)\\b",
171
+ "excludes": [".stories."],
172
+ "message": "DS定義外シャドウ禁止(shadow-xl/2xl)",
173
+ "fix": "shadow-xs/sm/md/lg を使う(preset.css が --shadow-md/lg を DS 値に再定義済み)。オーバーレイは用途別トークン shadow-menu/tooltip/dialog/modal/overlay を推奨。フローティング UI の強い影(md/lg)は意図された正規仕様"
145
174
  },
146
175
  {
147
176
  "id": "R13",
@@ -200,6 +229,16 @@
200
229
  "message": "CardのpaddingをCard本体とchildで分離しない",
201
230
  "fix": "Card本体が p-4 で管理。全幅コンテンツは -mx-4 で突き破る"
202
231
  },
232
+ {
233
+ "id": "R18c",
234
+ "severity": "warning",
235
+ "category": "spacing",
236
+ "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/"],
238
+ "message": "Card直下の子に mt-/mb-/my-/space-y- を足さない(縦間隔はCard本体の flex-col gap-4=16px が一括管理。二重がけで間延びする)",
239
+ "fix": "余白クラスを外し Card の gap-4 に委ねる。丸アイコンは IconBadge を使う(外側marginを持たない)",
240
+ "note": "limitation: この正規表現はJSXソース文字列のみを見る。別CSS/module.cssファイルに書かれた margin(実バグの主因)は検出不可。あくまでJSXにTailwindで直書きした場合の補助で、本命は components.json の Card 縦間隔ルール(正典)と IconBadge 部品化"
241
+ },
203
242
  {
204
243
  "id": "R19",
205
244
  "severity": "error",
@@ -454,10 +493,10 @@
454
493
  "id": "AI7",
455
494
  "severity": "warning",
456
495
  "category": "ai-pattern",
457
- "pattern": "rounded-md\\b|rounded-xl\\b|rounded-3xl\\b",
458
- "excludes": [".stories.", "components/foundations/", "components/primitives/", "components/ec/"],
459
- "message": "AI生成パターン: DS定義外の角丸禁止(rounded-md/xl/3xl)",
460
- "fix": "DS定義の角丸のみ使用する"
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 コメントで理由を明記"
461
500
  },
462
501
  {
463
502
  "id": "R44",