ksk-design-system 2.11.0 → 2.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.
Files changed (71) hide show
  1. package/MIGRATION.md +20 -0
  2. package/NATIVE_RECIPES.md +15 -0
  3. package/README.md +15 -0
  4. package/RELEASE.md +17 -0
  5. package/contracts/components.json +247 -30
  6. package/contracts/product-theme-overrides.json +21 -4
  7. package/contracts/token-hex-cache.json +8 -1
  8. package/dist/class-names.js +1 -1
  9. package/dist/index.js +6069 -5087
  10. package/dist/native/ui.js +1088 -769
  11. package/dist/{native-BQg-H087.js → native-CSERz4sr.js} +42 -0
  12. package/dist/native.js +1 -1
  13. package/dist/{server-variants-Bkhu25WC.js → server-variants-B2IA1PnQ.js} +5 -2
  14. package/dist/types/components/patterns/_internal/calendar-shared.d.ts +22 -0
  15. package/dist/types/components/patterns/add-tile.d.ts +25 -0
  16. package/dist/types/components/patterns/agenda-list.d.ts +51 -0
  17. package/dist/types/components/patterns/banner.d.ts +3 -1
  18. package/dist/types/components/patterns/code-display.d.ts +39 -0
  19. package/dist/types/components/patterns/commerce/bottom-tab-bar.d.ts +27 -2
  20. package/dist/types/components/patterns/commerce/mobile-tab-bar.d.ts +20 -3
  21. package/dist/types/components/patterns/detail-sheet-scaffold.d.ts +6 -0
  22. package/dist/types/components/patterns/feature-comparison-table.d.ts +31 -0
  23. package/dist/types/components/patterns/kanban-column.d.ts +36 -0
  24. package/dist/types/components/patterns/mobile-app-shell.d.ts +7 -1
  25. package/dist/types/components/patterns/mobile-floating-action-button.d.ts +12 -1
  26. package/dist/types/components/patterns/month-calendar.d.ts +85 -0
  27. package/dist/types/components/patterns/screen.d.ts +56 -2
  28. package/dist/types/components/patterns/selectable-tile.d.ts +53 -0
  29. package/dist/types/components/patterns/settings-section.d.ts +13 -2
  30. package/dist/types/components/patterns/share-buttons.d.ts +14 -2
  31. package/dist/types/components/patterns/shells/admin-shell.d.ts +32 -1
  32. package/dist/types/components/patterns/sidebar-nav.d.ts +10 -1
  33. package/dist/types/components/patterns/stat-card.d.ts +6 -1
  34. package/dist/types/components/patterns/tag-input.d.ts +20 -2
  35. package/dist/types/components/ui/alert.d.ts +5 -3
  36. package/dist/types/components/ui/avatar.d.ts +13 -1
  37. package/dist/types/components/ui/card.d.ts +12 -1
  38. package/dist/types/components/ui/container.d.ts +1 -1
  39. package/dist/types/components/ui/emoji-icon.d.ts +31 -0
  40. package/dist/types/components/ui/highlight.d.ts +32 -0
  41. package/dist/types/components/ui/icon-badge.d.ts +5 -1
  42. package/dist/types/components/ui/input.d.ts +13 -1
  43. package/dist/types/components/ui/sheet.d.ts +5 -2
  44. package/dist/types/components/ui/textarea.d.ts +8 -1
  45. package/dist/types/components/ui/toast.d.ts +15 -2
  46. package/dist/types/index.d.ts +22 -2
  47. package/dist/types/lib/server-variants/inline-field.d.ts +16 -0
  48. package/dist/types/lib/use-soft-keyboard-focus.d.ts +28 -0
  49. package/dist/types/native/components/AddTile.d.ts +22 -0
  50. package/dist/types/native/components/AutoGrowTextarea.d.ts +2 -0
  51. package/dist/types/native/components/Avatar.d.ts +2 -2
  52. package/dist/types/native/components/Card.d.ts +11 -3
  53. package/dist/types/native/components/CodeDisplay.d.ts +28 -0
  54. package/dist/types/native/components/EmojiIcon.d.ts +16 -0
  55. package/dist/types/native/components/FeatureComparisonTable.d.ts +32 -0
  56. package/dist/types/native/components/Highlight.d.ts +14 -0
  57. package/dist/types/native/components/IconBadge.d.ts +5 -1
  58. package/dist/types/native/components/Input.d.ts +7 -0
  59. package/dist/types/native/components/SettingsSection.d.ts +6 -2
  60. package/dist/types/native/components/Textarea.d.ts +2 -0
  61. package/dist/types/native/components/index.d.ts +8 -2
  62. package/dist/types/native/components/use-reduce-motion.d.ts +10 -3
  63. package/dist/types/tokens/native/themes.d.ts +42 -0
  64. package/package.json +1 -1
  65. package/src/components/COMPONENT_LOOKUP.md +36 -27
  66. package/src/native/COMPONENT_LOOKUP.md +6 -1
  67. package/src/styles/product-theme.css +25 -2
  68. package/src/styles/semantic.css +11 -0
  69. package/src/styles/sheet-keyboard.css +15 -4
  70. package/src/styles/source-safelist.css +85 -10
  71. package/tokens.json +7 -0
package/MIGRATION.md CHANGED
@@ -3,6 +3,16 @@
3
3
  メジャーバージョン間の移行ガイド。
4
4
  patch / minor は原則破壊変更なし、自動アップグレード可(例外: **v1.34.0 で npm パッケージ名を変更**。import の置換が必要。下記参照)。
5
5
 
