mikeneko-ui 1.0.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.
@@ -0,0 +1,451 @@
1
+ {
2
+ "meta": {
3
+ "name": "mikeneko UI Design System",
4
+ "version": "2.0.0",
5
+ "base": "shadcn/ui",
6
+ "totalComponents": 45
7
+ },
8
+ "components": [
9
+ {
10
+ "name": "Accordion",
11
+ "category": "disclosure",
12
+ "shadcnPath": "ui/accordion",
13
+ "variants": ["single", "multiple"],
14
+ "subComponents": ["AccordionItem", "AccordionTrigger", "AccordionContent"],
15
+ "props": {
16
+ "type": "single | multiple",
17
+ "collapsible": "boolean"
18
+ }
19
+ },
20
+ {
21
+ "name": "Alert",
22
+ "category": "feedback",
23
+ "shadcnPath": "ui/alert",
24
+ "variants": ["default", "destructive"],
25
+ "subComponents": ["AlertTitle", "AlertDescription"],
26
+ "props": {
27
+ "variant": "default | destructive"
28
+ },
29
+ "meltaNote": "info/success/warning は default variant + カスタムクラスで表現"
30
+ },
31
+ {
32
+ "name": "AlertDialog",
33
+ "category": "overlay",
34
+ "shadcnPath": "ui/alert-dialog",
35
+ "variants": ["default"],
36
+ "subComponents": ["AlertDialogTrigger", "AlertDialogContent", "AlertDialogHeader", "AlertDialogFooter", "AlertDialogTitle", "AlertDialogDescription", "AlertDialogAction", "AlertDialogCancel"],
37
+ "props": {}
38
+ },
39
+ {
40
+ "name": "AspectRatio",
41
+ "category": "layout",
42
+ "shadcnPath": "ui/aspect-ratio",
43
+ "variants": ["1:1", "16:9", "4:3", "3:2"],
44
+ "subComponents": [],
45
+ "props": {
46
+ "ratio": "number"
47
+ }
48
+ },
49
+ {
50
+ "name": "Avatar",
51
+ "category": "data-display",
52
+ "shadcnPath": "ui/avatar",
53
+ "variants": ["image", "fallback"],
54
+ "subComponents": ["AvatarImage", "AvatarFallback"],
55
+ "props": {}
56
+ },
57
+ {
58
+ "name": "Badge",
59
+ "category": "data-display",
60
+ "shadcnPath": "ui/badge",
61
+ "variants": ["default", "secondary", "destructive", "outline"],
62
+ "subComponents": [],
63
+ "props": {
64
+ "variant": "default | secondary | destructive | outline"
65
+ }
66
+ },
67
+ {
68
+ "name": "Breadcrumb",
69
+ "category": "navigation",
70
+ "shadcnPath": "ui/breadcrumb",
71
+ "variants": ["default"],
72
+ "subComponents": ["BreadcrumbList", "BreadcrumbItem", "BreadcrumbLink", "BreadcrumbPage", "BreadcrumbSeparator", "BreadcrumbEllipsis"],
73
+ "props": {}
74
+ },
75
+ {
76
+ "name": "Button",
77
+ "category": "action",
78
+ "shadcnPath": "ui/button",
79
+ "variants": ["default", "destructive", "outline", "secondary", "ghost", "link"],
80
+ "sizes": ["default", "sm", "lg", "icon"],
81
+ "subComponents": [],
82
+ "props": {
83
+ "variant": "default | destructive | outline | secondary | ghost | link",
84
+ "size": "default | sm | lg | icon",
85
+ "disabled": "boolean",
86
+ "asChild": "boolean"
87
+ },
88
+ "meltaNote": "default=primary-500, outline=bordered sub button, ghost=subtle"
89
+ },
90
+ {
91
+ "name": "Calendar",
92
+ "category": "input",
93
+ "shadcnPath": "ui/calendar",
94
+ "variants": ["single", "range"],
95
+ "subComponents": [],
96
+ "props": {
97
+ "mode": "single | range",
98
+ "selected": "Date | DateRange"
99
+ }
100
+ },
101
+ {
102
+ "name": "Card",
103
+ "category": "layout",
104
+ "shadcnPath": "ui/card",
105
+ "variants": ["default"],
106
+ "subComponents": ["CardHeader", "CardTitle", "CardDescription", "CardContent", "CardFooter"],
107
+ "props": {},
108
+ "meltaNote": "shadow-sm がデフォルト。shadow-lg/2xl 禁止"
109
+ },
110
+ {
111
+ "name": "Carousel",
112
+ "category": "data-display",
113
+ "shadcnPath": "ui/carousel",
114
+ "variants": ["horizontal", "vertical"],
115
+ "subComponents": ["CarouselContent", "CarouselItem", "CarouselPrevious", "CarouselNext"],
116
+ "props": {
117
+ "orientation": "horizontal | vertical"
118
+ }
119
+ },
120
+ {
121
+ "name": "Chart",
122
+ "category": "data-display",
123
+ "shadcnPath": "ui/chart",
124
+ "variants": ["area", "bar", "line", "pie", "radar", "radial"],
125
+ "subComponents": ["ChartContainer", "ChartTooltip", "ChartTooltipContent", "ChartLegend", "ChartLegendContent"],
126
+ "props": {}
127
+ },
128
+ {
129
+ "name": "Checkbox",
130
+ "category": "input",
131
+ "shadcnPath": "ui/checkbox",
132
+ "variants": ["unchecked", "checked", "indeterminate", "disabled"],
133
+ "subComponents": [],
134
+ "props": {
135
+ "checked": "boolean | 'indeterminate'",
136
+ "disabled": "boolean",
137
+ "onCheckedChange": "(checked: boolean) => void"
138
+ }
139
+ },
140
+ {
141
+ "name": "Collapsible",
142
+ "category": "disclosure",
143
+ "shadcnPath": "ui/collapsible",
144
+ "variants": ["default"],
145
+ "subComponents": ["CollapsibleTrigger", "CollapsibleContent"],
146
+ "props": {
147
+ "open": "boolean",
148
+ "onOpenChange": "(open: boolean) => void"
149
+ }
150
+ },
151
+ {
152
+ "name": "Command",
153
+ "category": "input",
154
+ "shadcnPath": "ui/command",
155
+ "variants": ["default"],
156
+ "subComponents": ["CommandInput", "CommandList", "CommandEmpty", "CommandGroup", "CommandItem", "CommandSeparator"],
157
+ "props": {}
158
+ },
159
+ {
160
+ "name": "ContextMenu",
161
+ "category": "overlay",
162
+ "shadcnPath": "ui/context-menu",
163
+ "variants": ["default"],
164
+ "subComponents": ["ContextMenuTrigger", "ContextMenuContent", "ContextMenuItem", "ContextMenuSeparator", "ContextMenuSub", "ContextMenuSubTrigger", "ContextMenuSubContent"],
165
+ "props": {}
166
+ },
167
+ {
168
+ "name": "Dialog",
169
+ "category": "overlay",
170
+ "shadcnPath": "ui/dialog",
171
+ "variants": ["default"],
172
+ "subComponents": ["DialogTrigger", "DialogContent", "DialogHeader", "DialogFooter", "DialogTitle", "DialogDescription", "DialogClose"],
173
+ "props": {
174
+ "open": "boolean",
175
+ "onOpenChange": "(open: boolean) => void"
176
+ },
177
+ "meltaNote": "旧 Modal コンポーネントの置き換え"
178
+ },
179
+ {
180
+ "name": "Drawer",
181
+ "category": "overlay",
182
+ "shadcnPath": "ui/drawer",
183
+ "variants": ["default"],
184
+ "subComponents": ["DrawerTrigger", "DrawerContent", "DrawerHeader", "DrawerFooter", "DrawerTitle", "DrawerDescription", "DrawerClose"],
185
+ "props": {}
186
+ },
187
+ {
188
+ "name": "DropdownMenu",
189
+ "category": "overlay",
190
+ "shadcnPath": "ui/dropdown-menu",
191
+ "variants": ["default"],
192
+ "subComponents": ["DropdownMenuTrigger", "DropdownMenuContent", "DropdownMenuItem", "DropdownMenuSeparator", "DropdownMenuLabel", "DropdownMenuGroup", "DropdownMenuSub", "DropdownMenuSubTrigger", "DropdownMenuSubContent"],
193
+ "props": {},
194
+ "meltaNote": "旧 Dropdown コンポーネントの置き換え"
195
+ },
196
+ {
197
+ "name": "HoverCard",
198
+ "category": "overlay",
199
+ "shadcnPath": "ui/hover-card",
200
+ "variants": ["default"],
201
+ "subComponents": ["HoverCardTrigger", "HoverCardContent"],
202
+ "props": {}
203
+ },
204
+ {
205
+ "name": "Input",
206
+ "category": "input",
207
+ "shadcnPath": "ui/input",
208
+ "variants": ["default", "disabled", "error"],
209
+ "subComponents": [],
210
+ "props": {
211
+ "type": "string",
212
+ "placeholder": "string",
213
+ "disabled": "boolean"
214
+ },
215
+ "meltaNote": "旧 TextField コンポーネントの置き換え"
216
+ },
217
+ {
218
+ "name": "InputOTP",
219
+ "category": "input",
220
+ "shadcnPath": "ui/input-otp",
221
+ "variants": ["default"],
222
+ "subComponents": ["InputOTPGroup", "InputOTPSlot", "InputOTPSeparator"],
223
+ "props": {
224
+ "maxLength": "number"
225
+ }
226
+ },
227
+ {
228
+ "name": "Label",
229
+ "category": "input",
230
+ "shadcnPath": "ui/label",
231
+ "variants": ["default"],
232
+ "subComponents": [],
233
+ "props": {
234
+ "htmlFor": "string"
235
+ }
236
+ },
237
+ {
238
+ "name": "Menubar",
239
+ "category": "navigation",
240
+ "shadcnPath": "ui/menubar",
241
+ "variants": ["default"],
242
+ "subComponents": ["MenubarMenu", "MenubarTrigger", "MenubarContent", "MenubarItem", "MenubarSeparator", "MenubarSub", "MenubarSubTrigger", "MenubarSubContent"],
243
+ "props": {}
244
+ },
245
+ {
246
+ "name": "NavigationMenu",
247
+ "category": "navigation",
248
+ "shadcnPath": "ui/navigation-menu",
249
+ "variants": ["default"],
250
+ "subComponents": ["NavigationMenuList", "NavigationMenuItem", "NavigationMenuTrigger", "NavigationMenuContent", "NavigationMenuLink"],
251
+ "props": {}
252
+ },
253
+ {
254
+ "name": "Pagination",
255
+ "category": "navigation",
256
+ "shadcnPath": "ui/pagination",
257
+ "variants": ["default"],
258
+ "subComponents": ["PaginationContent", "PaginationItem", "PaginationLink", "PaginationPrevious", "PaginationNext", "PaginationEllipsis"],
259
+ "props": {}
260
+ },
261
+ {
262
+ "name": "Popover",
263
+ "category": "overlay",
264
+ "shadcnPath": "ui/popover",
265
+ "variants": ["default"],
266
+ "subComponents": ["PopoverTrigger", "PopoverContent"],
267
+ "props": {}
268
+ },
269
+ {
270
+ "name": "Progress",
271
+ "category": "feedback",
272
+ "shadcnPath": "ui/progress",
273
+ "variants": ["default", "indeterminate"],
274
+ "subComponents": [],
275
+ "props": {
276
+ "value": "number"
277
+ }
278
+ },
279
+ {
280
+ "name": "RadioGroup",
281
+ "category": "input",
282
+ "shadcnPath": "ui/radio-group",
283
+ "variants": ["default"],
284
+ "subComponents": ["RadioGroupItem"],
285
+ "props": {
286
+ "value": "string",
287
+ "onValueChange": "(value: string) => void"
288
+ },
289
+ "meltaNote": "旧 Radio コンポーネントの置き換え"
290
+ },
291
+ {
292
+ "name": "ScrollArea",
293
+ "category": "layout",
294
+ "shadcnPath": "ui/scroll-area",
295
+ "variants": ["default"],
296
+ "subComponents": ["ScrollBar"],
297
+ "props": {}
298
+ },
299
+ {
300
+ "name": "Select",
301
+ "category": "input",
302
+ "shadcnPath": "ui/select",
303
+ "variants": ["default"],
304
+ "subComponents": ["SelectTrigger", "SelectValue", "SelectContent", "SelectItem", "SelectGroup", "SelectLabel", "SelectSeparator"],
305
+ "props": {
306
+ "value": "string",
307
+ "onValueChange": "(value: string) => void"
308
+ }
309
+ },
310
+ {
311
+ "name": "Separator",
312
+ "category": "layout",
313
+ "shadcnPath": "ui/separator",
314
+ "variants": ["horizontal", "vertical"],
315
+ "subComponents": [],
316
+ "props": {
317
+ "orientation": "horizontal | vertical",
318
+ "decorative": "boolean"
319
+ },
320
+ "meltaNote": "旧 Divider コンポーネントの置き換え"
321
+ },
322
+ {
323
+ "name": "Sheet",
324
+ "category": "overlay",
325
+ "shadcnPath": "ui/sheet",
326
+ "variants": ["top", "right", "bottom", "left"],
327
+ "subComponents": ["SheetTrigger", "SheetContent", "SheetHeader", "SheetFooter", "SheetTitle", "SheetDescription", "SheetClose"],
328
+ "props": {
329
+ "side": "top | right | bottom | left"
330
+ }
331
+ },
332
+ {
333
+ "name": "Sidebar",
334
+ "category": "navigation",
335
+ "shadcnPath": "ui/sidebar",
336
+ "variants": ["default", "compact", "floating", "inset"],
337
+ "subComponents": ["SidebarProvider", "SidebarTrigger", "SidebarHeader", "SidebarContent", "SidebarFooter", "SidebarGroup", "SidebarGroupLabel", "SidebarGroupContent", "SidebarMenu", "SidebarMenuItem", "SidebarMenuButton"],
338
+ "props": {
339
+ "side": "left | right",
340
+ "variant": "sidebar | floating | inset",
341
+ "collapsible": "offcanvas | icon | none"
342
+ }
343
+ },
344
+ {
345
+ "name": "Skeleton",
346
+ "category": "feedback",
347
+ "shadcnPath": "ui/skeleton",
348
+ "variants": ["default"],
349
+ "subComponents": [],
350
+ "props": {}
351
+ },
352
+ {
353
+ "name": "Slider",
354
+ "category": "input",
355
+ "shadcnPath": "ui/slider",
356
+ "variants": ["single", "range"],
357
+ "subComponents": [],
358
+ "props": {
359
+ "value": "number[]",
360
+ "min": "number",
361
+ "max": "number",
362
+ "step": "number"
363
+ }
364
+ },
365
+ {
366
+ "name": "Sonner",
367
+ "category": "feedback",
368
+ "shadcnPath": "ui/sonner",
369
+ "variants": ["success", "error", "warning", "info"],
370
+ "subComponents": ["Toaster"],
371
+ "props": {},
372
+ "meltaNote": "旧 Toast コンポーネントの置き換え。toast() 関数で呼び出し"
373
+ },
374
+ {
375
+ "name": "Switch",
376
+ "category": "input",
377
+ "shadcnPath": "ui/switch",
378
+ "variants": ["on", "off", "disabled"],
379
+ "subComponents": [],
380
+ "props": {
381
+ "checked": "boolean",
382
+ "onCheckedChange": "(checked: boolean) => void",
383
+ "disabled": "boolean"
384
+ },
385
+ "meltaNote": "旧 Toggle (switch) コンポーネントの置き換え"
386
+ },
387
+ {
388
+ "name": "Table",
389
+ "category": "data-display",
390
+ "shadcnPath": "ui/table",
391
+ "variants": ["default"],
392
+ "subComponents": ["TableHeader", "TableBody", "TableFooter", "TableHead", "TableRow", "TableCell", "TableCaption"],
393
+ "props": {}
394
+ },
395
+ {
396
+ "name": "Tabs",
397
+ "category": "navigation",
398
+ "shadcnPath": "ui/tabs",
399
+ "variants": ["default"],
400
+ "subComponents": ["TabsList", "TabsTrigger", "TabsContent"],
401
+ "props": {
402
+ "value": "string",
403
+ "defaultValue": "string",
404
+ "onValueChange": "(value: string) => void"
405
+ }
406
+ },
407
+ {
408
+ "name": "Textarea",
409
+ "category": "input",
410
+ "shadcnPath": "ui/textarea",
411
+ "variants": ["default", "disabled"],
412
+ "subComponents": [],
413
+ "props": {
414
+ "placeholder": "string",
415
+ "disabled": "boolean"
416
+ }
417
+ },
418
+ {
419
+ "name": "Toggle",
420
+ "category": "input",
421
+ "shadcnPath": "ui/toggle",
422
+ "variants": ["default", "outline"],
423
+ "subComponents": [],
424
+ "props": {
425
+ "variant": "default | outline",
426
+ "size": "default | sm | lg",
427
+ "pressed": "boolean"
428
+ }
429
+ },
430
+ {
431
+ "name": "ToggleGroup",
432
+ "category": "input",
433
+ "shadcnPath": "ui/toggle-group",
434
+ "variants": ["single", "multiple"],
435
+ "subComponents": ["ToggleGroupItem"],
436
+ "props": {
437
+ "type": "single | multiple",
438
+ "variant": "default | outline"
439
+ }
440
+ },
441
+ {
442
+ "name": "Tooltip",
443
+ "category": "overlay",
444
+ "shadcnPath": "ui/tooltip",
445
+ "variants": ["default"],
446
+ "subComponents": ["TooltipProvider", "TooltipTrigger", "TooltipContent"],
447
+ "props": {},
448
+ "meltaNote": "TooltipProvider でアプリ全体をラップ必須"
449
+ }
450
+ ]
451
+ }
@@ -0,0 +1,196 @@
1
+ # Prohibited Patterns
2
+
3
+ > このファイルがすべての禁止パターンの正規版(SSOT)です。他ファイルからはここを参照してください。
4
+
5
+ ---
6
+
7
+ ## カラー
8
+
9
+ | 禁止 | 理由 | 代替 |
10
+ |------|------|------|
11
+ | `text-black` | 純黒はコントラストが強すぎて長時間の利用で目が疲れる | `text-slate-900`(#0f172a) |
12
+ | `bg-gray-300` 以上の暗い背景 | テキストのコントラスト確保が困難になる | `bg-gray-50` 〜 `bg-gray-200` |
13
+ | `bg-primary-400`(薄いアクセント) | CTAとして弱く、目立たない | `bg-primary-500` |
14
+ | `text-gray-400` for body text | WCAG不適合(コントラスト比不足) | `text-body`(#3d4b5f) |
15
+ | `border-gray-100` | 薄すぎて境界が見えない | `border-slate-200`(#e2e8f0) |
16
+ | `bg-green-*` | emeraldで統一する | `bg-emerald-*` |
17
+ | `bg-yellow-*` | amberで統一する | `bg-amber-*` |
18
+ | `bg-rose-*` | redで統一する | `bg-red-*` |
19
+ | `text-blue-*` for links | primaryで統一する | `text-primary-500` |
20
+ | 色だけで情報伝達 | 色覚多様性への非対応。アクセシビリティ違反 | アイコン/テキストを必ず併用 |
21
+
22
+ ---
23
+
24
+ ## 哲学由来の禁止(melta UI)
25
+
26
+ > 全項目は `foundations/design_philosophy.md` の「Avoid」セクションを参照。以下は実装上とくに重要な項目のみ抜粋。
27
+
28
+ | 禁止 | 理由 | 代替 |
29
+ |------|------|------|
30
+ | 過剰なアニメーション(常時ループ等) | 操作の邪魔になり、認知コストを増加させる | 150〜300ms の状態変化フィードバックに限定 |
31
+
32
+ ---
33
+
34
+ ## モーション
35
+
36
+ | 禁止 | 理由 | 代替 |
37
+ |------|------|------|
38
+ | `duration-500` 以上 | 操作が鈍く感じる(Progress フィルバーは例外) | `duration-300` 以下 |
39
+ | `prefers-reduced-motion` 無視 | アクセシビリティ違反 | メディアクエリで対応 |
40
+
41
+ ---
42
+
43
+ ## タイポグラフィ
44
+
45
+ | 禁止 | 理由 | 代替 |
46
+ |------|------|------|
47
+ | `tracking-tight` | 日本語の可読性が低下する | `tracking-normal` 以上(本文2%、見出し1%) |
48
+ | `text-xs` for body text | 本文には小さすぎて読みづらい | `text-base`(16px) |
49
+ | `font-light`(300) | 細すぎて可読性が低い | `font-normal`(400)以上 |
50
+ | プレースホルダーのみでラベル省略 | 入力開始で消え、目的がわからなくなる | `<label>` を必ず使用 |
51
+
52
+ ---
53
+
54
+ ## スペーシング・レイアウト
55
+
56
+ | 禁止 | 理由 | 代替 |
57
+ |------|------|------|
58
+ | `rounded-none` on cards | UIの統一感を損なう | `rounded-xl`(12px) |
59
+ | `shadow-lg` / `shadow-2xl` | 影が強すぎてノイズになる | `shadow-sm` 〜 `shadow-md`(オーバーレイ: `shadow-xl`) |
60
+ | `py-0.5` for buttons | タップターゲットが小さすぎる | `h-8` 以上(S: `h-8` / M: `h-10` / L: `h-12`) |
61
+ | `p-0` on cards | コンテンツが窮屈になる | `p-5` 以上 |
62
+ | `gap-0` between sections | セクションの区切りが不明瞭 | `gap-6` 以上 |
63
+ | `m-0` for page content | ページ端にコンテンツが張り付く | `px-6 py-8` 以上 |
64
+ | サイドバーに暗い背景色 | メインコンテンツとのコントラストが強すぎる | `bg-white` + ボーダー |
65
+ | サイドバー幅の非標準値(`w-60` 等) | 実装ごとにバラつきが出る | `w-64`(標準)or `w-16`(コンパクト) |
66
+ | ナビアイテムの `rounded-xl` | ボタン等他コンポーネントとの一貫性を損なう | `rounded-lg` |
67
+ | ナビアイコン `w-7 h-7` 以上 | DS標準アイコンサイズからの逸脱 | `w-5 h-5` |
68
+ | Drawer のフォーカストラップ省略 | キーボードユーザーが背面要素を操作してしまう | フォーカストラップを実装 |
69
+ | `aria-current="page"` 省略 | スクリーンリーダーが現在ページを識別できない | Active ナビアイテムに必ず付与 |
70
+ | 3列以上の複雑なレイアウト | 認知負荷が高い | サイドバー + メインの2列 |
71
+
72
+ ---
73
+
74
+ ## AI生成パターンの排除
75
+
76
+ > AI(LLM)がUIを生成する際に頻出する「それっぽい」装飾パターンを明示的に禁止する。人間がデザインしたUIとの差別化を図り、melta UI の「静謐・精緻・温もり」を守るためのセクション。
77
+
78
+ | 禁止 | 理由 | 代替 |
79
+ |------|------|------|
80
+ | カード上部/左部のカラーバー(`border-t-4` や色付き `div`) | AI生成UIの典型パターン。装飾過剰で汎用性が低い | ボーダー(`border border-slate-200`)のみでカードを構成する |
81
+ | 左端/上端のカラーストライプ(`border-l-4 border-*-500`) | Alert含め全コンポーネントで禁止 | `border border-*-200 rounded-lg` で全周ボーダー |
82
+
83
+ ---
84
+
85
+ ## コンポーネント
86
+
87
+ ### ボタン
88
+
89
+ | 禁止 | 理由 | 代替 |
90
+ |------|------|------|
91
+ | 同一スタイルボタンの並列配置 | 重要度の区別がつかない(Neutralのみ例外) | 階層の異なるボタンを組み合わせる |
92
+ | Lighted Buttonの単独使用 | トグル状態の対比がないと意味不明 | Neutralとペアで使用する |
93
+ | `aria-label` なしのアイコンボタン | 操作内容がスクリーンリーダーに伝わらない | `aria-label="閉じる"` 等を付与 |
94
+ | 44px未満のタップ領域 | 操作困難(インラインテキストリンクを除く) | パディングでタップ領域を確保 |
95
+
96
+ ### フォーム
97
+
98
+ | 禁止 | 理由 | 代替 |
99
+ |------|------|------|
100
+ | `<select>` の `appearance-none` 省略 | ネイティブ矢印はブラウザ間で位置・余白が不安定 | `appearance-none` + `pr-10` + カスタムSVGシェブロン(`absolute right-3 top-1/2 -translate-y-1/2`) |
101
+ | ラベルなしのフォーム入力 | スクリーンリーダーが目的を読み上げられない | `<label>` を `for` 属性で関連付け |
102
+ | ラベルの横配置 | モバイルで破綻し、視線移動が増える | ラベルは入力欄の上 |
103
+ | グループ時の `<fieldset>` / `<legend>` の省略 | グループの目的が伝わらない | 必ず使用する |
104
+ | エラーメッセージの自動非表示 | ユーザーが読む前に消える | 修正されるまで表示 |
105
+ | 色のみによるエラー状態の伝達 | 色覚多様性への非対応 | ボーダー色 + エラーアイコン + テキスト |
106
+ | カード直下の `<fieldset>` + `<legend>` | `<legend>` のブラウザデフォルト描画がカードの `border` と干渉し、見出しがボーダー上に浮いて視覚的に破綻する | カードレベルのセクション見出しは `<div>` + `<h2>` を使用。`<fieldset>` / `<legend>` はカード内部のフォームコントロールグループに限定する |
107
+ | 日付セレクト(年月日)の均等幅(`grid-cols-3` 等) | 月・日セレクトが不必要に広くなり選択しにくい | `flex` レイアウトで年 `w-28`、月・日 `w-20` に固定。年/月/日のサフィックスラベル付与を推奨 |
108
+ | チェックのみで確定する設計 | 意図しない確定が起きる | 確認ボタンを必ず配置 |
109
+ | 入力途中の自動フォーカス移動 | ユーザーを混乱させる | ユーザー操作に任せる |
110
+ | 離れた位置のエラー表示 | フィールドとの対応がわからない | フィールド直下に表示 |
111
+
112
+ ### モーダル
113
+
114
+ | 禁止 | 理由 | 代替 |
115
+ |------|------|------|
116
+ | フォーカストラップなしのモーダル | キーボードユーザーがモーダル外に出てしまう | Tab/Shift+Tabがモーダル内を循環 |
117
+ | Escキーで閉じられないモーダル | ユーザーが脱出できない | Escキーで閉じる |
118
+ | 閉じる手段がないモーダル | ユーザーが操作を中断できない | 閉じるボタン + Esc + オーバーレイクリック |
119
+ | `role="dialog"` の省略 | スクリーンリーダーがモーダルを認識できない | 必ず付与 |
120
+ | オーバーレイなしのモーダル | 背景との分離が不明確 | `bg-black/50` のオーバーレイ |
121
+ | 2階層以上のモーダルネスト | UXが複雑になりすぎる | 設計を見直す |
122
+
123
+ ### リスト
124
+
125
+ | 禁止 | 理由 | 代替 |
126
+ |------|------|------|
127
+ | テキスト行数と合わない固定高さ | テキストが切れる or 余白が不均等 | 可変高さにする |
128
+ | 色のみによる選択状態の伝達 | 色覚多様性への非対応 | ボーダー太さ + 背景スタイルを併用 |
129
+ | ジェスチャー操作のみで代替手段がない | キーボード/スクリーンリーダーで操作不可 | ボタンによる代替操作を提供 |
130
+ | アイコン/サムネイル間にボーダー配置 | 情報の断絶を誤解させる | ボーダーはアイテム間のみ |
131
+
132
+ ### テーブル
133
+
134
+ | 禁止 | 理由 | 代替 |
135
+ |------|------|------|
136
+ | レイアウト目的での `<table>` 使用 | セマンティクス違反 | `flex` / `grid` を使う |
137
+ | `<th>` の `scope` 省略 | ヘッダーとデータの関係が不明確 | `scope="col"` を付与 |
138
+
139
+ ### タグ・チップ
140
+
141
+ | 禁止 | 理由 | 代替 |
142
+ |------|------|------|
143
+ | ×ボタンなしの削除可能タグ | キーボードのみでは削除操作を発見できない | ×ボタンを必ず表示する |
144
+ | 24px 未満の×ボタンタップ領域 | 操作困難。モバイルで誤タップが頻発する | `p-0.5` + SVG `w-3 h-3`(実質24px以上を確保) |
145
+ | `aria-label` なしの×ボタン | スクリーンリーダーがボタンの目的を読み上げられない | `aria-label="{タグ名}を削除"` を付与 |
146
+ | Filter Chip の `aria-selected` 省略 | 選択状態がスクリーンリーダーに伝わらない | `aria-selected="true"` / `"false"` を付与 |
147
+ | Badge と Tag の混同使用 | Badge はステータス表示(単方向)、Tag はユーザー管理メタデータ(双方向) | 用途に応じて `badge.md` / `tag.md` を使い分ける |
148
+
149
+ ### ディバイダー
150
+
151
+ | 禁止 | 理由 | 代替 |
152
+ |------|------|------|
153
+ | `<div>` + `border-b` で水平区切り | セマンティクス違反。支援技術が区切りを認識できない | `<hr>` or `role="separator"` |
154
+ | `border-gray-100` でディバイダー | 薄すぎて境界が見えない | `border-slate-200` |
155
+ | `border-slate-400` 以上の区切り線 | 線が強すぎてノイズになる | `border-slate-200`(標準)/ `border-slate-300`(強調) |
156
+
157
+ ### ステッパー
158
+
159
+ | 禁止 | 理由 | 代替 |
160
+ |------|------|------|
161
+ | 色だけでステップ状態を区別 | 色覚多様性への非対応 | アイコン + ボーダー + 背景色を併用 |
162
+ | `aria-current="step"` の省略 | スクリーンリーダーが現在ステップを識別できない | Active ステップに必ず付与 |
163
+ | Indicator `w-6 h-6` 未満のサイズ | タップターゲットが小さすぎる | `w-8 h-8`(標準)/ `w-6 h-6`(コンパクト最小) |
164
+ | Connector に `bg-slate-400` 以上 | 線が強すぎてノイズになる | `bg-primary-500`(完了区間)/ `bg-slate-200`(未着手区間) |
165
+
166
+ ### Date Picker
167
+
168
+ | 禁止 | 理由 | 代替 |
169
+ |------|------|------|
170
+ | `<input type="date">` のネイティブ表示 | ブラウザ間で表示が不統一 | カスタム Date Picker を使用 |
171
+ | カレンダーポップアップに `shadow-lg` 以上 | 影が強すぎてノイズになる | `shadow-md` |
172
+ | `z-20` 以外の z-index | Dropdown レイヤーの統一が崩れる | `z-20`(Dropdown レイヤー) |
173
+ | 色だけで Today を表示 | 色覚多様性への非対応 | `font-semibold` を併用 |
174
+ | キーボードナビゲーション省略 | キーボードユーザーが操作不可 | 矢印 + Enter + Escape を実装 |
175
+ | 曜日ヘッダー省略 | 日付の曜日が判別できない | 日〜土のラベルを必ず表示 |
176
+
177
+ ### スケルトン・ローディング
178
+
179
+ | 禁止 | 理由 | 代替 |
180
+ |------|------|------|
181
+ | スケルトンに `bg-slate-200` 以外の色 | DS統一から外れる | `bg-slate-200` 固定 |
182
+ | 常時回転スピナーのみの全画面表示 | 進捗が伝わらず不安を与える | スケルトン or プログレスバーを併用 |
183
+ | `aria-busy="true"` の省略 | スクリーンリーダーがローディング状態を認識できない | コンテナに `aria-busy="true"` + `role="status"` |
184
+ | 実コンテンツ到着後の `aria-busy` 未解除 | ローディング完了が伝わらない | `aria-busy="false"` に変更する |
185
+
186
+ ---
187
+
188
+ ## アクセシビリティ(全般)
189
+
190
+ | 禁止 | 理由 | 代替 |
191
+ |------|------|------|
192
+ | `outline: none` without ring | フォーカスインジケーターが消える | `focus:ring-2 focus:ring-primary-500/50` |
193
+ | `tabindex` > 0 | フォーカス順序が混乱する | DOM順に従い、`tabindex="0"` or `-1` のみ使用 |
194
+ | 時間制限のある操作 | ユーザーが操作を完了できない可能性 | 時間制限を設けない |
195
+ | 装飾的アニメーションの多用 | 動きに敏感なユーザーへの配慮不足 | 状態変化のフィードバックのみ |
196
+ | 200%拡大時のテキスト切り詰め | コンテンツにアクセスできなくなる | レスポンシブに対応 |