ksk-design-system 1.51.2 → 1.52.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/AGENTS.md CHANGED
@@ -40,6 +40,17 @@ UI を書く前に必ず確認すること:
40
40
  - [ ] `.tsx` 編集後に `bash scripts/lint-scratch.sh`、コンポーネント増減時は `npm run check` を実行したか
41
41
  - [ ] `FormField` を import する前にどちらか確認したか(react-hook-form の Controller と統合するなら `RhfFormField`=`ui/form` の `FormField` を index.ts で別名 export したもの。単純な label+error 表示は `patterns/form-field` の `FormField`。迷ったら後者)
42
42
 
43
+ ### 新規・変更するコンポーネントの API チェック(2026-08 の consumer 実機点検で3件連続した型)
44
+
45
+ 「DS 部品の既定値が consumer の想定とズレていた」不具合が同じ週に3件出た(#308 / #311 / exam-kit 側で発覚した ChipSelector の複数選択既定)。部品の props を設計・変更するときは次を確認する:
46
+
47
+ - [ ] **押せる要素は、押せると見て分かる面を既定で持つか**。素の Pressable + テキストだけの操作子を作らない。面・タップ領域(44pt)は `IconButton` 等の既存部品に委ねる(#308: Calendar の月送り矢印が面を持たず、consumer から差し替え口も無かった)
48
+ - [ ] **インタラクティブな部品は a11y 既定値を自分で持つか**。`accessibilityRole` と、状態(selected / disabled / checked)の `accessibilityState` 反映は**呼び出し側の義務にしない**。呼び出し側の明示値が優先される形で部品が既定を持つ(#311: Chip が role を持たず、スクリーンリーダーにただのテキストとして扱われた)
49
+ - [ ] **モードを持つ部品(単一/複数選択・開閉など)の既定値は、間違えて使うと壊れる側にしていないか**。既定で済ませた呼び出しが静かに誤動作する組み合わせ(例: ChipSelector の既定 `multiple=true` を単一選択のつもりで使うと、押しても values[0] が現在値のまま切り替わらない)は、既定を安全側へ倒すか、必須 prop にして省略をコンパイルエラーにする
50
+ - [ ] **名前付きスロット(meta / description 等)は「何を・どこに置くか」を JSDoc に書いたか**。書いていないスロットは consumer に流用され、想定外の位置崩れになる(#309: ActionTile の meta に選択チェックを入れられ、左下に浮いた)
51
+
52
+ いずれも lint では拾えない設計判断なので、レビューではこの4点を明示的に見る。
53
+
43
54
  ---
44
55
 
45
56
  ## このDSについて
package/CLAUDE.md CHANGED
@@ -40,6 +40,17 @@ UI を書く前に必ず確認すること:
40
40
  - [ ] `.tsx` 編集後に `bash scripts/lint-scratch.sh`、コンポーネント増減時は `npm run check` を実行したか
41
41
  - [ ] `FormField` を import する前にどちらか確認したか(react-hook-form の Controller と統合するなら `RhfFormField`=`ui/form` の `FormField` を index.ts で別名 export したもの。単純な label+error 表示は `patterns/form-field` の `FormField`。迷ったら後者)
42
42
 
43
+ ### 新規・変更するコンポーネントの API チェック(2026-08 の consumer 実機点検で3件連続した型)
44
+
45
+ 「DS 部品の既定値が consumer の想定とズレていた」不具合が同じ週に3件出た(#308 / #311 / exam-kit 側で発覚した ChipSelector の複数選択既定)。部品の props を設計・変更するときは次を確認する:
46
+
47
+ - [ ] **押せる要素は、押せると見て分かる面を既定で持つか**。素の Pressable + テキストだけの操作子を作らない。面・タップ領域(44pt)は `IconButton` 等の既存部品に委ねる(#308: Calendar の月送り矢印が面を持たず、consumer から差し替え口も無かった)
48
+ - [ ] **インタラクティブな部品は a11y 既定値を自分で持つか**。`accessibilityRole` と、状態(selected / disabled / checked)の `accessibilityState` 反映は**呼び出し側の義務にしない**。呼び出し側の明示値が優先される形で部品が既定を持つ(#311: Chip が role を持たず、スクリーンリーダーにただのテキストとして扱われた)
49
+ - [ ] **モードを持つ部品(単一/複数選択・開閉など)の既定値は、間違えて使うと壊れる側にしていないか**。既定で済ませた呼び出しが静かに誤動作する組み合わせ(例: ChipSelector の既定 `multiple=true` を単一選択のつもりで使うと、押しても values[0] が現在値のまま切り替わらない)は、既定を安全側へ倒すか、必須 prop にして省略をコンパイルエラーにする
50
+ - [ ] **名前付きスロット(meta / description 等)は「何を・どこに置くか」を JSDoc に書いたか**。書いていないスロットは consumer に流用され、想定外の位置崩れになる(#309: ActionTile の meta に選択チェックを入れられ、左下に浮いた)
51
+
52
+ いずれも lint では拾えない設計判断なので、レビューではこの4点を明示的に見る。
53
+
43
54
  ---
44
55
 
45
56
  ## 必須: セッション開始時に読み込むファイル
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "meta": {
3
3
  "name": "KSK Design System — Component Contracts",
4
- "version": "1.51.2",
4
+ "version": "1.52.0",
5
5
  "description": "全コンポーネントの構造化定義。バリアント・アクセシビリティ要件・使用ルールを機械可読形式で管理。",
6
6
  "counts": {
7
7
  "ui": 67,
@@ -2052,7 +2052,7 @@
2052
2052
  "name": "QuickActionGrid / ActionTile",
2053
2053
  "exported": false,
2054
2054
  "path": "src/components/patterns/quick-action-grid.tsx",
2055
- "description": "ショートカット/絵文字 action の button tile と grid。icon/emoji、label、description、meta、selected/disabled/loading state、2/3/4 column または auto-fit を持つ。",
2055
+ "description": "ショートカット/絵文字 action の button tile と grid。icon/emoji、label、description、meta、indicator、selected/disabled/loading state、2/3/4 column または auto-fit を持つ。",
2056
2056
  "variants": [
2057
2057
  "neutral",
2058
2058
  "selected",
@@ -2064,13 +2064,19 @@
2064
2064
  ],
2065
2065
  "accessibility": [
2066
2066
  "button semantics",
2067
- "aria-pressed when selected"
2067
+ "aria-pressed when selected (selected prop または variant=\"selected\" のどちらでも true)",
2068
+ "選択状態は色だけでなく既定チェック(indicator省略時)でも伝える(WCAG 1.4.1)",
2069
+ "既定チェックは読み上げ対象外(aria-hidden / accessibilityElementsHidden)。選択状態の正本は aria-pressed(web) / accessibilityState.selected(native)"
2068
2070
  ],
2069
2071
  "rules": [
2070
2072
  "card + button の hybrid を consumer 側で手組みしない",
2071
2073
  "shortcut row/grid の columns/gap を consumer 側で決め打ちしない",
2072
2074
  "children には ActionTile を使う",
2073
- "選択状態は selected prop を使う"
2075
+ "選択状態は selected prop を使う",
2076
+ "meta はカード下段右端の補足情報専用。選択インジケータには indicator prop を使う(issue #309)",
2077
+ "indicator はラベル行右端(loading 時 Spinner の位置)に表示。省略時は選択状態でDS標準チェックが既定表示される。null/undefined/falseはいずれも「指定なし」として扱われ、選択中なら既定チェックへフォールバックする",
2078
+ "loading は indicator / 既定チェックより優先して表示される",
2079
+ "native では indicator に文字列・数値を渡してもよい(DS 側が Text にラップする)。それ以外の ReactNode はそのまま描画されるため、consumer が Text 相当で包む"
2074
2080
  ],
2075
2081
  "subcomponents": [
2076
2082
  "QuickActionGrid",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "meta": {
3
3
  "name": "KSK Design System — Semantic Token Hex Cache",
4
- "version": "1.51.2",
4
+ "version": "1.52.0",
5
5
  "description": "semantic / semanticDark トークン(var(--Primitive-*) 参照)を実 hex に解決したサイドカー生成物。hex はデフォルト(Blue)テーマでの解決値であり、Brand 系(meta.themeDependentKeys に列挙)はテーマ差し替え(orange/green/violet 等)で実色が変わる。テーマ別の完全解決値は `ksk-design-system/native` エクスポート(バンドル済み native トークンモジュール)の themes を参照。tokens.json 本体のスキーマは変更せず、AI がこのファイルだけで実色を把握できるようにし、primitive 値の変更による semantic 実色のドリフトを --check で機械検出する。",
6
6
  "generatedBy": "scripts/generate-token-hex-cache.mjs",
7
7
  "theme": "default",
package/dist/index.js CHANGED
@@ -15362,16 +15362,16 @@ var vp = {
15362
15362
  4: "grid-cols-2 sm:grid-cols-4",
15363
15363
  auto: "grid-cols-[repeat(auto-fit,minmax(8rem,1fr))]"
15364
15364
  };
15365
- function bp({ className: e, icon: t, emoji: n, label: r, description: i, meta: a, selected: o = !1, loading: s = !1, variant: c = o ? "selected" : "neutral", disabled: l, type: u, ...d }) {
15366
- let f = l || s;
15365
+ function bp({ className: e, icon: t, emoji: n, label: r, description: i, meta: a, indicator: o, selected: s = !1, loading: c = !1, variant: l = s ? "selected" : "neutral", disabled: u, type: d, ...f }) {
15366
+ let p = u || c, m = s || l === "selected", h = o != null && o !== !1;
15367
15367
  return /* @__PURE__ */ H("button", {
15368
15368
  "data-slot": "action-tile",
15369
- "data-variant": c,
15370
- "aria-pressed": o || void 0,
15371
- type: u ?? "button",
15372
- disabled: f,
15373
- className: W("relative flex min-h-24 flex-col items-start justify-between gap-3 rounded-xl border border-[var(--Border-Low-Emphasis)] p-3 text-left transition-colors", "focus-visible:ring-[3px] focus-visible:ring-[var(--Focus-High-Emphasis)]/50 focus-visible:outline-none", "hover:bg-[var(--Surface-Secondary)]", vp[c], f && "cursor-not-allowed opacity-50", e),
15374
- ...d,
15369
+ "data-variant": l,
15370
+ "aria-pressed": m || void 0,
15371
+ type: d ?? "button",
15372
+ disabled: p,
15373
+ className: W("relative flex min-h-24 flex-col items-start justify-between gap-3 rounded-xl border border-[var(--Border-Low-Emphasis)] p-3 text-left transition-colors", "focus-visible:ring-[3px] focus-visible:ring-[var(--Focus-High-Emphasis)]/50 focus-visible:outline-none", "hover:bg-[var(--Surface-Secondary)]", vp[l], p && "cursor-not-allowed opacity-50", e),
15374
+ ...f,
15375
15375
  children: [/* @__PURE__ */ H("span", {
15376
15376
  className: "flex w-full items-start justify-between gap-3",
15377
15377
  children: [/* @__PURE__ */ H("span", {
@@ -15392,10 +15392,17 @@ function bp({ className: e, icon: t, emoji: n, label: r, description: i, meta: a
15392
15392
  children: r
15393
15393
  })
15394
15394
  ]
15395
- }), s && /* @__PURE__ */ V(pl, {
15395
+ }), c ? /* @__PURE__ */ V(pl, {
15396
15396
  size: "sm",
15397
15397
  label: "処理中"
15398
- })]
15398
+ }) : h ? /* @__PURE__ */ V("span", {
15399
+ className: W("shrink-0", (typeof o == "string" || typeof o == "number") && "typo-label-md text-[var(--Text-High-Emphasis)]"),
15400
+ children: o
15401
+ }) : m ? /* @__PURE__ */ V("span", {
15402
+ className: "typo-label-md shrink-0 text-[var(--Text-Accent-Primary)]",
15403
+ "aria-hidden": !0,
15404
+ children: "✓"
15405
+ }) : null]
15399
15406
  }), (i || a) && /* @__PURE__ */ H("span", {
15400
15407
  className: "flex w-full flex-wrap items-end justify-between gap-x-2 gap-y-1",
15401
15408
  children: [i && /* @__PURE__ */ V("span", {
@@ -17634,7 +17641,7 @@ function lh({ className: e, state: t = "idle", label: n, count: r, compact: i =
17634
17641
  className: W("ml-0.5 rounded-full bg-[var(--Surface-Primary)] px-1.5 py-0.5 typo-label-xs", "text-[var(--Text-High-Emphasis)]"),
17635
17642
  children: r > 99 ? "99+" : r
17636
17643
  })
17637
- ] }), m = W("inline-flex min-h-9 max-w-full items-center justify-center gap-1.5 rounded-full border border-[var(--Border-Low-Emphasis)] px-2.5 py-1", "typo-label-xs select-none", ah[t], f && "cursor-pointer transition-colors hover:bg-[var(--Surface-Tertiary)]", f && "focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-[var(--Focus-High-Emphasis)]/50", u && "opacity-50", i && "min-w-9 px-2", e);
17644
+ ] }), m = W("inline-flex max-w-full items-center justify-center gap-1.5 rounded-full border border-[var(--Border-Low-Emphasis)] px-2.5 py-1", "typo-label-xs select-none", ah[t], f && "min-h-9", f && "cursor-pointer transition-colors hover:bg-[var(--Surface-Tertiary)]", f && "focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-[var(--Focus-High-Emphasis)]/50", u && "opacity-50", i && f && "min-w-9 px-2", i && !f && "p-1", e);
17638
17645
  if (!f) {
17639
17646
  let e = sh(d);
17640
17647
  return /* @__PURE__ */ V("span", {
package/dist/native/ui.js CHANGED
@@ -2256,7 +2256,7 @@ function Yt({ checked: e = !1, onChange: t, disabled: n = !1, label: r, descript
2256
2256
  style: {
2257
2257
  flexDirection: "row",
2258
2258
  gap: c.spacing.scale[2],
2259
- alignItems: "flex-start",
2259
+ alignItems: i ? "flex-start" : "center",
2260
2260
  minHeight: c.touchTargets.buttonCTA.min,
2261
2261
  opacity: n ? .6 : 1
2262
2262
  },
@@ -2264,7 +2264,7 @@ function Yt({ checked: e = !1, onChange: t, disabled: n = !1, label: r, descript
2264
2264
  pointerEvents: "none",
2265
2265
  accessibilityElementsHidden: !0,
2266
2266
  importantForAccessibility: "no-hide-descendants",
2267
- style: { paddingTop: 2 },
2267
+ style: { paddingTop: i ? 2 : 0 },
2268
2268
  children: /* @__PURE__ */ E(Jt, {
2269
2269
  checked: e,
2270
2270
  disabled: n
@@ -2331,7 +2331,7 @@ function Zt({ options: e, values: t = [], onChange: n, disabled: r = !1 }) {
2331
2331
  t.includes(e) ? n?.(t.filter((t) => t !== e)) : n?.([...t, e]);
2332
2332
  };
2333
2333
  return /* @__PURE__ */ E(W, {
2334
- style: { gap: i.spacing.scale[3] },
2334
+ style: { gap: i.spacing.scale[1] },
2335
2335
  children: e.map((e) => /* @__PURE__ */ E(Yt, {
2336
2336
  label: e.label,
2337
2337
  description: e.description,
@@ -2346,7 +2346,7 @@ function Zt({ options: e, values: t = [], onChange: n, disabled: r = !1 }) {
2346
2346
  function Qt({ options: e, value: t, onChange: n, disabled: r = !1 }) {
2347
2347
  let { theme: i, scales: a } = K();
2348
2348
  return /* @__PURE__ */ E(W, {
2349
- style: { gap: a.spacing.scale[3] },
2349
+ style: { gap: a.spacing.scale[1] },
2350
2350
  children: e.map((e) => {
2351
2351
  let o = t === e.value, s = r || e.disabled;
2352
2352
  return /* @__PURE__ */ D(z, {
@@ -2355,7 +2355,8 @@ function Qt({ options: e, value: t, onChange: n, disabled: r = !1 }) {
2355
2355
  style: {
2356
2356
  flexDirection: "row",
2357
2357
  gap: a.spacing.scale[2],
2358
- alignItems: "flex-start",
2358
+ alignItems: e.description ? "flex-start" : "center",
2359
+ minHeight: a.touchTargets.buttonCTA.min,
2359
2360
  opacity: s ? .5 : 1
2360
2361
  },
2361
2362
  accessibilityRole: "radio",
@@ -2369,7 +2370,7 @@ function Qt({ options: e, value: t, onChange: n, disabled: r = !1 }) {
2369
2370
  borderColor: o ? i.brand.primary : i.border["medium-emphasis"],
2370
2371
  alignItems: "center",
2371
2372
  justifyContent: "center",
2372
- marginTop: 2
2373
+ marginTop: e.description ? 2 : 0
2373
2374
  },
2374
2375
  children: o && /* @__PURE__ */ E(W, { style: {
2375
2376
  width: 10,
@@ -5550,10 +5551,10 @@ function ci({ state: e = "idle", label: t, count: n, compact: r = !1, loading: i
5550
5551
  style: [q("label.xs"), { color: u.text["high-emphasis"] }],
5551
5552
  children: n > 99 ? "99+" : n
5552
5553
  })
5553
- ] }), m = [{
5554
- minHeight: 36,
5555
- minWidth: r ? 36 : void 0,
5556
- paddingHorizontal: d.spacing.scale[2],
5554
+ ] }), m = !o && !!c, h = [{
5555
+ minHeight: m ? 36 : void 0,
5556
+ minWidth: r && m ? 36 : void 0,
5557
+ paddingHorizontal: r && !m ? d.spacing.scale[1] : d.spacing.scale[2],
5557
5558
  paddingVertical: d.spacing.scale[1],
5558
5559
  borderRadius: d.borderRadius.full,
5559
5560
  borderWidth: 1,
@@ -5565,19 +5566,19 @@ function ci({ state: e = "idle", label: t, count: n, compact: r = !1, loading: i
5565
5566
  gap: d.spacing.scale[1],
5566
5567
  maxWidth: "100%"
5567
5568
  }, s];
5568
- return o || !c ? /* @__PURE__ */ E(W, {
5569
- accessibilityRole: "text",
5570
- accessibilityLabel: t,
5571
- style: m,
5572
- children: p
5573
- }) : /* @__PURE__ */ E(z, {
5569
+ return m ? /* @__PURE__ */ E(z, {
5574
5570
  accessibilityRole: "button",
5575
5571
  accessibilityLabel: t,
5576
5572
  accessibilityState: { busy: i || e === "syncing" },
5577
5573
  onPress: c,
5578
- style: ({ pressed: e }) => [m, e && { opacity: .82 }],
5574
+ style: ({ pressed: e }) => [h, e && { opacity: .82 }],
5579
5575
  ...l,
5580
5576
  children: p
5577
+ }) : /* @__PURE__ */ E(W, {
5578
+ accessibilityRole: "text",
5579
+ accessibilityLabel: t,
5580
+ style: h,
5581
+ children: p
5581
5582
  });
5582
5583
  }
5583
5584
  var li = ci;
@@ -6744,36 +6745,36 @@ function Gi(e, t) {
6744
6745
  };
6745
6746
  }
6746
6747
  }
6747
- function Ki({ icon: e, emoji: t, label: n, description: r, meta: i, selected: a = !1, loading: o = !1, disabled: s = !1, variant: c = a ? "selected" : "neutral", onPress: l, style: u, accessibilityRole: d, accessibilityState: f, ...p }) {
6748
- let { theme: m, scales: h } = K(), g = s || o, _ = Gi(c, m);
6748
+ function Ki({ icon: e, emoji: t, label: n, description: r, meta: i, indicator: a, selected: o = !1, loading: s = !1, disabled: c = !1, variant: l = o ? "selected" : "neutral", onPress: u, style: d, accessibilityRole: f, accessibilityState: p, ...m }) {
6749
+ let { theme: h, scales: g } = K(), _ = c || s, v = o || l === "selected", y = a != null && a !== !1, b = Gi(l, h);
6749
6750
  return /* @__PURE__ */ D(z, {
6750
- onPress: l,
6751
- disabled: g,
6752
- accessibilityRole: d ?? "button",
6751
+ onPress: u,
6752
+ disabled: _,
6753
+ accessibilityRole: f ?? "button",
6753
6754
  accessibilityState: {
6754
- disabled: g,
6755
- selected: a,
6756
- busy: o,
6757
- ...f
6755
+ disabled: _,
6756
+ selected: v,
6757
+ busy: s,
6758
+ ...p
6758
6759
  },
6759
- ...p,
6760
+ ...m,
6760
6761
  style: ({ pressed: e }) => [{
6761
6762
  minHeight: 96,
6762
6763
  borderWidth: 1,
6763
- borderRadius: h.borderRadius.xl,
6764
- padding: h.spacing.scale[3],
6765
- gap: h.spacing.scale[3],
6764
+ borderRadius: g.borderRadius.xl,
6765
+ padding: g.spacing.scale[3],
6766
+ gap: g.spacing.scale[3],
6766
6767
  justifyContent: "space-between",
6767
- opacity: g ? .5 : 1,
6768
- ..._,
6769
- backgroundColor: e ? m.surface.secondary : _.backgroundColor
6770
- }, u],
6768
+ opacity: _ ? .5 : 1,
6769
+ ...b,
6770
+ backgroundColor: e ? h.surface.secondary : b.backgroundColor
6771
+ }, d],
6771
6772
  children: [/* @__PURE__ */ D(W, {
6772
6773
  style: {
6773
6774
  flexDirection: "row",
6774
6775
  alignItems: "flex-start",
6775
6776
  justifyContent: "space-between",
6776
- gap: h.spacing.scale[2]
6777
+ gap: g.spacing.scale[2]
6777
6778
  },
6778
6779
  children: [/* @__PURE__ */ D(W, {
6779
6780
  style: {
@@ -6781,7 +6782,7 @@ function Ki({ icon: e, emoji: t, label: n, description: r, meta: i, selected: a
6781
6782
  minWidth: 0,
6782
6783
  flexDirection: "row",
6783
6784
  alignItems: "center",
6784
- gap: h.spacing.scale[2]
6785
+ gap: g.spacing.scale[2]
6785
6786
  },
6786
6787
  children: [
6787
6788
  t && /* @__PURE__ */ E(H, {
@@ -6792,30 +6793,47 @@ function Ki({ icon: e, emoji: t, label: n, description: r, meta: i, selected: a
6792
6793
  typeof n == "string" ? /* @__PURE__ */ E(H, {
6793
6794
  numberOfLines: 1,
6794
6795
  style: [q("label.md"), {
6795
- color: m.text["high-emphasis"],
6796
+ color: h.text["high-emphasis"],
6796
6797
  flex: 1
6797
6798
  }],
6798
6799
  children: n
6799
6800
  }) : n
6800
6801
  ]
6801
- }), o && /* @__PURE__ */ E(Ge, { size: "sm" })]
6802
+ }), s ? /* @__PURE__ */ E(Ge, { size: "sm" }) : y ? typeof a == "string" || typeof a == "number" ? /* @__PURE__ */ E(H, {
6803
+ style: [q("label.md"), { color: h.text["high-emphasis"] }],
6804
+ children: a
6805
+ }) : a : v ? /* @__PURE__ */ E(W, {
6806
+ pointerEvents: "none",
6807
+ accessibilityElementsHidden: !0,
6808
+ importantForAccessibility: "no-hide-descendants",
6809
+ children: /* @__PURE__ */ E(H, {
6810
+ style: [q("label.md"), { color: h.text["accent-primary"] }],
6811
+ children: "✓"
6812
+ })
6813
+ }) : null]
6802
6814
  }), (r || i) && /* @__PURE__ */ D(W, {
6803
6815
  style: {
6804
6816
  flexDirection: "row",
6805
6817
  alignItems: "flex-end",
6806
6818
  justifyContent: "space-between",
6807
- gap: h.spacing.scale[2]
6819
+ gap: g.spacing.scale[2]
6808
6820
  },
6809
6821
  children: [typeof r == "string" ? /* @__PURE__ */ E(H, {
6810
6822
  style: [q("body.sm"), {
6811
- color: m.text["medium-emphasis"],
6823
+ color: h.text["medium-emphasis"],
6812
6824
  flex: 1
6813
6825
  }],
6814
6826
  children: r
6815
6827
  }) : r, typeof i == "string" ? /* @__PURE__ */ E(H, {
6816
- style: [q("label.sm"), { color: m.text["low-emphasis"] }],
6828
+ style: [q("label.sm"), {
6829
+ color: h.text["low-emphasis"],
6830
+ marginLeft: "auto"
6831
+ }],
6817
6832
  children: i
6818
- }) : i]
6833
+ }) : i && /* @__PURE__ */ E(W, {
6834
+ style: { marginLeft: "auto" },
6835
+ children: i
6836
+ })]
6819
6837
  })]
6820
6838
  });
6821
6839
  }
@@ -7,7 +7,14 @@ interface ActionTileProps extends Omit<React.ComponentProps<"button">, "children
7
7
  emoji?: React.ReactNode;
8
8
  label: React.ReactNode;
9
9
  description?: React.ReactNode;
10
+ /** カード下段の右端に置く補足情報(例:「所要5分」「要解放」)。選択インジケータには使わない — `indicator` を使う。 */
10
11
  meta?: React.ReactNode;
12
+ /**
13
+ * 選択状態などを示す小さな表示。**ラベル行の右端**(loading 時に Spinner が入る位置)に置かれる。
14
+ * 省略時、選択状態なら DS 標準のチェックを表示する。表示自体を消したい場合の口は用意していない
15
+ * (選択を色だけで伝えると WCAG 1.4.1 に反するため)。
16
+ */
17
+ indicator?: React.ReactNode;
11
18
  selected?: boolean;
12
19
  loading?: boolean;
13
20
  variant?: ActionTileVariant;
@@ -16,7 +23,7 @@ interface QuickActionGridProps extends React.ComponentProps<"div"> {
16
23
  columns?: QuickActionGridColumns;
17
24
  gap?: QuickActionGridGap;
18
25
  }
19
- declare function ActionTile({ className, icon, emoji, label, description, meta, selected, loading, variant, disabled, type, ...props }: ActionTileProps): React.JSX.Element;
26
+ declare function ActionTile({ className, icon, emoji, label, description, meta, indicator, selected, loading, variant, disabled, type, ...props }: ActionTileProps): React.JSX.Element;
20
27
  declare function QuickActionGrid({ className, columns, gap, ...props }: QuickActionGridProps): React.JSX.Element;
21
28
  export { ActionTile, QuickActionGrid };
22
29
  export type { ActionTileProps, ActionTileVariant, QuickActionGridColumns, QuickActionGridGap, QuickActionGridProps };
@@ -11,7 +11,14 @@ export interface ActionTileProps extends AccessibilityProps {
11
11
  emoji?: React.ReactNode;
12
12
  label: React.ReactNode;
13
13
  description?: React.ReactNode;
14
+ /** カード下段の右端に置く補足情報(例:「所要5分」「要解放」)。選択インジケータには使わない — `indicator` を使う。 */
14
15
  meta?: React.ReactNode;
16
+ /**
17
+ * 選択状態などを示す小さな表示。**ラベル行の右端**(loading 時に Spinner が入る位置)に置かれる。
18
+ * 省略時、選択状態なら DS 標準のチェックを表示する。表示自体を消したい場合の口は用意していない
19
+ * (選択を色だけで伝えると WCAG 1.4.1 に反するため)。
20
+ */
21
+ indicator?: React.ReactNode;
15
22
  selected?: boolean;
16
23
  loading?: boolean;
17
24
  disabled?: boolean;
@@ -25,5 +32,5 @@ export interface QuickActionGridProps {
25
32
  children: React.ReactNode;
26
33
  style?: StyleProp<ViewStyle>;
27
34
  }
28
- export declare function ActionTile({ icon, emoji, label, description, meta, selected, loading, disabled, variant, onPress, style, accessibilityRole, accessibilityState, ...accessibilityProps }: ActionTileProps): React.JSX.Element;
35
+ export declare function ActionTile({ icon, emoji, label, description, meta, indicator, selected, loading, disabled, variant, onPress, style, accessibilityRole, accessibilityState, ...accessibilityProps }: ActionTileProps): React.JSX.Element;
29
36
  export declare function QuickActionGrid({ columns, gap, children, style, }: QuickActionGridProps): React.JSX.Element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ksk-design-system",
3
- "version": "1.51.2",
3
+ "version": "1.52.0",
4
4
  "type": "module",
5
5
  "description": "KSK Design System — フリーランス向けマルチテーマ対応デザインシステム",
6
6
  "license": "MIT",
@@ -144,7 +144,7 @@
144
144
  | ProgressSteps | `@/components/patterns/progress-steps` | — | Step2Active, FirstStep, ThirdStep, AllComplete, ThreeSteps |
145
145
  | AUTO_PROMPT_SUPPRESSION_EVENT, AutoPrompt, PromptCoordinatorProvider | `@/components/patterns/prompt-coordinator` | — | Default |
146
146
  | Prose | `@/components/patterns/prose` | — | PrivacyPolicy, SingleSection |
147
- | ActionTile, QuickActionGrid | `@/components/patterns/quick-action-grid` | — | EmojiOnly, IconAndLabel, WithMeta, NarrowWithLongMeta |
147
+ | ActionTile, QuickActionGrid | `@/components/patterns/quick-action-grid` | — | EmojiOnly, IconAndLabel, WithMeta, IndicatorOverride, SelectedWithoutDescription, NarrowWithLongMeta |
148
148
  | ReviewOverlay | `@/components/patterns/review-overlay` | — | Default, WithPins |
149
149
  | Screen | `@/components/patterns/screen` | — | ScrollableWithFooter, WithHeader, FixedPhotoHero |
150
150
  | SearchBar | `@/components/patterns/search-bar` | — | Default, WithValue, Disabled, WithOnSearch |