6
+ ## v2.13.0 の導入注意
7
+
8
+ 以下はv2.13.0でnpm公開する変更の導入注意です。consumerへの展開・アプリ配布は今回の対象に含まず、次回のまとめ展開で反映します。
9
+
10
+ - **下部ナビ・FABの入力中表示(#700)**: `MobileTabBar` / `MobileFloatingActionButton` は既定の `keyboardBehavior="hide"` での非表示条件が増えます。`BottomTabBar` の既定stayは維持し、hideを明示した場合だけ同じ検知を使います。viewportの縮小に加え、タッチ主体の端末でテキスト入力にフォーカスした時点でも非表示になります。pointer/hover能力では物理キーボード接続を判別できないため、この先行非表示が不要なら `hideOnInputFocus={false}` でviewport検知だけにできます。従来どおり表示位置を変えたくない画面は `keyboardBehavior="stay"` を明示してください。
11
+ - **下側Sheetの入力時高さ(#706)**: `safeArea={true}`(既定)の通常bottom Sheetは、キーボード表示時に上端のsafe-areaも差し引き、ステータスバー・ノッチへの侵入を避けます。独自の全画面配置でこの補正が不要なら `safeArea={false}` を指定してください。snap Sheetは今回の高さ変更の対象外です。
12
+ - **画面・分類・配置編集(#701–#703)**: Screenへ上端safe-area、svh/fill、768px以上の中央カード、landmark省略を追加します。fillの中央カードは親の高さを尊重します。KanbanColumnの分類色指定と、選択・ドラッグ・矢印移動用SelectableTileも追加します。これらの追加APIは任意指定です。
13
+ - **予定のモバイル表示(#704)**: MonthCalendarへ週表示、予定一覧AgendaListを追加します。週表示は選択日を優先し、月外の初期選択日や内部の月またぎ移動でも表示週・月見出しを揃えます。既定の月表示は維持します。
14
+ - **管理画面のモバイルナビ(#705)**: AdminShellへ任意のモバイルドロワーを追加します。リンク選択時の自動closeは `closeMobileDrawerOnNavigate={true}` の明示指定で有効にし、既定falseでは既存の挙動を維持します。
15
+
6
16
  <!-- deprecations:start(自動生成・手で編集しない) -->
7
17
 
8
18
  ## 非推奨 API 一覧
@@ -39,6 +49,16 @@ npx ksk-ds check-migration ./src
39
49
 
40
50
  ---
41
51
 
52
+ ## v2.12.0
53
+
54
+ 追加のみで、APIの削除・改名はありません。propsを渡さなければ従来と同じ表示です。次の3点は取り込み時に確認してください。
55
+
56
+ - ShareButtonsのLINEの塗りボタンは、文字が黒になります。白だと#06C755上で約2.2:1となりAAに届かないためです。
57
+ - IconBadgeのsuccess / warningは、アイコン色がText-*に変わります。非テキストの3:1を満たすためで、見た目が少し濃くなります。
58
+ - inline系のAlertが `title` / `description` / `icon` propを描画するようになりました。以前は空の枠になっていたため、該当箇所の表示を確認してください。
59
+
60
+ ---
61
+
42
62
  ## v2.11.0
43
63
 
44
64
  追加のみで、APIの削除・改名はありません。propsを渡さなければ従来と同じ表示です。次の2点は取り込み時に確認してください。
package/NATIVE_RECIPES.md CHANGED
@@ -17,6 +17,21 @@ RN 側の公開 export 一覧は `src/native/COMPONENT_LOOKUP.md` で確認で
17
17
  import { Button, Screen, PhotoHero } from "ksk-design-system/native/ui"
18
18
  ```
19
19
 
20
+ ## OS のモーション設定
21
+
22
+ ```tsx
23
+ import { useReduceMotion } from "ksk-design-system/native/ui"
24
+
25
+ const { reduceMotion, resolved } = useReduceMotion()
26
+ const suppressMotion = !resolved || reduceMotion
27
+ ```
28
+
29
+ `resolved` は OS 設定の初回取得または設定変更イベントで `true` になります。
30
+ 取得前・取得失敗時は `false` のため、`suppressMotion` の間は演出を開始せず、
31
+ 実行中の演出は停止して元の表示へ戻してください。設定変更は即時反映され、
32
+ 遅れて届いた初回取得結果では上書きしません。アンマウント時には購読を解除します。
33
+ この hook は `native/ui` の公開 API です。トークン専用の `native` エントリには含みません。
34
+
20
35
  ## Expo Router / React Navigation bottom tabs
21
36
 
22
37
  Expo Router の `<Tabs>` では `createExpoRouterTabBar` を渡します。アイコンは各 screen の `tabBarIcon` をそのまま使えるため、consumer 側で floating tab bar を組み直す必要はありません。
package/README.md CHANGED
@@ -540,6 +540,21 @@ import { BottomTabBar } from "ksk-design-system"
540
540
 
541
541
  React Native は **0.78 以上**(React 19 を同梱する最初の RN)が必要です。
542
542
 
543
+ ### OS のモーション設定
544
+
545
+ ```tsx
546
+ import { useReduceMotion } from "ksk-design-system/native/ui"
547
+
548
+ const { reduceMotion, resolved } = useReduceMotion()
549
+ const suppressMotion = !resolved || reduceMotion
550
+ ```
551
+
552
+ `resolved` は OS 設定の初回取得または設定変更イベントで `true` になります。
553
+ 取得前・取得失敗時は `false` のため、`suppressMotion` の間は演出を開始せず、
554
+ 実行中の演出は停止して元の表示へ戻してください。設定変更は即時反映され、
555
+ 遅れて届いた初回取得結果では上書きしません。アンマウント時には購読を解除します。
556
+ この hook は `native/ui` の公開 API です。トークン専用の `native` エントリには含みません。
557
+
543
558
  `ksk-design-system/native/ui` から直接 RN 用コンポーネント export(134 個)を import できます。iOS 26 の **Liquid Glass** にも対応:
544
559
 
545
560
  ```tsx
package/RELEASE.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  `ksk-design-system` のリリーススケジュール・運用ルール。
4
4
 
5
+ ## v2.12.0(2026-10-17)
6
+
7
+ 2.11.0以降に、consumer側の見た目の上書きをなくすためのAPI・部品を22件追加したminorリリース。追加のみで、propsを渡さなければ従来と同じ表示です。
8
+
9
+ - 新部品を7つ追加しました。`EmojiIcon`(#676)、`AddTile`(#678)、`MonthCalendar` / `KanbanColumn`(#679)、`CodeDisplay`(#686)、`FeatureComparisonTable`(#687)、`Highlight`(#692)です。
10
+ - Input / Textareaに枠なしでその場編集できる `variant="inline"` / `"inline-title"` を追加しました(#675)。
11
+ - Cardに `selected` / `elevation`、StatCardに `elevation`、Avatarに `size` を追加しました(#677・#688・#689)。
12
+ - SidebarNavに `tone="inverse"`、AdminShellに `sidebarTone` を追加し、暗色サイドバーにできるようにしました(#680)。
13
+ - MobileTabBarに `keyboardBehavior` / `bottomOffsetExtra`、MobileAppShellに `bottomPaddingExtra`、nativeの上端safe-area用の `--Safe-Area-Inset-Top` を追加しました(#681・#682)。
14
+ - Bannerに `density="compact"` / `layout="bar"`、IconBadgeに `tone`、SettingsSectionに `icon`、SettingsListRowに `showChevron` を追加しました(#683・#684・#690)。
15
+ - ShareButtonsに `message` / `layout="block"` / `labels` とLINEのhover・押下・前景トークンを追加しました(#685)。
16
+ - Toastの位置変数と `<Toaster position>`、`--Surface-Highlight` / `--Text-on-Highlight` トークン、TagInputのid / name / aria-*の内部input転送を追加しました(#691・#692・#693)。
17
+ - DS部品のスクロールバー非表示を既存の `scrollbar-hide` に統一しました(#694)。
18
+ - inline系Alertが `title` / `description` / `icon` propを描画するようにしました(#695)。
19
+
20
+ 導入時は [2.12.0の注意](./MIGRATION.md#v2120) を確認してください。npm公開・タグ・GitHub Releaseはversion変更のmainマージ後に `publish.yml` が実行します。consumerへの取り込みとアプリ配布は別工程で、今回のDS公開準備には含めません。
21
+
5
22
  ## v2.11.0(2026-10-16)
6
23
 
7
24
  2.10.0以降に、consumer側の見た目の上書きをなくすためのAPIを9件追加したminorリリース。追加のみで、propsを渡さなければ従来と同じ表示です。
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "meta": {
3
3
  "name": "KSK Design System — Component Contracts",
4
- "version": "2.11.0",
4
+ "version": "2.13.0",
5
5
  "description": "全コンポーネントの構造化定義。バリアント・アクセシビリティ要件・使用ルールを機械可読形式で管理。",
6
6
  "counts": {
7
- "ui": 70,
8
- "patterns": 62,
7
+ "ui": 72,
8
+ "patterns": 69,
9
9
  "commerce": 12,
10
10
  "admin": 8,
11
11
  "shells": 3,
12
- "total": 155
12
+ "total": 164
13
13
  },
14
14
  "exportNaming": {
15
15
  "_doc": "contracts の name が `import { name } from \"ksk-design-system\"` で解決できるかを示す。__tests__/contracts-export-integrity.test.ts が src/index.ts の実 export と突き合わせて固定する。",
@@ -120,7 +120,9 @@
120
120
  "showCount + maxLength で controlled / uncontrolled / IME 対応の文字数カウンタを表示",
121
121
  "showCount 未指定時は wrapper / counter DOM を追加しない",
122
122
  "既存の手書き CSS を持つ画面の段階移行では unstyled を使う(showCount / adornment / IME 追従は維持される)",
123
- "Native Input supports style (outer container View) and inputStyle (inner TextInput) as RN-idiomatic style overrides, merged after DS defaults (issue #447)"
123
+ "Native Input supports style (outer container View) and inputStyle (inner TextInput) as RN-idiomatic style overrides, merged after DS defaults (issue #447)",
124
+ "その場で編集する欄(詳細シートのタイトル・メモ等)は variant=\"inline\"(本文 typo-body-md)/ \"inline-title\"(見出し typo-heading-xl)。枠・背景なし、hover で Surface-Secondary、focus-visible で Focus リング、aria-invalid で Caution のリング。unstyled + typo・余白・フォーカス下線の手書きで作らない(issue #675)",
125
+ "CommitInput / CommitTextarea / AutoGrowTextarea / CommitAutoGrowTextarea にも同じ variant を渡せる。native Input / Textarea / AutoGrowTextarea も同名(フォーカス・invalid は下線)"
124
126
  ]
125
127
  },
126
128
  {
@@ -253,7 +255,8 @@
253
255
  "Must use <Textarea> not <textarea>",
254
256
  "showCount + maxLength で controlled / uncontrolled / IME 対応の文字数カウンタを表示",
255
257
  "showCount 未指定時は wrapper / counter DOM を追加しない",
256
- "既存の手書き CSS を持つ画面の段階移行では unstyled を使う(autoGrow / showCount は維持される)"
258
+ "既存の手書き CSS を持つ画面の段階移行では unstyled を使う(autoGrow / showCount は維持される)",
259
+ "variant=\"inline\" / \"inline-title\" は枠・背景・最小高さ・resize なしでその場編集する(issue #675。Input と同じ)"
257
260
  ]
258
261
  },
259
262
  {
@@ -346,7 +349,12 @@
346
349
  "押せる面(button / a)は Card の DOM 先頭に置き、Tab 順はカード本体 → 内側の CardAction(視覚順)。onClick の型は MouseEventHandler<HTMLElement> で、以前の div 前提のハンドラもそのまま渡せる",
347
350
  "押せる Card の名前は aria-label → aria-labelledby → CardTitle(自前の id でも結ばれる)の順。どれも無いと開発ビルドで 1 回 console.warn。押せない入れ子の Card の CardTitle / CardDescription は外側の押せる Card に登録されない",
348
351
  "<Button unstyled> に border / rounded / shadow / active:scale を被せて押せるカードを自作しない(P040)。native は onPress / disabled",
349
- "parity(web と差がある点): native の押せる Card は Pressable 1 つで、CardTitle / CardAction の登録・前面化の仕組みを持たない。入れ子の Card や Card 内の別操作は RN の Pressable の入れ子規則(内側の Pressable が先に反応)に従い、読み上げ名は accessibilityLabel を明示するか子の Text の連結になる"
352
+ "parity(web と差がある点): native の押せる Card は Pressable 1 つで、CardTitle / CardAction の登録・前面化の仕組みを持たない。入れ子の Card や Card 内の別操作は RN の Pressable の入れ子規則(内側の Pressable が先に反応)に従い、読み上げ名は accessibilityLabel を明示するか子の Text の連結になる",
353
+ "面の中に置くカード(入れ子・Section 内のグリッド)は elevation=\"none\"。`!shadow-none` / `shadow-none` の className で消さない(issue #689)",
354
+ "選ぶカード(配席の卓・プラン選択等)は selected。onClick の押せる面に aria-pressed(href では aria-current=\"true\")が付き、押せない Card では見た目だけで開発ビルドで warn。Surface-Accent-Primary-Light の面 + Border-Accent-Primary の 2px 相当の枠になる。Button unstyled に選択色を被せて自作しない。座席のような円形は Card に形の className を足して組む(専用部品は持たない)。native Card も selected(accessibilityState.selected)(issue #677)"
355
+ ],
356
+ "variants": [
357
+ "elevation: none / sm / md(既定) / lg(issue #689。native と同じ語彙)"
350
358
  ]
351
359
  },
352
360
  {
@@ -379,7 +387,11 @@
379
387
  "rules": [
380
388
  "rounded-full only",
381
389
  "Use DiceBear shapes for placeholder, not pravatar.cc",
382
- "native (src/native/components/Avatar.tsx): size はプリセット(sm/md/lg/xl)に加えて pt の数値も可。shape=\"circle\"(既定)|\"rounded\"、rounded の角丸は radius(lg/xl/2xl・既定 xl)。fallback は文字列に加えて ReactNode を受け、独自のフォールバック表示(決定論グラデ+絵文字等)を差し込める。source はリモート URL 文字列も受け取り {uri} に正規化する(issue #449)"
390
+ "native (src/native/components/Avatar.tsx): size はプリセット(sm/md/lg/xl)に加えて pt の数値も可。shape=\"circle\"(既定)|\"rounded\"、rounded の角丸は radius(lg/xl/2xl・既定 xl)。fallback は文字列に加えて ReactNode を受け、独自のフォールバック表示(決定論グラデ+絵文字等)を差し込める。source はリモート URL 文字列も受け取り {uri} に正規化する(issue #449)",
391
+ "寸法は size で指定する。className の size-* / w-* h-* で上書きしない(AvatarFallback の文字サイズが追随しなくなる)。native は xs=24 も持つ(issue #688)"
392
+ ],
393
+ "variants": [
394
+ "size: xs(24) / sm(32) / md(40・既定) / lg(56) / xl(80)。native と同じ語彙・値(issue #688)"
383
395
  ]
384
396
  },
385
397
  {
@@ -407,7 +419,8 @@
407
419
  "DialogTitle は level=\"page\"|\"section\"|\"card\" で見出しの役割を指定する(値は contracts/composition.json の textHierarchy と1対1)。未指定時は position=\"fullscreen\" 配下で page 相当、それ以外は従来の typo-heading-lg",
408
420
  "native (src/native/components/Dialog.tsx): position=\"center\"(既定) / \"top\" / \"fullscreen\" を持ち、fullscreen は四辺・top は上端の safe-area を避ける。実測 inset は SafeAreaInsetsProvider から供給し、未供給なら回避量 0(従来どおり)",
409
421
  "modal な Dialog の content は aria-modal=\"true\" を出力する(modal={false} では出さない)。開いているモーダルの横断判定は useHasOpenModal() / useOpenModalCount() を使い、consumer 側で data-state 等の内部属性を直接読まない(#505)",
410
- "size は sm(400px) / md(480px・既定) / lg(640px) / xl(800px) の幅の段(opt-in)。未指定は従来の 480px のまま。position=\"fullscreen\" では無視。size の段は sm: 付きなので、上書きは className に sm:max-w-* を渡す(接頭辞なしの max-w-* は size に勝たない)。Sheet の size と段の名前を揃えている。ResponsiveDialogContent の size は PC 側の Dialog にだけ渡る"
422
+ "size は sm(400px) / md(480px・既定) / lg(640px) / xl(800px) の幅の段(opt-in)。未指定は従来の 480px のまま。position=\"fullscreen\" では無視。size の段は sm: 付きなので、上書きは className に sm:max-w-* を渡す(接頭辞なしの max-w-* は size に勝たない)。Sheet の size と段の名前を揃えている。ResponsiveDialogContent の size は PC 側の Dialog にだけ渡る",
423
+ "position=\"top\" / \"fullscreen\" の上端 safe area は --Safe-Area-Inset-Top で読む(issue #682。Sheet と同じ)"
411
424
  ],
412
425
  "variants": {
413
426
  "position": [
@@ -456,7 +469,8 @@
456
469
  "native (src/native/components/Sheet.tsx): safeArea(既定 true) で side=\"top\" の上端 inset 退避と、画面いっぱいに近い side=\"bottom\" の食い込み分の退避を行う。実測 inset は SafeAreaInsetsProvider から供給し、未供給なら回避量 0(従来どおり)",
457
470
  "native (src/native/components/Sheet.tsx): surfaceColor でパネル(および snap モードの footer)の面色を上書きできる。未指定なら theme.surface.primary(従来どおり)。scrim の色は変えない(issue #448)",
458
471
  "modal な Sheet の content は aria-modal=\"true\" を出力する(modal={false} では出さない)。開いているモーダルの横断判定は useHasOpenModal() / useOpenModalCount() を使い、consumer 側で data-state 等の内部属性を直接読まない(#505)",
459
- "size は sm(max-w-sm・既定) / md(max-w-xl) / lg(max-w-3xl) の幅の段(opt-in)。side=\"left\" / \"right\" のときだけ効き、top / bottom / float 系では無視。未指定は従来の max-w-sm のまま。className の max-w-* は size より優先。Dialog の size と段の名前を揃えている"
472
+ "size は sm(max-w-sm・既定) / md(max-w-xl) / lg(max-w-3xl) の幅の段(opt-in)。side=\"left\" / \"right\" のときだけ効き、top / bottom / float 系では無視。未指定は従来の max-w-sm のまま。className の max-w-* は size より優先。Dialog の size と段の名前を揃えている",
473
+ "上端の safe area は --Safe-Area-Inset-Top(= max(--Native-Safe-Area-Inset-Top, env(safe-area-inset-top)))で読む。WKWebView で env() が 0 に固着する場合、ネイティブの殻が --Native-Safe-Area-Inset-Top に実測値を書く。consumer で pt-[max(...native-safe-top...)] や [data-slot=sheet-content] の max-height を上書きしない(issue #682。Dialog top / fullscreen・BottomSheetFrame・ResponsiveOverlayFrame・MediaActionCluster・sheet-keyboard.css も同じ)"
460
474
  ],
461
475
  "variants": {
462
476
  "titleLevel": [
@@ -670,7 +684,8 @@
670
684
  "新規 action prop で右側に CTA ボタン (元に戻す / 再試行 等) を表示できる",
671
685
  "保存完了・接続復旧・同期開始など一時的な操作結果は Banner ではなく toast.* helper を使う",
672
686
  "connectionRestored / saveComplete / retryStarted / retryFailed helper を提供",
673
- "viewport の下端 offset は product theme の公開変数 --Toast-Viewport-Offset-Bottom(既定 1rem = 従来の bottom-4)で調整する。下部タブバー / FAB と重なるプロダクトは :root で持ち上げる。[data-slot=\"toast-viewport\"] を消費側 CSS から直接狙わない(issue #503)"
687
+ "viewport の下端 offset は product theme の公開変数 --Toast-Viewport-Offset-Bottom(既定 1rem = 従来の bottom-4)で調整する。下部タブバー / FAB と重なるプロダクトは :root で持ち上げる。[data-slot=\"toast-viewport\"] を消費側 CSS から直接狙わない(issue #503)",
688
+ "viewport の左右の余白と最大幅は product theme 変数 --Toast-Viewport-Offset-X(既定 1rem)/ --Toast-Viewport-Max-Width(既定 24rem)、中央寄せは <Toaster position=\"bottom-center\"> / configureToast({ position: \"bottom-center\" })。[data-slot=\"toast-viewport\"] の left / right / max-width を !important で上書きしない(issue #691)"
674
689
  ],
675
690
  "props": {
676
691
  "Toaster.container": "Element | DocumentFragment | null — 明示先 > PortalContainerProvider > document.body。Shadow DOM 内では Toaster を明示配置する(issue #651)",
@@ -954,7 +969,8 @@
954
969
  "description": "淡いアクセント背景の円に装飾アイコンを収めるバッジ。Card や Stack の gap と競合しないよう外側 margin を持たない。",
955
970
  "variants": [
956
971
  "size: md(44px) / ml(48px) / lg(72px)",
957
- "appearance: accent / plain"
972
+ "appearance: accent / plain",
973
+ "tone: accent(既定) / info / success / warning / caution(issue #684)"
958
974
  ],
959
975
  "accessibility": [
960
976
  "装飾用途は既定で aria-hidden",
@@ -963,7 +979,8 @@
963
979
  "rules": [
964
980
  "外側 margin を追加せず、親の gap で配置間隔を管理する",
965
981
  "背景は Surface-Accent-Primary-Light、前景は Object-Accent-Primary と currentColor を使う",
966
- "appearance=plain は既存パターン内部の視覚互換用途に限定する"
982
+ "appearance=plain は既存パターン内部の視覚互換用途に限定する",
983
+ "tone で情報・成功・注意・警告の色にする(面は Surface-*、アイコンは Object-*)。Surface-Info + Object-Info の円を自作しない。色だけで意味を伝えず、隣の見出し・本文で状態を言葉でも示す。native IconBadge も同名 tone(issue #684)"
967
984
  ]
968
985
  },
969
986
  {
@@ -985,7 +1002,9 @@
985
1002
  "rules": [
986
1003
  "bordered は白背景+カラー枠線",
987
1004
  "inline は色付き背景・コンパクト",
988
- "bordered variant (success/info/error/warning) は title/description prop で自動アイコン表示可"
1005
+ "bordered variant (success/info/error/warning) は title/description prop で自動アイコン表示可",
1006
+ "inline 系(inline-info / inline-caution / inline-warning)も title / description / icon / action の prop で書ける(issue #695。以前は children だけを描画し空の枠になった)。inline の既定アイコンは無し",
1007
+ "children と title / description / icon / action を併用しない。併用時は children 優先で prop は描画されず、開発ビルドで警告する(issue #695)"
989
1008
  ]
990
1009
  },
991
1010
  {
@@ -1369,6 +1388,41 @@
1369
1388
  "size": "number | string (Web), number (Native) — 既定24",
1370
1389
  "accessibilityLabel": "string — 単独の情報画像に付ける名前。Webはaria-labelを優先"
1371
1390
  }
1391
+ },
1392
+ {
1393
+ "name": "EmojiIcon",
1394
+ "path": "src/components/ui/emoji-icon.tsx",
1395
+ "description": "絵文字をアイコンと同じ寸法の箱に収めて描く装飾(issue #676)。EmptyState / ErrorState / Alert / Banner の icon、ListItem の leftSlot、Toast など、アイコンを受けるスロットに絵文字を置くときに使う。",
1396
+ "sizes": [
1397
+ "sm(16)",
1398
+ "md(24・既定)",
1399
+ "lg(36)",
1400
+ "xl(48)"
1401
+ ],
1402
+ "accessibility": [
1403
+ "常に aria-hidden の装飾。意味は隣の見出し・本文で伝える",
1404
+ "native (src/native/components/EmojiIcon.tsx): 同じ語彙・値。accessibilityElementsHidden / importantForAccessibility=no-hide-descendants"
1405
+ ],
1406
+ "rules": [
1407
+ "アイコンスロットに絵文字を素の文字で渡して text-5xl 等の生サイズで拡大しない。EmojiIcon の size を使う",
1408
+ "ActionTile は既存の emoji prop を使う"
1409
+ ]
1410
+ },
1411
+ {
1412
+ "name": "Highlight",
1413
+ "path": "src/components/ui/highlight.tsx",
1414
+ "description": "本文中の検索一致を <mark> で強調する(issue #692)。面は --Surface-Highlight、文字は --Text-on-Highlight(light / dark で AA)。",
1415
+ "subcomponents": [
1416
+ "splitHighlight"
1417
+ ],
1418
+ "accessibility": [
1419
+ "<mark> は読み上げで強調として扱われる(SR により読み方は異なる)。本文の意味は変えない",
1420
+ "native (src/native/components/Highlight.tsx): Text のネストで一致部分に面と文字色を重ねる"
1421
+ ],
1422
+ "rules": [
1423
+ "検索一致の面に状態色(Surface-Warning / Object-Warning)を流用しない。--Surface-Highlight / --Text-on-Highlight を使う",
1424
+ "検索語の正規表現の特殊文字は Highlight が文字としてエスケープする。consumer で RegExp を組まない"
1425
+ ]
1372
1426
  }
1373
1427
  ],
1374
1428
  "patterns": [
@@ -1383,7 +1437,9 @@
1383
1437
  "caution"
1384
1438
  ],
1385
1439
  "rules": [
1386
- "Color + icon + text (never color alone)"
1440
+ "Color + icon + text (never color alone)",
1441
+ "density: default(gap-3 p-4) / compact(gap-2 px-3 py-2)。余白を詰めたいときは density=\"compact\"。`!p-2` 等の className で上書きしない(issue #683)",
1442
+ "layout: card(既定・角丸の囲み) / bar(全幅・角丸なし・下線のみ)。画面上端の注意帯は layout=\"bar\" を使い、div で帯を自作しない(issue #683。native Banner は画像バナーで別 API のため Web のみ)"
1387
1443
  ]
1388
1444
  },
1389
1445
  {
@@ -1456,7 +1512,8 @@
1456
1512
  "description": "KPI / メトリクス表示カード。interactive prop で button 化、focus-ring / active:scale 自動付与。",
1457
1513
  "rules": [
1458
1514
  "interactive または onClick を渡せば role=button + キーボード操作対応",
1459
- "内側の label / value / unit / trend は stat-card-* data-slot を持つ(issue #650)"
1515
+ "内側の label / value / unit / trend は stat-card-* data-slot を持つ(issue #650)",
1516
+ "elevation: none / sm / md(既定)。Card・面の中に並べる StatCard は elevation=\"none\"。`!shadow-none` で消さない(issue #689。native StatCard は影を持たないため Web のみ)"
1460
1517
  ]
1461
1518
  },
1462
1519
  {
@@ -1659,10 +1716,12 @@
1659
1716
  "duplicates-control"
1660
1717
  ],
1661
1718
  "rules": [
1662
- "Use for multi-value text input (tags, emails, keywords)"
1719
+ "Use for multi-value text input (tags, emails, keywords)",
1720
+ "FormField と使うときは id を渡して htmlFor で結ぶ。inputLabel を label の代わりに使わない(lint P026 の例外が要らなくなる)"
1663
1721
  ],
1664
1722
  "accessibility": [
1665
- "枠は var(--Border-Control, var(--Border-Medium-Emphasis))。通常 light/dark から3:1以上(light=Gray-500、dark=White-Alpha-500)。非操作区切りはMediumを維持し、prefers-contrast: more / data-contrast指定でも同じ専用値を使う(issue #636)"
1723
+ "枠は var(--Border-Control, var(--Border-Medium-Emphasis))。通常 light/dark から3:1以上(light=Gray-500、dark=White-Alpha-500)。非操作区切りはMediumを維持し、prefers-contrast: more / data-contrast指定でも同じ専用値を使う(issue #636)",
1724
+ "id / name / aria-labelledby / aria-describedby / aria-invalid を内部 input へ転送する。`<FormField htmlFor={id}>` の子に置くと label が名前になり、説明・エラーが自動で結ばれる。id か aria-labelledby があり inputLabel を明示しないときは aria-label を付けない(issue #693)"
1666
1725
  ]
1667
1726
  },
1668
1727
  {
@@ -1779,7 +1838,8 @@
1779
1838
  "rules": [
1780
1839
  "SheetContent 内で使い、Sheet の autoFocus=false と組み合わせる",
1781
1840
  "KebabMenu は DetailSheetHeader trailing に置く",
1782
- "editable title は titleEditor slot に置く"
1841
+ "editable title は titleEditor slot に置く",
1842
+ "DetailSheetHeader の titleEditor には <CommitInput variant=\"inline-title\" aria-label=… /> を渡す(issue #675)"
1783
1843
  ]
1784
1844
  },
1785
1845
  {
@@ -1829,8 +1889,12 @@
1829
1889
  "keyboard 表示中に入力を邪魔する場合は keyboardBehavior=hide を使う",
1830
1890
  "variant=glass に shadow-* を重ねない(glass-accent が inset 3層 + drop shadow を内包するため二重になる)",
1831
1891
  "下部固定の全幅 CTA は fullWidth を使い、fixed inset-x + Button を手組みしない。fullWidth 時は placement が無視されラベルが常に表示される",
1832
- "広告バナー等で動的に持ち上げる必要があるときは、内部変数 --ksk-fab-bottom-offset を直接上書きせず bottomOffsetExtra を使う(issue #453)"
1833
- ]
1892
+ "広告バナー等で動的に持ち上げる必要があるときは、内部変数 --ksk-fab-bottom-offset を直接上書きせず bottomOffsetExtra を使う(issue #453)",
1893
+ "既定挙動の変更(issue #700・次のリリースで告知): keyboardBehavior=\"hide\"(既定)は、キーボード検知に加え、タッチ主体の端末((pointer: coarse) and (hover: none))でテキスト入力欄にフォーカスがある間も隠れる。隠れている間は invisible でフォーカスも受けない。従来どおり常に出したいときは keyboardBehavior=\"stay\" でオプトアウトする。物理キーボード接続はpointer/hover能力から判別できないため、フォーカスによる先行非表示だけを止めるときは hideOnInputFocus=false(viewport検知は維持)。consumer の html:has(input:focus) で隠す CSS は不要"
1894
+ ],
1895
+ "props": {
1896
+ "hideOnInputFocus": "boolean(既定 true)— keyboardBehavior=\"hide\" のとき、タッチ主体端末の入力フォーカスでも隠す。false なら viewport のキーボード検知だけを使う。pointer/hover能力から物理キーボード接続は判別できない"
1897
+ }
1834
1898
  },
1835
1899
  {
1836
1900
  "name": "MobileAppHeader",
@@ -2081,7 +2145,10 @@
2081
2145
  "providers を渡すと明示順で表示",
2082
2146
  "region=jp は line/x/copy、region=us は whatsapp/x/copy を既定にする",
2083
2147
  "provider 別の計測には onShare(provider) を使う。コピー結果の計測には onCopy(result) を使う",
2084
- "Clipboard API が利用不可または拒否された場合も copyErrorLabel を通知する"
2148
+ "Clipboard API が利用不可または拒否された場合も copyErrorLabel を通知する",
2149
+ "任意の本文(招待コード入りの案内文など)は message(native と同名)。LINE は line.me/R/share?text= に「message + url」、X / Telegram は text に message、WhatsApp / メールは「message + url」を渡す。copy は url のまま(issue #685)",
2150
+ "共有が画面の主操作のとき(招待シート等)は layout=\"block\"(全幅・Control-Height-Lg の主ボタンを縦に積む)。LINE は --Brand-Line の塗り + --Brand-on-Line(黒。白文字は約 2.2:1 で AA 未達)、hover / 押下は --Brand-Line-Hover / --Brand-Line-Pressed。LINE ボタンや --External-LINE* を consumer で自作しない(issue #685)",
2151
+ "表示ラベル・アクセシブルネームの上書きは labels(例: { line: \"LINE で招待を送る\" })"
2085
2152
  ],
2086
2153
  "props": {
2087
2154
  "groupLabel": "string (既定 \"シェア\") — role=\"group\" 全体ラッパーの aria-label(issue #428)"
@@ -2139,6 +2206,10 @@
2139
2206
  "写真ヒーローなど 1 画面固定では scroll=false と padding=none を組み合わせる",
2140
2207
  "mainId で本文 landmark の id を調整でき、skipLink=false で内蔵 SkipLink を無効化できる",
2141
2208
  "footer には主要 CTA を置き、safe-area 余白を消費側で再実装しない",
2209
+ "上端のステータスバー / ダイナミックアイランドは safeAreaTop で避ける(header の上、header が無ければ画面上端に --Safe-Area-Inset-Top の余白。issue #701)。header 側で pt-[max(1rem,var(--Safe-Area-Inset-Top))] を自作しない",
2210
+ "アドレスバーの出入りで高さを揺らしたくない画面は height=\"svh\"、高さの決まった親の中では height=\"fill\"(既定 dvh)",
2211
+ "オンボーディング・ログイン等の 1 画面フローを PC で中央カードにするときは desktopLayout=\"card\"(md = 768px 以上で Surface-Secondary の背景の中央に枠・角丸のカード。cardMaxWidth 既定 30rem / cardMaxHeight 既定 47.5rem)。md:w-[480px] md:rounded-2xl 等を className で自作しない",
2212
+ "他の <main> の中に置くときは landmark=\"none\"(本文を div にし、id とスキップリンクを既定で出さない)",
2142
2213
  "React Native consumer は ksk-design-system/native/ui の Screen を使い、header/body/footer shell をローカル再実装しない"
2143
2214
  ]
2144
2215
  },
@@ -2531,7 +2602,9 @@
2531
2602
  "設定画面で SectionHeader + Card + ListItem の wrapper を consumer 側に作らない",
2532
2603
  "設定一覧で ad-hoc flex row を作らず SettingsListRow を使う",
2533
2604
  "switch / badge / button は rightSlot に置く",
2534
- "danger variant は削除・ログアウトなど不可逆操作のグループに限定する"
2605
+ "danger variant は削除・ログアウトなど不可逆操作のグループに限定する",
2606
+ "見出しアイコンは SettingsSection の icon(見出しの左・aria-hidden・20px・Object-Medium-Emphasis)。title を span で包んでアイコンを並べない(issue #690)",
2607
+ "次の画面へ進む行は SettingsListRow の showChevron(右端・ArrowRight2 16px・Object-Low-Emphasis・aria-hidden)。矢印を手書きしない。トグル等その場で完結する行には付けない。native も同名(issue #690)"
2535
2608
  ],
2536
2609
  "subcomponents": [
2537
2610
  "SettingsSection",
@@ -2557,7 +2630,8 @@
2557
2630
  ],
2558
2631
  "rules": [
2559
2632
  "BottomTabBar + MobileFloatingActionButton の geometry を consumer CSS で手組みしない",
2560
- "既に fixed な nav を渡す場合は bottomNavMode=external を使う"
2633
+ "既に fixed な nav を渡す場合は bottomNavMode=external を使う",
2634
+ "bottomPaddingExtra(CSS の長さ)は bottomPadding の既定余白(bottom-nav=5rem / bottom-nav-fab=7rem / none=0)に加算する。広告バナー等の常設要素の高さを渡し、main の下余白を mainClassName で自前計算しない(issue #681)"
2561
2635
  ]
2562
2636
  },
2563
2637
  {
@@ -2579,7 +2653,8 @@
2579
2653
  "モバイルの BottomTabBar と同じ items 配列を渡す",
2580
2654
  "ページ内アンカーの目次は SectionNav、ビュー状態の切替は SubNav を使う",
2581
2655
  "ロゴ行・フッターは部品に含めず slot 側で並べる",
2582
- "next/link 等のルーターで描画するときは項目ごとの render(Footer・AppHeader と同じレンダースロット)を使う。渡された props(className・aria-current・data-*・children・onClick)をそのまま転送すること。未指定は従来どおり <a>(href あり)/ <button>"
2656
+ "next/link 等のルーターで描画するときは項目ごとの render(Footer・AppHeader と同じレンダースロット)を使う。渡された props(className・aria-current・data-*・children・onClick)をそのまま転送すること。未指定は従来どおり <a>(href あり)/ <button>",
2657
+ "暗い面(Surface-Inverse)のサイドバーでは tone=\"inverse\"。文字は Text-on-Inverse-Secondary、hover / 選択中は Object-on-Inverse の淡い面 + Text-on-Inverse。暗色ナビを Button unstyled で自作しない(issue #680)"
2583
2658
  ]
2584
2659
  },
2585
2660
  {
@@ -2660,6 +2735,136 @@
2660
2735
  "QuickActionGrid",
2661
2736
  "ActionTile"
2662
2737
  ]
2738
+ },
2739
+ {
2740
+ "name": "AddTile",
2741
+ "path": "src/components/patterns/add-tile.tsx",
2742
+ "description": "一覧の末尾・空のカラム・グリッドの空き枠に置く「+追加」の点線タイル(issue #678)。押すと新しい項目を作る入口。",
2743
+ "sizes": [
2744
+ "sm(44px・一覧の末尾)",
2745
+ "md(64px・既定・空カラム / グリッドの空き枠)"
2746
+ ],
2747
+ "accessibility": [
2748
+ "type=button の実 button。label がアクセシブルネーム、アイコンは aria-hidden",
2749
+ "高さ 44px 以上・focus-visible リング",
2750
+ "native (src/native/components/AddTile.tsx): accessibilityRole=button / accessibilityLabel=label / accessibilityState.disabled"
2751
+ ],
2752
+ "rules": [
2753
+ "Button に border-dashed や形を上書きして「追加」タイルを自作しない",
2754
+ "画面の主操作(ヘッダーの作成・FAB)の代わりにしない。「この場所に足す」入口に限る",
2755
+ "点線は Border-Medium-Emphasis、hover は Border-Accent-Primary + Surface-Accent-Primary-Light + Text-Accent-Primary"
2756
+ ]
2757
+ },
2758
+ {
2759
+ "name": "CodeDisplay",
2760
+ "path": "src/components/patterns/code-display.tsx",
2761
+ "description": "招待コード・ログインコード・クーポン等の英数字コードを等幅・広めの字間で見せ、ワンタップでコピーする(issue #686)。入力させる側は CodeInput。",
2762
+ "sizes": [
2763
+ "md(typo-heading-lg・既定)",
2764
+ "lg(typo-heading-2xl)"
2765
+ ],
2766
+ "variants": [
2767
+ "tone: neutral(Surface-Secondary・既定) / accent(Surface-Accent-Primary-Light)"
2768
+ ],
2769
+ "accessibility": [
2770
+ "コピー結果はボタンの文言とアイコンで示し、aria-live=polite で読み上げる(色だけで伝えない)",
2771
+ "native (src/native/components/CodeDisplay.tsx): コードは selectable。RN コアにクリップボードが無いため onCopy(expo-clipboard 等)を渡したときだけコピーボタンを出す"
2772
+ ],
2773
+ "rules": [
2774
+ "font-mono / tracking-* を consumer で指定してコード表示を自作しない",
2775
+ "長いコードは break-all で折り返す。横スクロールさせない",
2776
+ "コピーの成否はトーストではなくボタン上で即時に示す(onCopy で計測・トーストを足すのは可)"
2777
+ ]
2778
+ },
2779
+ {
2780
+ "name": "FeatureComparisonTable",
2781
+ "path": "src/components/patterns/feature-comparison-table.tsx",
2782
+ "description": "プラン(Free / Plus 等)の機能比較表(issue #687)。列ごとの可否(✓ / —)や値を <table> と th scope で意味付きで出す。",
2783
+ "accessibility": [
2784
+ "<table> + sr-only の caption + 列見出し th[scope=col] + 行見出し th[scope=row]",
2785
+ "✓ / — は aria-hidden の装飾で、availableLabel / unavailableLabel(既定「利用できる」「利用できない」)を sr-only で持つ",
2786
+ "native (src/native/components/FeatureComparisonTable.tsx): 表のセマンティクスが無いため各行を 1 つの読み上げ要素(「機能名、Free 利用できない、Plus 利用できる」)にまとめる"
2787
+ ],
2788
+ "rules": [
2789
+ "div grid + アイコンだけで比較表を自作しない(読み上げで可否が分からない)",
2790
+ "列は 2〜3 を想定。推奨プランは highlight(Surface-Accent-Primary-Light + Text-Accent-Primary の見出し)",
2791
+ "値が無いセル(undefined)は false(利用できない)として扱う"
2792
+ ]
2793
+ },
2794
+ {
2795
+ "name": "MonthCalendar",
2796
+ "path": "src/components/patterns/month-calendar.tsx",
2797
+ "description": "予定付きの月カレンダー(issue #679)。日ごとの予定を一覧する予定表(日付を選ぶ入力は Calendar / DatePicker)。今日・選択日・土日・月外セル・予定チップ・「+n件」の見た目を DS が持つ。",
2798
+ "subcomponents": [
2799
+ "buildMonthWeeks"
2800
+ ],
2801
+ "accessibility": [
2802
+ "WAI-ARIA grid パターン: role=grid / row / columnheader / gridcell、タブストップは 1 つ(roving tabindex。選択日 → 今日 → 1 日)",
2803
+ "← → ↑ ↓ で 1 日 / 1 週、Home / End で週の端、PageUp / PageDown で前後の月(onMonthChange 指定時)、Enter / Space で onSelectDay",
2804
+ "セルの読み上げ名に日付・今日・予定件数と予定名を含める。予定チップと「+n件」はポインタ用の近道(tabIndex=-1)で、キーボードは日の選択から詳細へ辿る"
2805
+ ],
2806
+ "rules": [
2807
+ "日のセル・予定チップを Button unstyled で自作しない",
2808
+ "あふれは maxEventsPerDay(既定 2)超を「+n件」にまとめ、onShowMore(既定 onSelectDay)でその日の詳細へ",
2809
+ "md(768px)未満はチップの代わりに色ドット(最大 3)を出す。操作は日の選択に一本化する",
2810
+ "スマホの週の帯は view=\"week\"(フォーカス中の日を含む 1 週だけ。矢印キーで週が移る。issue #704)、日ごとの予定の中身は AgendaList を下に置く。週ストリップ・アジェンダを Button unstyled で自作しない",
2811
+ "土日の色は weekendTone(既定 true。日曜 Text-Caution / 土曜 Text-Accent-Primary・Calendar と同じ語彙)",
2812
+ "native は未提供(INTENTIONAL_NATIVE_GAPS)"
2813
+ ]
2814
+ },
2815
+ {
2816
+ "name": "AgendaList",
2817
+ "path": "src/components/patterns/agenda-list.tsx",
2818
+ "description": "予定がある日を時系列に並べる一覧(issue #704)。スマホのカレンダーで MonthCalendar(view=\"week\" の週の帯や月グリッド)の下に置き、日付列(日・曜日)+ その日の予定の行で中身を見せる。予定は MonthCalendarEvent と同じ形。",
2819
+ "accessibility": [
2820
+ "日ごとの li に読み上げ用の見出し(既定 h3。置き場所に合わせて headingLevel で変える・「10月3日(土)、今日」)。今日の行は aria-current=\"date\"。日付列の見た目は aria-hidden",
2821
+ "onSelectEvent を渡すと予定の行が button(44px 以上・focus-visible リング)。渡さなければ読むだけの行"
2822
+ ],
2823
+ "rules": [
2824
+ "予定の行の面は tone(MonthCalendar のチップと同じ色)。今日・選択日・土日(weekendTone)の見た目は DS が持つ",
2825
+ "既定は予定がある日だけを昇順に並べる。予定の無い日も出すときは dates(emptyDayLabel 既定「予定なし」)",
2826
+ "スクロール連動・「今日へ」のジャンプ先は dayId で id を付ける(行には常に data-date)",
2827
+ "並べる日が無いときは empty(EmptyState 等)",
2828
+ "native は未提供(INTENTIONAL_NATIVE_GAPS)"
2829
+ ]
2830
+ },
2831
+ {
2832
+ "name": "KanbanColumn",
2833
+ "path": "src/components/patterns/kanban-column.tsx",
2834
+ "description": "カンバンの列の入れ物(issue #679)。見出し(色ドット + title + 件数 + action)・カードを縦に積む本体・footer(AddTile 等)。",
2835
+ "accessibility": [
2836
+ "見出し(h3)で名前の付いた section。件数は見出しの読み上げに「(n件)」で含め、見た目の件数バッジは aria-hidden"
2837
+ ],
2838
+ "rules": [
2839
+ "列の上辺に太い色帯を付けない。状態は tone の色ドットと見出しの言葉で示す",
2840
+ "分類の識別色(カテゴリ別ボード等)は accentColor に var(--Categorical-N) を渡す(tone より優先。issue #702)。title の中に色の点を自作しない",
2841
+ "中のカードは Card elevation=\"none\"(面の中の面は影なし)",
2842
+ "ドラッグ&ドロップは持たない。consumer のライブラリで包む",
2843
+ "native は未提供(INTENTIONAL_NATIVE_GAPS)"
2844
+ ]
2845
+ },
2846
+ {
2847
+ "name": "SelectableTile",
2848
+ "path": "src/components/patterns/selectable-tile.tsx",
2849
+ "description": "押すと選べて、編集中はドラッグ・矢印キーで動かせるタイル(issue #703)。配席表の卓・座席、レイアウト編集のブロック等。押せる面そのものが 1 つの button で、consumer の pointer / key ハンドラと aria-* が同じ要素に付く。",
2850
+ "variants": {
2851
+ "shape": [
2852
+ "rounded",
2853
+ "circle"
2854
+ ]
2855
+ },
2856
+ "accessibility": [
2857
+ "1 つの <button>。名前は中身か aria-label。selected 指定時は aria-pressed(未指定なら付けない)",
2858
+ "movable の間は矢印キー(↑ ↓ ← →)で onMove を呼び preventDefault。consumer の onKeyDown が preventDefault したら呼ばない",
2859
+ "moveInstructions は button の中に hidden で描画して aria-describedby で結ぶ(名前には入らない。consumer の aria-describedby と連結)。非推奨の aria-grabbed / aria-dropeffect は使わない",
2860
+ "タップ領域は 44px 以上(min-h-11 / min-w-11)。focus-visible は 3px のリング"
2861
+ ],
2862
+ "rules": [
2863
+ "選択・移動するタイルを Button unstyled / Card selected + className で自作しない(Card の押せる面は内側の button でハンドラ・aria-describedby が乗らない)",
2864
+ "ドラッグ&ドロップ自体(pointer capture・落とし先の判定)は consumer が onPointerDown 等で実装し、dragging で見た目だけ渡す",
2865
+ "大きさは className で渡す(円形は size-12 等)。selected の面・枠は Card / ActionTile と同じトークンで、枠の太さは内側の outline(focus-visible の外側 ring と両立)",
2866
+ "native は未提供(INTENTIONAL_NATIVE_GAPS)"
2867
+ ]
2663
2868
  }
2664
2869
  ],
2665
2870
  "commerce": [
@@ -2798,10 +3003,13 @@
2798
3003
  "消費側は DS の内部マークアップ([data-slot=\"bottom-nav-pill\"] > :is(a, button)、span:first-child / span:last-child、[data-global-nav-add-icon])を !important や :has() で叩かない。DOM を狙う場合も公開 data-slot だけを使う。",
2799
3004
  "--Nav-Item-Min-Height / --Nav-Center-Action-Size は max(44px, var(...)) で参照するため、44px(HIG のタップ領域下限)より縮まない。",
2800
3005
  "--Nav-Center-Action-Surface / -Border / -Shadow と --Nav-Selected-Surface / -Shadow は宣言したときだけ DS 既定(.glass-accent / ガラスの選択プラッター)を置き換える。未宣言なら tone / dark の出し分けは DS 側が持つ。",
2801
- "--Nav-Pill-* の寸法が効くのは prominent レイアウト(showLabels か centerAction がある pill)。アイコンのみの compact pill は契約外で固定。"
3006
+ "--Nav-Pill-* の寸法が効くのは prominent レイアウト(showLabels か centerAction がある pill)。アイコンのみの compact pill は契約外で固定。",
3007
+ "bottomOffsetExtra(CSS の長さ)は safe-area・pill の 12px・lift の持ち上げ量に加算される。className の bottom-* で位置を上書きしない(issue #681)",
3008
+ "既定挙動の変更(issue #700・次のリリースで告知): keyboardBehavior=\"hide\" を明示したとき(既定はstay)は、キーボード検知に加え、タッチ主体の端末((pointer: coarse) and (hover: none))でテキスト入力欄にフォーカスがある間も隠れる。隠れている間は invisible でフォーカスも受けない。従来どおり常に出したいときは keyboardBehavior=\"stay\" でオプトアウトする。物理キーボード接続はpointer/hover能力から判別できないため、フォーカスによる先行非表示だけを止めるときは hideOnInputFocus=false(viewport検知は維持)。consumer の html:has(input:focus) で隠す CSS は不要"
2802
3009
  ],
2803
3010
  "props": {
2804
- "navLabel": "string (既定 \"メインナビゲーション\") — nav 要素の aria-label(issue #428)"
3011
+ "navLabel": "string (既定 \"メインナビゲーション\") — nav 要素の aria-label(issue #428)",
3012
+ "hideOnInputFocus": "boolean(既定 true)— keyboardBehavior=\"hide\" のとき、タッチ主体端末の入力フォーカスでも隠す。false なら viewport のキーボード検知だけを使う。pointer/hover能力から物理キーボード接続は判別できない"
2805
3013
  },
2806
3014
  "slots": [
2807
3015
  "bottom-nav-pill",
@@ -2836,14 +3044,20 @@
2836
3044
  "addAction 指定時はブランド色丸背景 + Add アイコンが自動で centerAction になる",
2837
3045
  "floatingPosition='left'|'right' を使う場合は FAB を反対側に併置する",
2838
3046
  "寸法・面の上書きは BottomTabBar と同じ --Nav-* を使う(MobileTabBar は薄いラッパーなので変数はそのまま効く。issue #471)",
2839
- "[data-global-nav-add-icon] は belle-todo 互換の後方互換フックで公開契約ではない。中央アクションのアイコンは data-slot=\"bottom-nav-center-action-icon\" で狙う(issue #471)"
3047
+ "[data-global-nav-add-icon] は belle-todo 互換の後方互換フックで公開契約ではない。中央アクションのアイコンは data-slot=\"bottom-nav-center-action-icon\" で狙う(issue #471)",
3048
+ "keyboardBehavior(hide 既定 / lift / stay)を BottomTabBar へ素通しする。キーボード表示中にタブバーを隠す CSS を consumer に書かない(issue #681)",
3049
+ "bottomOffsetExtra(CSS の長さ)で画面下の広告バナー等の高さぶん持ち上げる。MobileAppShell の bottomPaddingExtra・MobileFloatingActionButton の bottomOffsetExtra に同じ値を渡す(issue #681)",
3050
+ "既定挙動の変更(issue #700・次のリリースで告知): keyboardBehavior=\"hide\"(既定)は、キーボード検知に加え、タッチ主体の端末((pointer: coarse) and (hover: none))でテキスト入力欄にフォーカスがある間も隠れる。隠れている間は invisible でフォーカスも受けない。従来どおり常に出したいときは keyboardBehavior=\"stay\" でオプトアウトする。物理キーボード接続はpointer/hover能力から判別できないため、フォーカスによる先行非表示だけを止めるときは hideOnInputFocus=false(viewport検知は維持)。consumer の html:has(input:focus) で隠す CSS は不要"
2840
3051
  ],
2841
3052
  "productTheme": [
2842
3053
  "--Nav-Pill-*",
2843
3054
  "--Nav-Item-*",
2844
3055
  "--Nav-Center-Action-*",
2845
3056
  "--Nav-Selected-*"
2846
- ]
3057
+ ],
3058
+ "props": {
3059
+ "hideOnInputFocus": "boolean(既定 true)— keyboardBehavior=\"hide\" のとき、タッチ主体端末の入力フォーカスでも隠す。false なら viewport のキーボード検知だけを使う。pointer/hover能力から物理キーボード接続は判別できない"
3060
+ }
2847
3061
  },
2848
3062
  {
2849
3063
  "name": "FilterBar",
@@ -3033,7 +3247,10 @@
3033
3247
  "rules": [
3034
3248
  "For admin/dashboard pages",
3035
3249
  "mainId は同一ページ内で一意にする。skipLink=false で内蔵 SkipLink を無効化できる",
3036
- "header と main の既定 gutter は内蔵 Container が担うためページ側で外周 padding を重ねない"
3250
+ "header と main の既定 gutter は内蔵 Container が担うためページ側で外周 padding を重ねない",
3251
+ "暗色サイドバーは sidebarTone=\"inverse\"(aside を Surface-Inverse にする)。中のナビは SidebarNav tone=\"inverse\"、ロゴ・フッターの文字も Text-on-Inverse 系にする(issue #680)",
3252
+ "lg 未満でナビへ辿れるようにするときは mobileDrawer(issue #705)。ヘッダー左端のメニューボタン(44px・aria-expanded・aria-label 既定「メニューを開く」)から左の Sheet に同じ sidebar を開く。ハンバーガーと Sheet side=\"left\" を consumer で自作しない",
3253
+ "ドロワー内のリンク(a[href])と SidebarNav の項目を押すと閉じる(closeMobileDrawerOnNavigate 既定 false、明示 true で有効)。開閉の制御は mobileDrawerOpen / onMobileDrawerOpenChange"
3037
3254
  ]
3038
3255
  },
3039
3256
  {