@cakejp/design-system 0.11.0 → 0.13.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 +85 -1
- package/CLAUDE.md +22 -1
- package/README.md +48 -0
- package/UPDATING.md +9 -0
- package/bin/check-duplicates.mjs +256 -0
- package/bin/exports-parser.mjs +54 -0
- package/bin/init.js +11 -0
- package/contracts/components.json +395 -37
- package/contracts/composition.json +10 -7
- package/contracts/rules.json +21 -3
- package/dist/index.css +1 -1
- package/dist/index.js +6134 -3475
- package/dist/types/components/ec/admin-shell.d.ts +39 -2
- package/dist/types/components/ec/mypage-shell.d.ts +10 -1
- package/dist/types/components/ec/product-card.d.ts +3 -1
- package/dist/types/components/ec/product-list-item.d.ts +8 -1
- package/dist/types/components/foundations/alert.d.ts +5 -1
- package/dist/types/components/foundations/button.d.ts +1 -1
- package/dist/types/components/foundations/card.d.ts +36 -2
- package/dist/types/components/foundations/chip-variants.d.ts +17 -0
- package/dist/types/components/foundations/field.d.ts +81 -0
- package/dist/types/components/foundations/file-input.d.ts +75 -0
- package/dist/types/components/foundations/icon-badge.d.ts +2 -2
- package/dist/types/components/foundations/input.d.ts +11 -1
- package/dist/types/components/foundations/radio-group.d.ts +12 -2
- package/dist/types/components/foundations/skip-link.d.ts +39 -0
- package/dist/types/components/foundations/textarea.d.ts +11 -1
- package/dist/types/components/primitives/chat-composer.d.ts +87 -0
- package/dist/types/components/primitives/chip.d.ts +2 -7
- package/dist/types/components/primitives/content-carousel.d.ts +58 -0
- package/dist/types/components/primitives/date-picker.d.ts +44 -0
- package/dist/types/components/primitives/error-state.d.ts +43 -16
- package/dist/types/components/primitives/funnel-shell.d.ts +12 -1
- package/dist/types/components/primitives/header.d.ts +15 -1
- package/dist/types/components/primitives/image-input.d.ts +119 -0
- package/dist/types/components/primitives/section-header.d.ts +9 -2
- package/dist/types/components/primitives/section-nav.d.ts +28 -2
- package/dist/types/components/primitives/section.d.ts +35 -2
- package/dist/types/components/primitives/share-buttons.d.ts +8 -2
- package/dist/types/components/primitives/standard-page-shell.d.ts +11 -1
- package/dist/types/components/primitives/timeline.d.ts +23 -0
- package/dist/types/components/primitives/workspace-shell.d.ts +21 -1
- package/dist/types/index.d.ts +80 -4
- package/dist/types/lib/pagination-range.d.ts +16 -0
- package/dist/types/lib/use-value-length.d.ts +31 -0
- package/package.json +2 -1
- package/src/preset-standalone.css +322 -4
- package/src/preset.css +17 -0
- package/src/styles/semantic.css +7 -0
- package/src/styles/typography.css +15 -1
- package/templates/AGENTS.md +11 -0
- package/templates/CLAUDE.md +11 -0
- package/tokens.json +18 -2
|
@@ -4,11 +4,14 @@
|
|
|
4
4
|
"version": "0.1.0",
|
|
5
5
|
"description": "全コンポーネントの構造化定義。バリアント・アクセシビリティ要件・使用ルールを機械可読形式で管理。",
|
|
6
6
|
"kind": "kind:\"shell\" は複数ページで再利用されるレイアウト枠(AdminShell / WorkspaceShell / MypageShell 等)。無印は部品コンポーネント。固有ページを組むときは該当 shell から始める。src/components/pages/ 配下のストーリーは特定ページ専用・非配布のため contracts の対象外。",
|
|
7
|
+
"exportNaming": "name は原則そのまま @cakejp/design-system から import できる export 名。例外は機械可読に印を付ける — exported:false=name は実装ファイル/グループ名で import できない(実 export は subcomponents 側。例: CheckboxCard → CheckboxCardGroup / CheckboxCardItem)、exportedAs=別名で export される(例: FormField → CakeFormField)、deprecatedAliases=互換のため残す旧 export 名(新規利用禁止)。この対応は __tests__/contracts-export-integrity.test.ts が src/index.ts と突き合わせて固定し、bin/check-duplicates.mjs の照合対象もこの規約に従う。",
|
|
8
|
+
"formBinding": "react-hook-form との繋ぎ方。formBinding:\"register\"=ネイティブ form control に props/ref を透過するので {...register(\"name\")} を直接 spread できる(Input / Textarea)。formBinding:\"controller\"=Radix ベースで ref が <button> 等に着地する、または値が Date/File など非文字列のため Controller の field.value / field.onChange に繋ぐ。formBinding:\"layout\"=値を持たないレイアウト部品でバインド対象ではない(Field / Form / FormField / ProductOption)。formBinding:\"none\"=値は扱うが単一フィールドのバインド対象ではない自己完結フォーム・複合ウィジェット(DataTable / SearchBar / ReviewForm)。この切り分けは __tests__/react-hook-form-integration.test.tsx が実挙動で固定する(issue #151 / #152)。",
|
|
7
9
|
"counts": {
|
|
8
|
-
"foundations":
|
|
9
|
-
"primitives":
|
|
10
|
+
"foundations": 50,
|
|
11
|
+
"primitives": 47,
|
|
10
12
|
"ec": 24,
|
|
11
|
-
"total":
|
|
13
|
+
"total": 121,
|
|
14
|
+
"note": "counts は各ティアの実装ファイル数(scripts/check-drift.sh が src/components/<tier>/*.tsx と突き合わせる)。subcomponents / deprecatedAliases は含まない。"
|
|
12
15
|
}
|
|
13
16
|
},
|
|
14
17
|
"foundations": [
|
|
@@ -26,9 +29,22 @@
|
|
|
26
29
|
{
|
|
27
30
|
"name": "Alert",
|
|
28
31
|
"path": "src/components/foundations/alert.tsx",
|
|
32
|
+
"subcomponents": [
|
|
33
|
+
"AlertTitle",
|
|
34
|
+
"AlertDescription"
|
|
35
|
+
],
|
|
29
36
|
"variants": [
|
|
30
|
-
"
|
|
31
|
-
"
|
|
37
|
+
"success",
|
|
38
|
+
"info",
|
|
39
|
+
"error",
|
|
40
|
+
"warning",
|
|
41
|
+
"inline-info",
|
|
42
|
+
"inline-caution",
|
|
43
|
+
"inline-warning"
|
|
44
|
+
],
|
|
45
|
+
"rules": [
|
|
46
|
+
"bordered variant(success/info/error/warning)は title/description/icon/action の prop-based API に対応(旧 Banner 相当)",
|
|
47
|
+
"inline variant(inline-info/inline-caution/inline-warning)も同じ prop-based API に対応(#109)。フォーム内・セクション内の軽量な補足情報用。アイコンは20pxで自動選択"
|
|
32
48
|
]
|
|
33
49
|
},
|
|
34
50
|
{
|
|
@@ -75,7 +91,8 @@
|
|
|
75
91
|
"ghost",
|
|
76
92
|
"link",
|
|
77
93
|
"inverse",
|
|
78
|
-
"ghost-inverse"
|
|
94
|
+
"ghost-inverse",
|
|
95
|
+
"overlay"
|
|
79
96
|
],
|
|
80
97
|
"sizes": [
|
|
81
98
|
"xs",
|
|
@@ -89,7 +106,12 @@
|
|
|
89
106
|
"aria-label必須(アイコンのみの場合)"
|
|
90
107
|
],
|
|
91
108
|
"rules": [
|
|
92
|
-
"<button>を直接使わない。必ずButtonコンポーネントを使う"
|
|
109
|
+
"<button>を直接使わない。必ずButtonコンポーネントを使う",
|
|
110
|
+
"高さは size='default'=44px(h-11) / xs=24px / sm=32px / lg=48px / xl=56px / hero=min 56px。default はフォーム入力コントロール(Input / SelectTrigger default / DatePicker trigger)と同じ 44px なので、入力行にボタンを並置しても揃う",
|
|
111
|
+
"⚠️ variant='secondary' はブランドアクセント意匠(Surface-Accent-Primary-Light地+Brand-Cake-Orange文字)。Material/Bootstrap/shadcn の secondary(グレー・控えめ)とは別物なので、他DSの感覚で選ばない",
|
|
112
|
+
"「戻る」「キャンセル」「閉じる」「スキップ」「あとで」等の後退・中立アクションは variant='tertiary'(Surface-Tertiary地+Text-High-Emphasis文字のニュートラルなグレー)を使う。主CTAの隣に置く2番目のボタンでも、役割が後退なら secondary ではなく tertiary",
|
|
113
|
+
"variant='secondary' を使うのは、主CTAと別方向の“前進”を促す副CTAのとき(例: 主='購入する' に対し 副='サンプルを見る')",
|
|
114
|
+
"variant='overlay'は画像・メディアの上に載せる操作ボタン専用(半透過白のSurface-Overlay-Light下地+shadow-md+backdrop-blur-sm)。ImageCarousel矢印と同系の意匠。size='icon'+className='rounded-full'で円形にできる"
|
|
93
115
|
]
|
|
94
116
|
},
|
|
95
117
|
{
|
|
@@ -109,22 +131,42 @@
|
|
|
109
131
|
"CardContent",
|
|
110
132
|
"CardFooter"
|
|
111
133
|
],
|
|
134
|
+
"variants": {
|
|
135
|
+
"surface": [
|
|
136
|
+
"default",
|
|
137
|
+
"primary"
|
|
138
|
+
]
|
|
139
|
+
},
|
|
112
140
|
"rules": [
|
|
113
141
|
"paddingはCard本体のp-4で一括管理。全幅コンテンツは-mx-4で突き破る",
|
|
114
|
-
"子要素の縦間隔はCard本体のflex-col gap-4(16px)で一括管理。直下の子にmargin-top/bottom/space-yを足さない(gapと二重がけになり間延びする)。丸アイコンはIconBadgeを使う(外側marginを持たない)"
|
|
142
|
+
"子要素の縦間隔はCard本体のflex-col gap-4(16px)で一括管理。直下の子にmargin-top/bottom/space-yを足さない(gapと二重がけになり間延びする)。丸アイコンはIconBadgeを使う(外側marginを持たない)",
|
|
143
|
+
"surface='default'(既定)は --card-surface(親から伝播したサーフェス文脈)→無ければ --card(Surface-Secondary)。surface='primary'は文脈に関係なく白(Surface-Primary)で固定する",
|
|
144
|
+
"Section background='subtle'|'accent-subtle' と、地がSurface-Secondaryのシェル(AdminShell / WorkspaceShell / FunnelShell)の配下では --card-surface が伝播するため、Card は surface 未指定のまま自動で白になる(surface='primary' の明示指定は従来通り有効で優先)",
|
|
145
|
+
"DSのSectionを使わない自前のグレー地では、親要素に className='[--card-surface:var(--Surface-Primary)]' を宣言すれば配下Cardが白になる(darkにも配慮するなら dark:[--card-surface:var(--Surface-Secondary)] を併記)。1枚だけ地に馴染ませたいときは className='bg-card' で上書きする"
|
|
115
146
|
]
|
|
116
147
|
},
|
|
117
148
|
{
|
|
118
149
|
"name": "CheckboxCard",
|
|
119
|
-
"path": "src/components/foundations/checkbox-card.tsx"
|
|
150
|
+
"path": "src/components/foundations/checkbox-card.tsx",
|
|
151
|
+
"formBinding": "controller",
|
|
152
|
+
"exported": false,
|
|
153
|
+
"subcomponents": [
|
|
154
|
+
"CheckboxCardGroup",
|
|
155
|
+
"CheckboxCardItem"
|
|
156
|
+
]
|
|
120
157
|
},
|
|
121
158
|
{
|
|
122
159
|
"name": "CheckboxGroup",
|
|
123
|
-
"path": "src/components/foundations/checkbox-group.tsx"
|
|
160
|
+
"path": "src/components/foundations/checkbox-group.tsx",
|
|
161
|
+
"formBinding": "controller",
|
|
162
|
+
"subcomponents": [
|
|
163
|
+
"CheckboxGroupItem"
|
|
164
|
+
]
|
|
124
165
|
},
|
|
125
166
|
{
|
|
126
167
|
"name": "Checkbox",
|
|
127
168
|
"path": "src/components/foundations/checkbox.tsx",
|
|
169
|
+
"formBinding": "controller",
|
|
128
170
|
"accessibility": [
|
|
129
171
|
"必ずLabelと紐付ける"
|
|
130
172
|
]
|
|
@@ -148,6 +190,7 @@
|
|
|
148
190
|
{
|
|
149
191
|
"name": "DataTable",
|
|
150
192
|
"path": "src/components/foundations/data-table.tsx",
|
|
193
|
+
"formBinding": "none",
|
|
151
194
|
"rules": [
|
|
152
195
|
"管理画面のテーブルはui/tableでなくこちらを使う。ソート・選択行・アクションメニュー対応",
|
|
153
196
|
"ActionCellのメニュー操作は行のonClickへ伝播しない(本体でstopPropagation済み)。行クリック選択との併用時も利用側ガードは不要"
|
|
@@ -177,9 +220,38 @@
|
|
|
177
220
|
"name": "DropdownMenu",
|
|
178
221
|
"path": "src/components/foundations/dropdown-menu.tsx"
|
|
179
222
|
},
|
|
223
|
+
{
|
|
224
|
+
"name": "Field",
|
|
225
|
+
"path": "src/components/foundations/field.tsx",
|
|
226
|
+
"formBinding": "layout",
|
|
227
|
+
"subcomponents": [
|
|
228
|
+
"FieldLabel",
|
|
229
|
+
"FieldSet",
|
|
230
|
+
"FieldLegend",
|
|
231
|
+
"FieldGroup",
|
|
232
|
+
"FieldDescription",
|
|
233
|
+
"FieldError",
|
|
234
|
+
"FieldSeparator"
|
|
235
|
+
],
|
|
236
|
+
"rules": [
|
|
237
|
+
"フォーム全体の骨格を組む補助群。ラベル+入力+エラーが一体で済むなら FormField が最短。ラベル・入力・説明・エラーを個別に組むときは Field + FieldLabel を使う",
|
|
238
|
+
"Field は 1 フィールド分の箱(縦リズムの最小単位)。orientation='vertical'(既定)/'horizontal'/'responsive'。responsive は FieldGroup の @container/field-group を基準に狭い=縦・広い=横へ切り替わる",
|
|
239
|
+
"余白は縦リズムに従う(FieldSet=gap-6 / FieldGroup=gap-4)。手で mt-/mb- を足さない",
|
|
240
|
+
"見出しは FieldLegend、グループ横断の区切りは FieldSeparator を使う"
|
|
241
|
+
]
|
|
242
|
+
},
|
|
180
243
|
{
|
|
181
244
|
"name": "Form",
|
|
182
245
|
"path": "src/components/foundations/form.tsx",
|
|
246
|
+
"formBinding": "layout",
|
|
247
|
+
"subcomponents": [
|
|
248
|
+
"FormField",
|
|
249
|
+
"FormItem",
|
|
250
|
+
"FormLabel",
|
|
251
|
+
"FormControl",
|
|
252
|
+
"FormDescription",
|
|
253
|
+
"FormMessage"
|
|
254
|
+
],
|
|
183
255
|
"accessibility": [
|
|
184
256
|
"aria-describedbyでエラーメッセージを紐付ける"
|
|
185
257
|
]
|
|
@@ -193,23 +265,29 @@
|
|
|
193
265
|
"path": "src/components/foundations/icon-badge.tsx",
|
|
194
266
|
"variants": [
|
|
195
267
|
"md",
|
|
268
|
+
"ml",
|
|
196
269
|
"lg"
|
|
197
270
|
],
|
|
198
271
|
"rules": [
|
|
199
|
-
"丸アイコンバッジ(md=44px/lg=72px)。アイコンを淡いアクセント背景の円で囲む装飾要素",
|
|
272
|
+
"丸アイコンバッジ(md=44px/ml=48px/lg=72px)。アイコンを淡いアクセント背景の円で囲む装飾要素",
|
|
200
273
|
"外側marginを持たない。縦間隔は親Cardのflex-col gap-4(16px)に委ねる(二重がけ防止)",
|
|
201
274
|
"アイコン色はcurrentColor(--Object-Accent-Primary)を継承。中のアイコンにcolorを渡さない",
|
|
202
|
-
"アイコンサイズはバッジが固定(md=20px/lg=38px)。アイコン側にsizeを渡さない"
|
|
275
|
+
"アイコンサイズはバッジが固定(md=20px/ml=24px/lg=38px)。アイコン側にsizeを渡さない"
|
|
203
276
|
]
|
|
204
277
|
},
|
|
205
278
|
{
|
|
206
279
|
"name": "Input",
|
|
207
280
|
"path": "src/components/foundations/input.tsx",
|
|
281
|
+
"formBinding": "register",
|
|
208
282
|
"accessibility": [
|
|
209
283
|
"必ずLabelと紐付ける"
|
|
210
284
|
],
|
|
211
285
|
"rules": [
|
|
212
|
-
"<input>を直接使わない。type='email'/'tel'を適切に指定する"
|
|
286
|
+
"<input>を直接使わない。type='email'/'tel'を適切に指定する",
|
|
287
|
+
"高さは 44px(h-11)。フォーム入力コントロールと Button の既定(Input / SelectTrigger default / DatePicker trigger / Button size='default')は 44px で統一されており、検索+絞り込みセレクト+ボタンのような並置でも揃う",
|
|
288
|
+
"44px は rules.json の touchTarget『Text input』の min を満たす値であり、DS の既定として採用している。recommended の 48px まで上げたい画面は consumer が className='h-12' で上書きする",
|
|
289
|
+
"文字数カウンタは showCount + maxLength で有効化(右下に {現在}/{max}、上限で Text-Caution)。制御/非制御両対応",
|
|
290
|
+
"非制御は react-hook-form の register() / reset() で ref 経由に値が入る実利用経路まで story とテストで検証する"
|
|
213
291
|
]
|
|
214
292
|
},
|
|
215
293
|
{
|
|
@@ -247,8 +325,44 @@
|
|
|
247
325
|
{
|
|
248
326
|
"name": "RadioGroup",
|
|
249
327
|
"path": "src/components/foundations/radio-group.tsx",
|
|
328
|
+
"formBinding": "controller",
|
|
329
|
+
"subcomponents": [
|
|
330
|
+
"RadioGroupItem"
|
|
331
|
+
],
|
|
332
|
+
"variants": [
|
|
333
|
+
"tile",
|
|
334
|
+
"chip"
|
|
335
|
+
],
|
|
250
336
|
"accessibility": [
|
|
251
|
-
"各RadioGroupItem
|
|
337
|
+
"各RadioGroupItemにラベルテキスト必須。ラベルは children として RadioGroupItem の内側に書く(<RadioGroupItem value='x'>ラベル</RadioGroupItem>)。RadioGroupItem が内部で <label> 相当の関連付けまで行うため、外側に <Label htmlFor> を併置してはいけない(ラベル重複になる)"
|
|
338
|
+
],
|
|
339
|
+
"props": [
|
|
340
|
+
"children: ラベル本文(必須。tile/chip 共通)",
|
|
341
|
+
"description?: ReactNode — ラベル下の補足説明(tile のみ)",
|
|
342
|
+
"expandedContent?: ReactNode — 選択時に展開する追加コンテンツ(tile のみ)"
|
|
343
|
+
],
|
|
344
|
+
"rules": [
|
|
345
|
+
"variant='tile'(既定)=ラジオ丸+ラベル+補足説明+展開コンテンツのタイル型",
|
|
346
|
+
"⚠️ タイルの枠(border/角丸/余白/選択状態の意匠)は RadioGroupItem 自身が描画する。consumer 側で <div className='border rounded-lg ...'> 等で囲むと枠が二重になる。囲まずにそのまま並べる",
|
|
347
|
+
"ラベルは children で渡す。<RadioGroupItem/> と <Label htmlFor> を兄弟に並べる書き方は誤り(枠の二重化+ラベル重複を招く)",
|
|
348
|
+
"variant='chip'=ラベルを内包したChoice Chip意匠の排他選択(タグ選択・絞り込み等)。ラジオ丸は描画せず、Chip本体と同じchipVariantsを再利用して選択状態をaccent意匠(静止=薄オレンジ/hover=ベタ塗り)で示す。description/expandedContentは持たない。Radixのキーボード操作・a11yは維持"
|
|
349
|
+
]
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
"name": "FileInput",
|
|
353
|
+
"path": "src/components/foundations/file-input.tsx",
|
|
354
|
+
"formBinding": "controller",
|
|
355
|
+
"accessibility": [
|
|
356
|
+
"idをLabel/FormFieldのhtmlForと揃えて紐付ける",
|
|
357
|
+
"ネイティブ<input type='file'>をvisually-hiddenで内包しキーボード・SR操作可能",
|
|
358
|
+
"エラー表示はaria-describedbyでFieldErrorと接続"
|
|
359
|
+
],
|
|
360
|
+
"rules": [
|
|
361
|
+
"<input type='file'>を直接書かない。汎用の添付(PDF/CSV/画像混在)はFileInputを使う",
|
|
362
|
+
"画像1枚の入力(プレビュー+形式/サイズ検証+値のバインド)はImageInputを使う",
|
|
363
|
+
"複数枚の画像を並べて管理するグリッドはImageUploaderを使う",
|
|
364
|
+
"複数選択時(multiple)は選択済みを「n件選択」で集約表示",
|
|
365
|
+
"maxSize(バイト)超過ファイルは受理せずonErrorを呼ぶ"
|
|
252
366
|
]
|
|
253
367
|
},
|
|
254
368
|
{
|
|
@@ -265,8 +379,10 @@
|
|
|
265
379
|
{
|
|
266
380
|
"name": "Select",
|
|
267
381
|
"path": "src/components/foundations/select.tsx",
|
|
382
|
+
"formBinding": "controller",
|
|
268
383
|
"rules": [
|
|
269
|
-
"<select>HTMLネイティブを使わない"
|
|
384
|
+
"<select>HTMLネイティブを使わない",
|
|
385
|
+
"SelectTrigger の高さは size='default'=44px(h-11)で Input / DatePicker trigger / Button default と揃う。size='sm'=36px。高さは素のクラスで当てているため className='h-12' 等で上書きできる(data 属性セレクタではない)"
|
|
270
386
|
]
|
|
271
387
|
},
|
|
272
388
|
{
|
|
@@ -293,15 +409,31 @@
|
|
|
293
409
|
"アニメーションはpulseのみ許可"
|
|
294
410
|
]
|
|
295
411
|
},
|
|
412
|
+
{
|
|
413
|
+
"name": "SkipLink",
|
|
414
|
+
"path": "src/components/foundations/skip-link.tsx",
|
|
415
|
+
"category": "navigation",
|
|
416
|
+
"accessibility": [
|
|
417
|
+
"WCAG 2.4.1(Bypass Blocks)対応。キーボード/SR ユーザーがヘッダーの反復リンクを飛ばして本文へ移動する",
|
|
418
|
+
"aria/文言は日本語(既定「コンテンツへ移動」)"
|
|
419
|
+
],
|
|
420
|
+
"rules": [
|
|
421
|
+
"sr-only で常時視覚には出さず、フォーカス時のみ左上に可視化する(focus:not-sr-only)",
|
|
422
|
+
"スキップ先 <main id> は href(既定 #main-content)と一致させる",
|
|
423
|
+
"全シェル(StandardPageShell / FunnelShell / WorkspaceShell / AdminShell / MypageShell)が DOM 先頭に標準内蔵する。シェルを使う場合は個別に置かない(skipLink={false} で無効化)"
|
|
424
|
+
]
|
|
425
|
+
},
|
|
296
426
|
{
|
|
297
427
|
"name": "Slider",
|
|
298
|
-
"path": "src/components/foundations/slider.tsx"
|
|
428
|
+
"path": "src/components/foundations/slider.tsx",
|
|
429
|
+
"formBinding": "controller"
|
|
299
430
|
},
|
|
300
431
|
{
|
|
301
|
-
"name": "
|
|
432
|
+
"name": "Toaster",
|
|
302
433
|
"path": "src/components/foundations/sonner.tsx",
|
|
303
434
|
"rules": [
|
|
304
|
-
"トースト内にアクションリンクを入れない。左ボーダーではなく背景色全体で状態を表現"
|
|
435
|
+
"トースト内にアクションリンクを入れない。左ボーダーではなく背景色全体で状態を表現",
|
|
436
|
+
"アプリのルートに <Toaster /> を1つ置き、表示は toast()(sonner の再 export)で呼ぶ"
|
|
305
437
|
]
|
|
306
438
|
},
|
|
307
439
|
{
|
|
@@ -311,6 +443,7 @@
|
|
|
311
443
|
{
|
|
312
444
|
"name": "Switch",
|
|
313
445
|
"path": "src/components/foundations/switch.tsx",
|
|
446
|
+
"formBinding": "controller",
|
|
314
447
|
"accessibility": [
|
|
315
448
|
"Label必須"
|
|
316
449
|
]
|
|
@@ -334,20 +467,27 @@
|
|
|
334
467
|
{
|
|
335
468
|
"name": "Textarea",
|
|
336
469
|
"path": "src/components/foundations/textarea.tsx",
|
|
470
|
+
"formBinding": "register",
|
|
337
471
|
"accessibility": [
|
|
338
472
|
"Label必須"
|
|
473
|
+
],
|
|
474
|
+
"rules": [
|
|
475
|
+
"文字数カウンタは showCount + maxLength で有効化(右下に {現在}/{max}、上限で Text-Caution)。制御/非制御両対応",
|
|
476
|
+
"非制御は react-hook-form の register() / reset() で ref 経由に値が入る実利用経路まで story とテストで検証する"
|
|
339
477
|
]
|
|
340
478
|
},
|
|
341
479
|
{
|
|
342
480
|
"name": "ToggleGroup",
|
|
343
481
|
"path": "src/components/foundations/toggle-group.tsx",
|
|
482
|
+
"formBinding": "controller",
|
|
344
483
|
"rules": [
|
|
345
484
|
"水平パディングはコンポーネント内に入れない。親が管理する"
|
|
346
485
|
]
|
|
347
486
|
},
|
|
348
487
|
{
|
|
349
488
|
"name": "Toggle",
|
|
350
|
-
"path": "src/components/foundations/toggle.tsx"
|
|
489
|
+
"path": "src/components/foundations/toggle.tsx",
|
|
490
|
+
"formBinding": "controller"
|
|
351
491
|
},
|
|
352
492
|
{
|
|
353
493
|
"name": "Tooltip",
|
|
@@ -366,6 +506,23 @@
|
|
|
366
506
|
"name": "BannerCarousel",
|
|
367
507
|
"path": "src/components/primitives/banner-carousel.tsx"
|
|
368
508
|
},
|
|
509
|
+
{
|
|
510
|
+
"name": "ContentCarousel",
|
|
511
|
+
"path": "src/components/primitives/content-carousel.tsx",
|
|
512
|
+
"features": [
|
|
513
|
+
"scroll-snap",
|
|
514
|
+
"dots",
|
|
515
|
+
"arrows",
|
|
516
|
+
"autoPlay",
|
|
517
|
+
"itemsPerView"
|
|
518
|
+
],
|
|
519
|
+
"rules": [
|
|
520
|
+
"ReactNode スライド対応(slides: ReactNode[])。テキスト主体のヒーローバナー用",
|
|
521
|
+
"itemsPerView=2|3|4 で PC の複数カード表示に対応。SP は1枚表示を維持し、EC 商品以外の求人・記事カード等にも使う",
|
|
522
|
+
"画像だけのバナーは ImageCarousel を使う",
|
|
523
|
+
"矢印・ドットの意匠は ImageCarousel と同一"
|
|
524
|
+
]
|
|
525
|
+
},
|
|
369
526
|
{
|
|
370
527
|
"name": "StickyActionBar",
|
|
371
528
|
"path": "src/components/primitives/sticky-action-bar.tsx",
|
|
@@ -395,6 +552,35 @@
|
|
|
395
552
|
"name": "CategoryScroll",
|
|
396
553
|
"path": "src/components/primitives/category-scroll.tsx"
|
|
397
554
|
},
|
|
555
|
+
{
|
|
556
|
+
"name": "ChatComposer",
|
|
557
|
+
"path": "src/components/primitives/chat-composer.tsx",
|
|
558
|
+
"formBinding": "controller",
|
|
559
|
+
"variants": [
|
|
560
|
+
"submitKey:enter",
|
|
561
|
+
"submitKey:mod-enter"
|
|
562
|
+
],
|
|
563
|
+
"features": [
|
|
564
|
+
"attachments",
|
|
565
|
+
"maxFiles",
|
|
566
|
+
"maxSizeMb",
|
|
567
|
+
"maxLength",
|
|
568
|
+
"isSubmitting"
|
|
569
|
+
],
|
|
570
|
+
"accessibility": [
|
|
571
|
+
"入力欄はvisually-hiddenのlabel(label prop)とhtmlForで紐付ける",
|
|
572
|
+
"送信ボタンのaria-labelは日本語(送信 / 送信中)",
|
|
573
|
+
"添付削除はChipのremovableで操作でき、キーボードで到達できる"
|
|
574
|
+
],
|
|
575
|
+
"rules": [
|
|
576
|
+
"チャット・問い合わせ・返信の入力欄をTextarea+Buttonで手組みしない",
|
|
577
|
+
"既定はEnter送信・Shift+Enter改行。長文が主なsubmitKey='mod-enter'を使う",
|
|
578
|
+
"IME変換中のEnterでは送信しない(日本語入力の誤送信防止)",
|
|
579
|
+
"添付は内蔵のFileInputで選択し、選択済みはChipのremovableで表示・削除する",
|
|
580
|
+
"送信中はisSubmittingを立てる(送信ボタン無効化で二重送信を防ぐ)",
|
|
581
|
+
"<form>を内包しないため、フォーム内に置いても入れ子にならない"
|
|
582
|
+
]
|
|
583
|
+
},
|
|
398
584
|
{
|
|
399
585
|
"name": "Chip",
|
|
400
586
|
"path": "src/components/primitives/chip.tsx",
|
|
@@ -411,6 +597,21 @@
|
|
|
411
597
|
"Tagと違い押せる・削除できる"
|
|
412
598
|
]
|
|
413
599
|
},
|
|
600
|
+
{
|
|
601
|
+
"name": "DatePicker",
|
|
602
|
+
"path": "src/components/primitives/date-picker.tsx",
|
|
603
|
+
"formBinding": "controller",
|
|
604
|
+
"subcomponents": [
|
|
605
|
+
"DateTimePicker"
|
|
606
|
+
],
|
|
607
|
+
"rules": [
|
|
608
|
+
"input type='date' 禁止ルールの実装済みの正解形。Popover+Calendar を毎回手組みしない",
|
|
609
|
+
"trigger の選択値は M月D日(曜日)表記、カレンダーは日本語ロケール",
|
|
610
|
+
"選択範囲は min/max、個別不可日は disabledDates で指定する",
|
|
611
|
+
"DateTimePicker は JST 前提で Date をそのまま扱う(TZ 変換しない)",
|
|
612
|
+
"FormField の children に置き、id を htmlFor と揃えて label/エラーと接続する"
|
|
613
|
+
]
|
|
614
|
+
},
|
|
414
615
|
{
|
|
415
616
|
"name": "EmptyState",
|
|
416
617
|
"path": "src/components/primitives/empty-state.tsx",
|
|
@@ -421,8 +622,19 @@
|
|
|
421
622
|
{
|
|
422
623
|
"name": "ErrorState",
|
|
423
624
|
"path": "src/components/primitives/error-state.tsx",
|
|
625
|
+
"variants": {
|
|
626
|
+
"kind": [
|
|
627
|
+
"error",
|
|
628
|
+
"notFound"
|
|
629
|
+
]
|
|
630
|
+
},
|
|
631
|
+
"subcomponents": [
|
|
632
|
+
"NotFoundIllustration"
|
|
633
|
+
],
|
|
424
634
|
"rules": [
|
|
425
|
-
"
|
|
635
|
+
"kind='error'(既定)は色+アイコン+テキスト必須。リトライアクションを含める",
|
|
636
|
+
"kind='notFound' は 404 向け。イラスト・見出し・説明が既定で入るため action(トップへ戻る等)だけ渡せばよい",
|
|
637
|
+
"NotFoundIllustration は単体 export。consumer が独自レイアウトで使う場合に流用する"
|
|
426
638
|
]
|
|
427
639
|
},
|
|
428
640
|
{
|
|
@@ -441,6 +653,8 @@
|
|
|
441
653
|
{
|
|
442
654
|
"name": "FormField",
|
|
443
655
|
"path": "src/components/primitives/form-field.tsx",
|
|
656
|
+
"formBinding": "layout",
|
|
657
|
+
"exportedAs": "CakeFormField",
|
|
444
658
|
"variants": {
|
|
445
659
|
"descriptionPosition": [
|
|
446
660
|
"above",
|
|
@@ -449,7 +663,8 @@
|
|
|
449
663
|
},
|
|
450
664
|
"rules": [
|
|
451
665
|
"Label+Input+エラーメッセージをセットで管理",
|
|
452
|
-
"グリッド横並び時は descriptionPosition='below' で高さを揃える"
|
|
666
|
+
"グリッド横並び時は descriptionPosition='below' で高さを揃える",
|
|
667
|
+
"npm 経由では CakeFormField として import する(foundations/form.tsx の FormField と名前が衝突するため別名で export)"
|
|
453
668
|
]
|
|
454
669
|
},
|
|
455
670
|
{
|
|
@@ -466,6 +681,52 @@
|
|
|
466
681
|
"name": "ImageGallery",
|
|
467
682
|
"path": "src/components/primitives/image-gallery.tsx"
|
|
468
683
|
},
|
|
684
|
+
{
|
|
685
|
+
"name": "ImageInput",
|
|
686
|
+
"path": "src/components/primitives/image-input.tsx",
|
|
687
|
+
"formBinding": "controller",
|
|
688
|
+
"variants": [
|
|
689
|
+
"aspect:square",
|
|
690
|
+
"aspect:landscape",
|
|
691
|
+
"size:sm",
|
|
692
|
+
"size:md",
|
|
693
|
+
"size:lg",
|
|
694
|
+
"objectFit:cover",
|
|
695
|
+
"objectFit:contain"
|
|
696
|
+
],
|
|
697
|
+
"features": [
|
|
698
|
+
"preview",
|
|
699
|
+
"accept",
|
|
700
|
+
"maxSizeMb",
|
|
701
|
+
"clear",
|
|
702
|
+
"formBinding"
|
|
703
|
+
],
|
|
704
|
+
"props": [
|
|
705
|
+
"value: File | string | null — Fileは新規選択・stringは保存済み画像のURL(必須)",
|
|
706
|
+
"onChange: (file: File | null) => void — 検証を通ったファイルのみ渡る(必須)",
|
|
707
|
+
"onBlur?: () => void — フォーカスが部品外へ抜けたとき(React Hook Form の touched 連携)",
|
|
708
|
+
"id? / name? — 内包 input に付与。FormField の htmlFor と揃える",
|
|
709
|
+
"accept?: string — 既定 'image/png,image/jpeg'",
|
|
710
|
+
"maxSizeMb?: number — 既定 2",
|
|
711
|
+
"error?: string — 外部(RHF等)のエラー。内蔵検証のエラーより優先して表示",
|
|
712
|
+
"onValidationError?: (error) => void — 検証エラーをモーダル等で出したい場合のみ"
|
|
713
|
+
],
|
|
714
|
+
"accessibility": [
|
|
715
|
+
"検証エラーはFieldError(role='alert')にインライン表示し、色だけで伝えない",
|
|
716
|
+
"内包inputにaria-invalid / aria-describedbyを付けてエラーと紐付ける",
|
|
717
|
+
"クリアボタンのaria-labelは日本語(画像を削除)",
|
|
718
|
+
"ファイル選択の口はFileInputを内包し、キーボード・SRで操作できる"
|
|
719
|
+
],
|
|
720
|
+
"rules": [
|
|
721
|
+
"画像1枚の入力を<input type='file'>+<img>で手組みしない",
|
|
722
|
+
"value/onChangeの制御コンポーネント。保存済み画像はURL文字列をそのまま渡す",
|
|
723
|
+
"プレビューのobjectURLは内部でrevokeされる。consumer側でcreateObjectURLしない",
|
|
724
|
+
"検証エラーの既定はインライン表示。モーダルは強すぎるため既定にしない",
|
|
725
|
+
"表示サイズはaspect(square/landscape)×size(sm/md/lg)で指定し、任意のw-[Npx]を足さない",
|
|
726
|
+
"非同期検証(画像寸法チェック等)は持たない。onChange後にconsumer側で検証しerrorで戻す",
|
|
727
|
+
"汎用の添付はFileInput(foundations)、複数枚のグリッド管理はImageUploader(primitives)"
|
|
728
|
+
]
|
|
729
|
+
},
|
|
469
730
|
{
|
|
470
731
|
"name": "ImageUploader",
|
|
471
732
|
"path": "src/components/primitives/image-uploader.tsx",
|
|
@@ -473,6 +734,10 @@
|
|
|
473
734
|
"upload",
|
|
474
735
|
"delete",
|
|
475
736
|
"grid"
|
|
737
|
+
],
|
|
738
|
+
"rules": [
|
|
739
|
+
"複数枚の画像を並べて管理するグリッド。ファイル選択の口は持たず、追加はonAddでconsumerが実装する",
|
|
740
|
+
"画像1枚の入力(プレビュー+検証+値のバインド)はImageInputを使う"
|
|
476
741
|
]
|
|
477
742
|
},
|
|
478
743
|
{
|
|
@@ -525,9 +790,24 @@
|
|
|
525
790
|
"name": "ProgressSteps",
|
|
526
791
|
"path": "src/components/primitives/progress-steps.tsx"
|
|
527
792
|
},
|
|
793
|
+
{
|
|
794
|
+
"name": "Timeline",
|
|
795
|
+
"path": "src/components/primitives/timeline.tsx",
|
|
796
|
+
"features": [
|
|
797
|
+
"vertical",
|
|
798
|
+
"custom-marker",
|
|
799
|
+
"connector"
|
|
800
|
+
],
|
|
801
|
+
"rules": [
|
|
802
|
+
"本文付きの縦タイムラインに使う。現在位置を示す横型インジケータは ProgressSteps を使う",
|
|
803
|
+
"marker 省略時は連番。IconBadge 等の ReactNode を渡せる",
|
|
804
|
+
"コネクター線は Timeline が所有するため consumer が ::before / ::after で手組みしない"
|
|
805
|
+
]
|
|
806
|
+
},
|
|
528
807
|
{
|
|
529
808
|
"name": "QuantitySelector",
|
|
530
809
|
"path": "src/components/primitives/quantity-selector.tsx",
|
|
810
|
+
"formBinding": "controller",
|
|
531
811
|
"features": [
|
|
532
812
|
"increment",
|
|
533
813
|
"decrement",
|
|
@@ -536,7 +816,8 @@
|
|
|
536
816
|
},
|
|
537
817
|
{
|
|
538
818
|
"name": "SearchBar",
|
|
539
|
-
"path": "src/components/primitives/search-bar.tsx"
|
|
819
|
+
"path": "src/components/primitives/search-bar.tsx",
|
|
820
|
+
"formBinding": "none"
|
|
540
821
|
},
|
|
541
822
|
{
|
|
542
823
|
"name": "SearchPanel",
|
|
@@ -563,12 +844,18 @@
|
|
|
563
844
|
"path": "src/components/primitives/section.tsx",
|
|
564
845
|
"variants": [
|
|
565
846
|
"spacing: sm | md | lg | xl",
|
|
566
|
-
"background: none | subtle | accent-subtle"
|
|
847
|
+
"background: none | subtle | accent-subtle",
|
|
848
|
+
"scrim: none | dark | light | bottom-dark"
|
|
567
849
|
],
|
|
568
850
|
"rules": [
|
|
569
851
|
"全幅の縦リズム+背景帯。左右paddingを持たない(左右余白はContainerが唯一の担い手)",
|
|
852
|
+
"背景画像上に文字を載せる場合は backgroundImage + scrim を使う。consumer が gradient overlay を ::before / ::after で手組みしない",
|
|
853
|
+
"scrim は Surface-Overlay-Light / Dark を使い、dark / light / bottom-dark の意匠を DS が所有する",
|
|
570
854
|
"背景色はSection(全幅)が持ち中央寄せはContainerが持つ → 背景帯は画面端まで・コンテンツは中央寄せが二重がけなしで成立",
|
|
571
|
-
"縦余白はSP/PCペアで --Space-Section-* トークンを消費(rem直書き撲滅)"
|
|
855
|
+
"縦余白はSP/PCペアで --Space-Section-* トークンを消費(rem直書き撲滅)",
|
|
856
|
+
"background='subtle'|'accent-subtle'(色地)は配下に --card-surface: var(--Surface-Primary) を流す → 配下のCardはsurface未指定でも白になる(グレー地にカードが沈む事故を構造で防ぐ)。伝播はCSSカスタムプロパティのみでReact context不使用=Server Componentのまま使える",
|
|
857
|
+
"background='none'は文脈をリセットしない。色地Sectionの内側に入れ子にしたnoneは背景が透過して外側の色地が見えるため、配下Cardも白のままが正しい",
|
|
858
|
+
"darkでは伝播値をSurface-Secondaryに据え置く(darkのSurface-Secondaryは半透明白=色地に重なって一段明るく浮くのでそもそも沈まない。Surface-Primaryを強制すると地より暗い穴になりelevationが反転する)"
|
|
572
859
|
]
|
|
573
860
|
},
|
|
574
861
|
{
|
|
@@ -576,11 +863,13 @@
|
|
|
576
863
|
"path": "src/components/primitives/section-header.tsx",
|
|
577
864
|
"variants": [
|
|
578
865
|
"size: 3xl | 2xl | xl | lg | md | sm",
|
|
866
|
+
"desktopSize: 5xl | 4xl",
|
|
579
867
|
"align: start | center"
|
|
580
868
|
],
|
|
581
869
|
"rules": [
|
|
582
870
|
"タイトル+もっと見るボタンをCardTitle+Button手書き禁止。SectionHeaderを使う",
|
|
583
|
-
"中央寄せ大見出し(ランディング/ガイド系)は align=\"center\" を使う。eyebrow プロップに Badge 等を載せられる。手書きの中央寄せ見出し禁止"
|
|
871
|
+
"中央寄せ大見出し(ランディング/ガイド系)は align=\"center\" を使う。eyebrow プロップに Badge 等を載せられる。手書きの中央寄せ見出し禁止",
|
|
872
|
+
"3xl(28px)は通常ページの主見出しにも使う。4xl/5xlはLP・マーケティング系ヒーロー専用で、size=\"3xl\" に desktopSize=\"4xl\" または desktopSize=\"5xl\" を加えてPC時だけ拡大する"
|
|
584
873
|
]
|
|
585
874
|
},
|
|
586
875
|
{
|
|
@@ -595,7 +884,8 @@
|
|
|
595
884
|
"name": "StatusCountTabs",
|
|
596
885
|
"path": "src/components/primitives/status-count-tabs.tsx",
|
|
597
886
|
"rules": [
|
|
598
|
-
"ToggleGroup+Badge手書き禁止。Chip count propを使う"
|
|
887
|
+
"ToggleGroup+Badge手書き禁止。Chip count propを使う",
|
|
888
|
+
"activeIndex は初期値だけでなく、マウント後の外部変更にも表示が追従する"
|
|
599
889
|
]
|
|
600
890
|
},
|
|
601
891
|
{
|
|
@@ -618,18 +908,28 @@
|
|
|
618
908
|
"name": "SectionNav",
|
|
619
909
|
"path": "src/components/primitives/section-nav.tsx",
|
|
620
910
|
"category": "navigation",
|
|
911
|
+
"variants": [
|
|
912
|
+
"vertical",
|
|
913
|
+
"horizontal"
|
|
914
|
+
],
|
|
621
915
|
"rules": [
|
|
622
916
|
"ページ内セクション移動(アンカー/目次)専用。href=\"#section-id\" のページ内スクロールに使う",
|
|
623
917
|
"ページ間遷移に使わない → SideNav を使う",
|
|
624
918
|
"チェブロン・矢印を足さない(遷移アフォーダンスを持たせない。同一画面内の位置移動に見せる)",
|
|
625
919
|
"WorkspaceShell の sectionNav にはこれを使う(SideNav を流用しない)",
|
|
626
|
-
"固有幅・背景・境界を持たない(w-full)。パネル化・幅決定はシェル/利用側の責務"
|
|
920
|
+
"固有幅・背景・境界を持たない(w-full)。パネル化・幅決定はシェル/利用側の責務",
|
|
921
|
+
"orientation=\"vertical\"(既定)は縦積み目次。orientation=\"horizontal\" は Tabs アンダーバー式の横並び(ガイド・FAQ 等の長い静的ページのページ内ジャンプ、overflow-x-auto 対応)",
|
|
922
|
+
"sticky は内蔵しない。horizontal を貼り付ける場合は利用側が className=\"sticky top-14 …\" を付与し、ジャンプ先セクションに scroll-mt-* を付ける",
|
|
923
|
+
"IntersectionObserver は内包しない。activeKey は利用側が制御する(AnchorNav の新設は却下、本コンポーネントの variant で担う)"
|
|
627
924
|
]
|
|
628
925
|
},
|
|
629
926
|
{
|
|
630
927
|
"name": "StandardPageShell",
|
|
631
928
|
"path": "src/components/primitives/standard-page-shell.tsx",
|
|
632
929
|
"kind": "shell",
|
|
930
|
+
"deprecatedAliases": [
|
|
931
|
+
"EcPageShell"
|
|
932
|
+
],
|
|
633
933
|
"variants": [],
|
|
634
934
|
"rules": [
|
|
635
935
|
"消費者向け標準ページ(Standard Page(View / Edit))の骨格。composition.json pageSkeletons(mobile / desktop)の実装体。min-h-dvh flex flex-col の全高コンテナに header / main / bottomTab / footer を積む",
|
|
@@ -637,20 +937,30 @@
|
|
|
637
937
|
"あくまで枠。プロダクトのロゴ・タブ項目・ナビ項目・文言を焼き込まない。header / bottomTab は利用側(ec 層)が組み立てて渡す",
|
|
638
938
|
"bottomTab を渡すと main の下余白(pb-20 相当)はシェルが管理する。ページ側で pb-20 を書かない(付け忘れ/二重がけの構造的防止)",
|
|
639
939
|
"左右 padding は持たない(Container の責務)。中身は Section(全幅背景帯)+ Container(中央寄せ・左右余白)で組む",
|
|
640
|
-
"管理画面は AdminShell、複数情報をまたぐ集中編集は WorkspaceShell、マイページ配下は MypageShell を使う"
|
|
940
|
+
"管理画面は AdminShell、複数情報をまたぐ集中編集は WorkspaceShell、マイページ配下は MypageShell を使う",
|
|
941
|
+
"a11y: DOM 先頭に SkipLink を標準内蔵し <main id> を制御できる(mainId 既定 main-content、SkipLink の飛び先と一致)。sr-only で視覚無影響。skipLink={false} で無効化。ページ側で手組みしない"
|
|
641
942
|
]
|
|
642
943
|
},
|
|
643
944
|
{
|
|
644
945
|
"name": "WorkspaceShell",
|
|
645
946
|
"path": "src/components/primitives/workspace-shell.tsx",
|
|
646
947
|
"kind": "shell",
|
|
647
|
-
"
|
|
948
|
+
"deprecatedAliases": [
|
|
949
|
+
"WorkspaceLayout"
|
|
950
|
+
],
|
|
951
|
+
"variants": [
|
|
952
|
+
"headerLayout=start",
|
|
953
|
+
"headerLayout=center"
|
|
954
|
+
],
|
|
648
955
|
"rules": [
|
|
649
956
|
"Focused Workspace(全画面集中編集)のシェル。編集ヘッダー(Header variant=back)+ 任意のセクションナビ + 編集本体で構成",
|
|
957
|
+
"headerLayout(既定 start): centerでヘッダーを左=戻る/中央=タイトル/右=primaryActionの3カラムgridに固定し、タイトルを真の中央に揃える(#112)。consumer 側の data-slot セレクタ上書きは不要",
|
|
650
958
|
"グローバルナビ・パンくずを持たない(構造的に置けない)。集中を妨げる導線は出さない",
|
|
651
959
|
"primaryActionはワークスペース全体の上位アクション(公開申請・承認依頼等)がある場合のみ。セクション/行単位の操作はコンテンツ内に置く",
|
|
652
960
|
"標準の編集はAdminShellのStandard Page(Edit)(旧Form Page)。複雑・複数情報をまたぐ集中編集・没入執筆のみWorkspaceShellを使う",
|
|
653
|
-
"sectionNavは編集内ナビ(アンカー/ステップ)のみ。PCでサイド表示・SPで非表示"
|
|
961
|
+
"sectionNavは編集内ナビ(アンカー/ステップ)のみ。PCでサイド表示・SPで非表示",
|
|
962
|
+
"地がSurface-Secondaryなので、シェルが配下Cardのサーフェス文脈(--card-surface: Surface-Primary)を宣言する → Cardはsurface未指定のまま白で地から浮く(#150)。darkは据え置き",
|
|
963
|
+
"a11y: DOM 先頭に SkipLink を標準内蔵し <main id> を制御できる(mainId 既定 main-content)。sr-only で視覚無影響。skipLink={false} で無効化"
|
|
654
964
|
]
|
|
655
965
|
},
|
|
656
966
|
{
|
|
@@ -664,12 +974,26 @@
|
|
|
664
974
|
"あくまで枠。ステップ定義(名前・数)・文言・商品データを焼き込まない。steps / activeStep は利用側(ドメイン)が渡す",
|
|
665
975
|
"グローバルナビ・BottomTabBar・パンくずを持たない(構造的に置けない)。離脱を誘う導線を出さず購入に集中させる",
|
|
666
976
|
"bottomAction(StickyActionBar 等)を渡すと本文の下余白はシェルが管理する。ページ側で pb を書かない(付け忘れ/二重がけの構造的防止)",
|
|
667
|
-
"左右 padding は持たない(Container の責務)。管理画面の複雑な集中編集は WorkspaceShell を使う(EC 購入導線=FunnelShell)"
|
|
977
|
+
"左右 padding は持たない(Container の責務)。管理画面の複雑な集中編集は WorkspaceShell を使う(EC 購入導線=FunnelShell)",
|
|
978
|
+
"地がSurface-Secondaryなので、シェルが配下Cardのサーフェス文脈(--card-surface: Surface-Primary)を宣言する → Cardはsurface未指定のまま白で地から浮く(#150)。darkは据え置き",
|
|
979
|
+
"a11y: DOM 先頭に SkipLink を標準内蔵し <main id> を制御できる(mainId 既定 main-content)。sr-only で視覚無影響。skipLink={false} で無効化"
|
|
668
980
|
]
|
|
669
981
|
},
|
|
670
982
|
{
|
|
671
983
|
"name": "Header",
|
|
672
|
-
"path": "src/components/primitives/header.tsx"
|
|
984
|
+
"path": "src/components/primitives/header.tsx",
|
|
985
|
+
"variants": [
|
|
986
|
+
"logo",
|
|
987
|
+
"logo-center",
|
|
988
|
+
"back",
|
|
989
|
+
"back-search"
|
|
990
|
+
],
|
|
991
|
+
"rules": [
|
|
992
|
+
"variant=\"logo\" の PC 行(@[768px]+)では searchSlot で navItems と actions の間に常設検索を inline 配置できる(flex-1 max-w-[400px] で伸縮)。navItems 無し+searchSlot だけでも PC 行を描画する",
|
|
993
|
+
"SP 行に searchSlot は出さない。SP の常設検索は従来どおり bottomSlot で運用する",
|
|
994
|
+
"bottomSlot はヘッダー下段の全幅スロット(ProductDetailBar 等)。PC 常設検索の置き場に使わない(PC 二段ヘッダーになる)",
|
|
995
|
+
"actions(HeaderAction)はカート・マイページ等の本来リンクである導線には href を指定する。href 指定時は Button asChild + <a> で描画され、中クリック/新規タブ・リンクコピーが効く。onClick と併用可(両方付与される)"
|
|
996
|
+
]
|
|
673
997
|
},
|
|
674
998
|
{
|
|
675
999
|
"name": "AdminSideNav",
|
|
@@ -678,6 +1002,7 @@
|
|
|
678
1002
|
"rules": [
|
|
679
1003
|
"管理画面向けサイドナビの汎用枠。PC は左端固定アイコンレール(ホバーでサブメニュー)、SP は制御ドロワー(サブメニューはアコーディオン)",
|
|
680
1004
|
"項目データ(メニュー定義・文言)は全て items prop で受ける。特定事業のメニューを部品側に焼き込まない(Cake.jp 既定は AdminShell が持つ)",
|
|
1005
|
+
"PC レールのラベルは max-w-12 + typo-label-xs + 中央揃えを本体が所有する。5文字超も語のまとまりで折り返せるため、consumer が data-slot セレクタで内部上書きしない",
|
|
681
1006
|
"SP ドロワー開閉は open / onOpenChange で制御する(内部 state を持たない)",
|
|
682
1007
|
"icon は ReactNode か描画コンテキスト(active / placement)で出し分ける関数を渡す"
|
|
683
1008
|
]
|
|
@@ -697,13 +1022,23 @@
|
|
|
697
1022
|
"name": "AdminShell",
|
|
698
1023
|
"path": "src/components/ec/admin-shell.tsx",
|
|
699
1024
|
"kind": "shell",
|
|
1025
|
+
"deprecatedAliases": [
|
|
1026
|
+
"AdminLayout"
|
|
1027
|
+
],
|
|
1028
|
+
"subcomponents": [
|
|
1029
|
+
"MissingComponent"
|
|
1030
|
+
],
|
|
700
1031
|
"rules": [
|
|
701
1032
|
"管理画面のレイアウトシェル。枠は primitives の AdminSideNav / AdminHeader を組み込む",
|
|
702
1033
|
"Cake.jp 管理メニュー8項目+サブメニュー・通知ベル・プロフィール・『{shopName}管理』を既定値として同梱する(ec 層)",
|
|
703
1034
|
"navItems で既定メニューを差し替え可、headerActions でヘッダー右アクションを差し替え可",
|
|
1035
|
+
"⚠️ PC の左サイドナビは 72px のアイコンレール(アイコン+短ラベル、サブメニューは hover ポップアップ)。バッジ+見出し+説明文のようなブランドブロックをレール上部に置く領域は無い。幅広サイドバー前提の画面はこの骨格では置き換えられない",
|
|
1036
|
+
"他ブランドで使う場合、ヘッダー左のブランド表示は brand(ReactNode。既定=『{shopName}管理』の文字列)で差し替える。SP ドロワー上部の見出しは sidebarHeader(ReactNode。既定=shopName)で差し替える",
|
|
704
1037
|
"戻る導線(onBack)はパンくずの上に置く。onBack を渡すとシェルが main 内・パンくずより上に戻るボタンを描画する(backLabel で文言変更・既定『戻る』)。子コンテンツ内に戻るリンクを手書きしない",
|
|
705
1038
|
"タイトル直下の上位アクション(AI商品作成・PDF出力等)は h1 と同じ左端に左寄せする。右端フロートにしない",
|
|
706
|
-
"既定値は props で差し替え可能で、骨格(Header + SideNav + Main)自体は他事業(ジョブボードの管理画面等)でも再利用できる"
|
|
1039
|
+
"既定値は props で差し替え可能で、骨格(Header + SideNav + Main)自体は他事業(ジョブボードの管理画面等)でも再利用できる",
|
|
1040
|
+
"a11y: DOM 先頭に SkipLink を標準内蔵し <main id> を制御できる(mainId 既定 main-content)。sr-only で視覚無影響。skipLink={false} で無効化",
|
|
1041
|
+
"地がSurface-Secondaryなので、シェルが配下Cardのサーフェス文脈(--card-surface: Surface-Primary)を宣言する → Cardはsurface未指定のまま白で地から浮く(#150)。darkは据え置き"
|
|
707
1042
|
]
|
|
708
1043
|
},
|
|
709
1044
|
{
|
|
@@ -724,7 +1059,8 @@
|
|
|
724
1059
|
"サイドナビは既定で ec/_mypage-menu-data の mypageMenuGroups を使用。activeMenu で現在ページを強調する",
|
|
725
1060
|
"既定値は props で差し替え可能(menuGroups / breadcrumbs / bottomNavItems / headerActions)で、骨格(ヘッダー+2カラム+BottomTabBar)自体は他事業(ジョブボードのマイページ等)でも再利用できる",
|
|
726
1061
|
"breadcrumbs 省略時は「ホーム > {ユーザー}さまのマイページ > {title}」を自動生成する",
|
|
727
|
-
"マイページトップ(Dashboard)はメインカラムを白背景で持たずセクションごとにカード化する別パターンなので、この shell を使わない"
|
|
1062
|
+
"マイページトップ(Dashboard)はメインカラムを白背景で持たずセクションごとにカード化する別パターンなので、この shell を使わない",
|
|
1063
|
+
"a11y: DOM 先頭に SkipLink を標準内蔵し <main id> を制御できる(mainId 既定 main-content)。sr-only で視覚無影響。skipLink={false} で無効化"
|
|
728
1064
|
]
|
|
729
1065
|
},
|
|
730
1066
|
{
|
|
@@ -774,8 +1110,11 @@
|
|
|
774
1110
|
"path": "src/components/ec/order-summary.tsx"
|
|
775
1111
|
},
|
|
776
1112
|
{
|
|
777
|
-
"name": "
|
|
778
|
-
"path": "src/components/ec/payment-method.tsx"
|
|
1113
|
+
"name": "PaymentMethodDisplay",
|
|
1114
|
+
"path": "src/components/ec/payment-method.tsx",
|
|
1115
|
+
"subcomponents": [
|
|
1116
|
+
"CreditCardIcon"
|
|
1117
|
+
]
|
|
779
1118
|
},
|
|
780
1119
|
{
|
|
781
1120
|
"name": "ProductCard",
|
|
@@ -788,6 +1127,9 @@
|
|
|
788
1127
|
"favorite",
|
|
789
1128
|
"discount-badge",
|
|
790
1129
|
"rating"
|
|
1130
|
+
],
|
|
1131
|
+
"rules": [
|
|
1132
|
+
"captionは規格・仕様の短い自由記述(例: \"1kg / 冷蔵\")。価格表示の直下にtypo-body-xs / Text-Medium-Emphasisで表示。tags(配送方法等のenum variant)とは別物で代替不可"
|
|
791
1133
|
]
|
|
792
1134
|
},
|
|
793
1135
|
{
|
|
@@ -818,6 +1160,13 @@
|
|
|
818
1160
|
{
|
|
819
1161
|
"name": "ProductOption",
|
|
820
1162
|
"path": "src/components/ec/product-option.tsx",
|
|
1163
|
+
"formBinding": "layout",
|
|
1164
|
+
"subcomponents": [
|
|
1165
|
+
"OptionQuantity",
|
|
1166
|
+
"OptionSelect",
|
|
1167
|
+
"OptionText",
|
|
1168
|
+
"OptionImageUpload"
|
|
1169
|
+
],
|
|
821
1170
|
"variants": [
|
|
822
1171
|
"quantity",
|
|
823
1172
|
"select",
|
|
@@ -831,6 +1180,9 @@
|
|
|
831
1180
|
{
|
|
832
1181
|
"name": "RatingStars",
|
|
833
1182
|
"path": "src/components/ec/rating-stars.tsx",
|
|
1183
|
+
"subcomponents": [
|
|
1184
|
+
"SparkleIcon"
|
|
1185
|
+
],
|
|
834
1186
|
"features": [
|
|
835
1187
|
"sparkle-icon",
|
|
836
1188
|
"review-count"
|
|
@@ -852,6 +1204,7 @@
|
|
|
852
1204
|
{
|
|
853
1205
|
"name": "ReviewForm",
|
|
854
1206
|
"path": "src/components/ec/review-form.tsx",
|
|
1207
|
+
"formBinding": "none",
|
|
855
1208
|
"features": [
|
|
856
1209
|
"rating",
|
|
857
1210
|
"text",
|
|
@@ -861,6 +1214,9 @@
|
|
|
861
1214
|
{
|
|
862
1215
|
"name": "ReviewSummary",
|
|
863
1216
|
"path": "src/components/ec/review-summary.tsx",
|
|
1217
|
+
"subcomponents": [
|
|
1218
|
+
"ReviewItem"
|
|
1219
|
+
],
|
|
864
1220
|
"features": [
|
|
865
1221
|
"average-score",
|
|
866
1222
|
"star-gauge"
|
|
@@ -884,7 +1240,9 @@
|
|
|
884
1240
|
"path": "src/components/ec/product-list-item.tsx",
|
|
885
1241
|
"category": "display",
|
|
886
1242
|
"rules": [
|
|
887
|
-
"カート/注文履歴/レビュー variant を持つ商品リスト行"
|
|
1243
|
+
"カート/注文履歴/レビュー variant を持つ商品リスト行",
|
|
1244
|
+
"captionは規格・仕様の短い自由記述(例: \"1kg / 冷蔵\")。価格表示の直下にtypo-body-xs / Text-Medium-Emphasisで表示。tags(配送方法等のenum variant)とは別物",
|
|
1245
|
+
"subtotal/subtotalLabel(既定\"小計\")はcart variant専用。数量セレクタ行の右側(収まらなければ下に折り返し)に¥{カンマ区切り}で表示。BtoB/法人ECのロット購入等、商品ごとの単価×数量の内訳を明示したい場合に使う"
|
|
888
1246
|
]
|
|
889
1247
|
}
|
|
890
1248
|
]
|