@qijenchen/design-system 0.1.0-beta.83 → 0.1.0-beta.85

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 (622) hide show
  1. package/CLAUDE.md +8 -8
  2. package/README.md +3 -2
  3. package/dist/components/Alert/alert.js.map +1 -1
  4. package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -1
  5. package/dist/components/AppShell/app-shell.d.ts +1 -1
  6. package/dist/components/AppShell/app-shell.d.ts.map +1 -1
  7. package/dist/components/AppShell/app-shell.js +22 -2
  8. package/dist/components/AppShell/app-shell.js.map +1 -1
  9. package/dist/components/Avatar/avatar.d.ts.map +1 -1
  10. package/dist/components/Avatar/avatar.js +4 -4
  11. package/dist/components/Avatar/avatar.js.map +1 -1
  12. package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -1
  13. package/dist/components/Breadcrumb/breadcrumb.js +1 -1
  14. package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
  15. package/dist/components/Button/button.d.ts +2 -2
  16. package/dist/components/Button/button.d.ts.map +1 -1
  17. package/dist/components/Button/button.js +12 -3
  18. package/dist/components/Button/button.js.map +1 -1
  19. package/dist/components/Calendar/calendar.d.ts +13 -5
  20. package/dist/components/Calendar/calendar.d.ts.map +1 -1
  21. package/dist/components/Calendar/calendar.js +7 -1
  22. package/dist/components/Calendar/calendar.js.map +1 -1
  23. package/dist/components/Carousel/carousel.d.ts.map +1 -1
  24. package/dist/components/Carousel/carousel.js +8 -3
  25. package/dist/components/Carousel/carousel.js.map +1 -1
  26. package/dist/components/Chart/chart.d.ts.map +1 -1
  27. package/dist/components/Chart/chart.js +1 -0
  28. package/dist/components/Chart/chart.js.map +1 -1
  29. package/dist/components/Checkbox/checkbox.d.ts +1 -1
  30. package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
  31. package/dist/components/Checkbox/checkbox.js +8 -4
  32. package/dist/components/Checkbox/checkbox.js.map +1 -1
  33. package/dist/components/Chip/chip.d.ts +1 -1
  34. package/dist/components/Chip/chip.d.ts.map +1 -1
  35. package/dist/components/Chip/chip.js.map +1 -1
  36. package/dist/components/Coachmark/coachmark.d.ts +10 -3
  37. package/dist/components/Coachmark/coachmark.d.ts.map +1 -1
  38. package/dist/components/Coachmark/coachmark.js.map +1 -1
  39. package/dist/components/Combobox/combobox.d.ts +5 -1
  40. package/dist/components/Combobox/combobox.d.ts.map +1 -1
  41. package/dist/components/Combobox/combobox.js +30 -13
  42. package/dist/components/Combobox/combobox.js.map +1 -1
  43. package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
  44. package/dist/components/DataTable/cell-registry.js +53 -62
  45. package/dist/components/DataTable/cell-registry.js.map +1 -1
  46. package/dist/components/DataTable/column-types.d.ts +10 -4
  47. package/dist/components/DataTable/column-types.d.ts.map +1 -1
  48. package/dist/components/DataTable/column-types.js.map +1 -1
  49. package/dist/components/DataTable/data-table-column-visibility-panel.d.ts +1 -1
  50. package/dist/components/DataTable/data-table-column-visibility-panel.js +183 -0
  51. package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -0
  52. package/dist/components/DataTable/data-table-filter-group.d.ts +47 -0
  53. package/dist/components/DataTable/data-table-filter-group.d.ts.map +1 -0
  54. package/dist/components/DataTable/data-table-filter-group.js +154 -0
  55. package/dist/components/DataTable/data-table-filter-group.js.map +1 -0
  56. package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
  57. package/dist/components/DataTable/data-table-filter-panel.js +285 -0
  58. package/dist/components/DataTable/data-table-filter-panel.js.map +1 -0
  59. package/dist/components/DataTable/data-table-filter-value-picker.d.ts +29 -0
  60. package/dist/components/DataTable/data-table-filter-value-picker.d.ts.map +1 -0
  61. package/dist/components/DataTable/data-table-filter-value-picker.js +187 -0
  62. package/dist/components/DataTable/data-table-filter-value-picker.js.map +1 -0
  63. package/dist/components/DataTable/data-table-interaction-layer.d.ts +11 -15
  64. package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
  65. package/dist/components/DataTable/data-table-interaction-layer.js +1 -3
  66. package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
  67. package/dist/components/DataTable/data-table-sort-manager.js +140 -0
  68. package/dist/components/DataTable/data-table-sort-manager.js.map +1 -0
  69. package/dist/components/DataTable/data-table.d.ts +5 -6
  70. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  71. package/dist/components/DataTable/data-table.js +36 -15
  72. package/dist/components/DataTable/data-table.js.map +1 -1
  73. package/dist/components/DataTable/filter-operators.js +140 -0
  74. package/dist/components/DataTable/filter-operators.js.map +1 -0
  75. package/dist/components/DataTable/filter-tree.js +312 -0
  76. package/dist/components/DataTable/filter-tree.js.map +1 -0
  77. package/dist/components/DataTable/index.d.ts +3 -0
  78. package/dist/components/DataTable/index.d.ts.map +1 -1
  79. package/dist/components/DataTable/index.js +12 -1
  80. package/dist/components/DataTable/index.js.map +1 -1
  81. package/dist/components/DataTable/lib/column-meta.js +25 -0
  82. package/dist/components/DataTable/lib/column-meta.js.map +1 -0
  83. package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
  84. package/dist/components/DateGrid/date-grid.js +3 -1
  85. package/dist/components/DateGrid/date-grid.js.map +1 -1
  86. package/dist/components/DatePicker/date-picker.d.ts +7 -1
  87. package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
  88. package/dist/components/DatePicker/date-picker.js +105 -74
  89. package/dist/components/DatePicker/date-picker.js.map +1 -1
  90. package/dist/components/Dialog/dialog.d.ts +20 -3
  91. package/dist/components/Dialog/dialog.d.ts.map +1 -1
  92. package/dist/components/Dialog/dialog.js +38 -20
  93. package/dist/components/Dialog/dialog.js.map +1 -1
  94. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  95. package/dist/components/DropdownMenu/dropdown-menu.js +3 -1
  96. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  97. package/dist/components/Field/field-context.d.ts +45 -5
  98. package/dist/components/Field/field-context.d.ts.map +1 -1
  99. package/dist/components/Field/field-context.js +19 -0
  100. package/dist/components/Field/field-context.js.map +1 -1
  101. package/dist/components/Field/field-edit-keys.d.ts +21 -0
  102. package/dist/components/Field/field-edit-keys.d.ts.map +1 -0
  103. package/dist/components/Field/field-edit-keys.js +19 -0
  104. package/dist/components/Field/field-edit-keys.js.map +1 -0
  105. package/dist/components/Field/field-types.d.ts +20 -1
  106. package/dist/components/Field/field-types.d.ts.map +1 -1
  107. package/dist/components/Field/field-types.js.map +1 -1
  108. package/dist/components/Field/field-wrapper.d.ts +3 -2
  109. package/dist/components/Field/field-wrapper.d.ts.map +1 -1
  110. package/dist/components/Field/field-wrapper.js +38 -39
  111. package/dist/components/Field/field-wrapper.js.map +1 -1
  112. package/dist/components/Field/field.d.ts +2 -1
  113. package/dist/components/Field/field.d.ts.map +1 -1
  114. package/dist/components/Field/field.js.map +1 -1
  115. package/dist/components/Field/index.d.ts +1 -0
  116. package/dist/components/Field/index.d.ts.map +1 -1
  117. package/dist/components/Field/index.js +2 -0
  118. package/dist/components/Field/index.js.map +1 -1
  119. package/dist/components/FieldControlGroup/field-control-group.d.ts +1 -1
  120. package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
  121. package/dist/components/FileItem/file-item.d.ts.map +1 -1
  122. package/dist/components/FileItem/file-item.js +1 -1
  123. package/dist/components/FileItem/file-item.js.map +1 -1
  124. package/dist/components/FileUpload/file-upload.d.ts +1 -1
  125. package/dist/components/FileUpload/file-upload.js.map +1 -1
  126. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  127. package/dist/components/FileViewer/file-viewer.js +7 -2
  128. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  129. package/dist/components/FileViewer/image-renderer.d.ts.map +1 -1
  130. package/dist/components/FileViewer/image-renderer.js +22 -1
  131. package/dist/components/FileViewer/image-renderer.js.map +1 -1
  132. package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
  133. package/dist/components/HoverCard/hover-card.js +5 -3
  134. package/dist/components/HoverCard/hover-card.js.map +1 -1
  135. package/dist/components/InlineEdit/index.d.ts +2 -0
  136. package/dist/components/InlineEdit/index.d.ts.map +1 -0
  137. package/dist/components/InlineEdit/index.js +5 -0
  138. package/dist/components/InlineEdit/index.js.map +1 -0
  139. package/dist/components/InlineEdit/inline-edit.d.ts +59 -0
  140. package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -0
  141. package/dist/components/InlineEdit/inline-edit.js +164 -0
  142. package/dist/components/InlineEdit/inline-edit.js.map +1 -0
  143. package/dist/components/Input/input.d.ts +6 -11
  144. package/dist/components/Input/input.d.ts.map +1 -1
  145. package/dist/components/Input/input.js +43 -13
  146. package/dist/components/Input/input.js.map +1 -1
  147. package/dist/components/LinkInput/link-input.d.ts +2 -2
  148. package/dist/components/LinkInput/link-input.d.ts.map +1 -1
  149. package/dist/components/LinkInput/link-input.js +6 -5
  150. package/dist/components/LinkInput/link-input.js.map +1 -1
  151. package/dist/components/Menu/menu-item.d.ts +14 -2
  152. package/dist/components/Menu/menu-item.d.ts.map +1 -1
  153. package/dist/components/Menu/menu-item.js +25 -3
  154. package/dist/components/Menu/menu-item.js.map +1 -1
  155. package/dist/components/NumberInput/number-input.d.ts +3 -3
  156. package/dist/components/NumberInput/number-input.d.ts.map +1 -1
  157. package/dist/components/NumberInput/number-input.js +6 -5
  158. package/dist/components/NumberInput/number-input.js.map +1 -1
  159. package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
  160. package/dist/components/OverflowIndicator/overflow-indicator.js +2 -6
  161. package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
  162. package/dist/components/Pagination/pagination.js +1 -1
  163. package/dist/components/Pagination/pagination.js.map +1 -1
  164. package/dist/components/PeoplePicker/index.js +7 -1
  165. package/dist/components/PeoplePicker/index.js.map +1 -1
  166. package/dist/components/PeoplePicker/people-picker.d.ts +9 -2
  167. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  168. package/dist/components/PeoplePicker/people-picker.js +23 -10
  169. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  170. package/dist/components/PeoplePicker/person-display.d.ts +6 -3
  171. package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
  172. package/dist/components/PeoplePicker/person-display.js +19 -14
  173. package/dist/components/PeoplePicker/person-display.js.map +1 -1
  174. package/dist/components/Popover/popover.d.ts.map +1 -1
  175. package/dist/components/Popover/popover.js +3 -1
  176. package/dist/components/Popover/popover.js.map +1 -1
  177. package/dist/components/ProfileCard/profile-card.d.ts +2 -2
  178. package/dist/components/ProfileCard/profile-card.js +3 -3
  179. package/dist/components/ProfileCard/profile-card.js.map +1 -1
  180. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  181. package/dist/components/RadioGroup/radio-group.js +15 -9
  182. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  183. package/dist/components/ScrollArea/scroll-area.d.ts +11 -1
  184. package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
  185. package/dist/components/ScrollArea/scroll-area.js +6 -3
  186. package/dist/components/ScrollArea/scroll-area.js.map +1 -1
  187. package/dist/components/Select/select.d.ts +46 -5
  188. package/dist/components/Select/select.d.ts.map +1 -1
  189. package/dist/components/Select/select.js +109 -28
  190. package/dist/components/Select/select.js.map +1 -1
  191. package/dist/components/SelectMenu/select-menu.d.ts +3 -1
  192. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  193. package/dist/components/SelectMenu/select-menu.js +8 -1
  194. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  195. package/dist/components/SelectionControl/boolean-value.d.ts +11 -0
  196. package/dist/components/SelectionControl/boolean-value.d.ts.map +1 -0
  197. package/dist/components/SelectionControl/boolean-value.js +23 -0
  198. package/dist/components/SelectionControl/boolean-value.js.map +1 -0
  199. package/dist/components/SelectionControl/index.d.ts +1 -0
  200. package/dist/components/SelectionControl/index.d.ts.map +1 -1
  201. package/dist/components/SelectionControl/index.js +2 -0
  202. package/dist/components/SelectionControl/index.js.map +1 -1
  203. package/dist/components/Sheet/index.js +2 -1
  204. package/dist/components/Sheet/sheet.d.ts +7 -1
  205. package/dist/components/Sheet/sheet.d.ts.map +1 -1
  206. package/dist/components/Sheet/sheet.js +5 -2
  207. package/dist/components/Sheet/sheet.js.map +1 -1
  208. package/dist/components/Sidebar/sidebar.d.ts +9 -4
  209. package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
  210. package/dist/components/Sidebar/sidebar.js +8 -10
  211. package/dist/components/Sidebar/sidebar.js.map +1 -1
  212. package/dist/components/Slider/slider.d.ts.map +1 -1
  213. package/dist/components/Slider/slider.js.map +1 -1
  214. package/dist/components/Switch/switch.d.ts +6 -6
  215. package/dist/components/Switch/switch.d.ts.map +1 -1
  216. package/dist/components/Switch/switch.js +3 -2
  217. package/dist/components/Switch/switch.js.map +1 -1
  218. package/dist/components/Tabs/tabs.d.ts.map +1 -1
  219. package/dist/components/Tabs/tabs.js +15 -1
  220. package/dist/components/Tabs/tabs.js.map +1 -1
  221. package/dist/components/Textarea/textarea.d.ts +2 -2
  222. package/dist/components/Textarea/textarea.d.ts.map +1 -1
  223. package/dist/components/Textarea/textarea.js +50 -42
  224. package/dist/components/Textarea/textarea.js.map +1 -1
  225. package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
  226. package/dist/components/TimePicker/time-columns.js +42 -38
  227. package/dist/components/TimePicker/time-columns.js.map +1 -1
  228. package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
  229. package/dist/components/TimePicker/time-picker.js +8 -6
  230. package/dist/components/TimePicker/time-picker.js.map +1 -1
  231. package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
  232. package/dist/components/Tooltip/tooltip.js +7 -5
  233. package/dist/components/Tooltip/tooltip.js.map +1 -1
  234. package/dist/components/TreeView/tree-view.d.ts +56 -1
  235. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  236. package/dist/components/TreeView/tree-view.js +211 -12
  237. package/dist/components/TreeView/tree-view.js.map +1 -1
  238. package/dist/index.d.ts +115 -58
  239. package/dist/index.d.ts.map +1 -1
  240. package/dist/index.js +95 -108
  241. package/dist/index.js.map +1 -1
  242. package/dist/patterns/element-anatomy/item-anatomy.d.ts +7 -6
  243. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
  244. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  245. package/dist/tokens/categorical-color.js +15 -0
  246. package/dist/tokens/categorical-color.js.map +1 -1
  247. package/dist/tokens/motion/motion.d.ts +7 -6
  248. package/dist/tokens/motion/motion.d.ts.map +1 -1
  249. package/dist/tokens/motion/motion.js +6 -6
  250. package/dist/tokens/motion/motion.js.map +1 -1
  251. package/dist/tokens/motion/overlay-motion.d.ts +19 -0
  252. package/dist/tokens/motion/overlay-motion.d.ts.map +1 -0
  253. package/dist/tokens/motion/overlay-motion.js +9 -0
  254. package/dist/tokens/motion/overlay-motion.js.map +1 -0
  255. package/dist/tokens/uiSize/icon-size.js +5 -0
  256. package/dist/tokens/uiSize/icon-size.js.map +1 -0
  257. package/ds-canonical/fork/governance.lock +31 -19
  258. package/ds-canonical/fork/hooks/_log-fire.sh +46 -0
  259. package/ds-canonical/fork/hooks/block_prototype_imports.py +15 -4
  260. package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +145 -13
  261. package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +2 -1
  262. package/ds-canonical/fork/hooks/check_dynamic_tailwind_class.sh +47 -0
  263. package/ds-canonical/fork/hooks/check_escape_marker_abuse.sh +27 -0
  264. package/ds-canonical/fork/hooks/check_field_family_invariants.sh +61 -1
  265. package/ds-canonical/fork/hooks/check_layout_space_magic_numbers.sh +28 -4
  266. package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +28 -0
  267. package/ds-canonical/fork/hooks/check_story_determinism.sh +2 -0
  268. package/ds-canonical/fork/hooks/check_story_invariants.sh +119 -0
  269. package/ds-canonical/fork/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  270. package/ds-canonical/fork/manifest.json +15 -0
  271. package/ds-canonical/fork/preamble.md +20 -18
  272. package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +3 -3
  273. package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +3 -3
  274. package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +1 -1
  275. package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +3 -3
  276. package/ds-canonical/fork/skills/propose-options/SKILL.md +3 -3
  277. package/ds-canonical/fork/skills/prototype/SKILL.md +1 -1
  278. package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +2 -2
  279. package/ds-canonical/fork/skills/visual-audit/SKILL.md +2 -2
  280. package/ds-canonical/hooks/README.md +1 -1
  281. package/ds-canonical/hooks/block_prototype_imports.py +15 -4
  282. package/ds-canonical/hooks/check_audit_post_report_validator.sh +65 -7
  283. package/ds-canonical/hooks/check_codex_brief_invariants.sh +28 -1
  284. package/ds-canonical/hooks/check_consumer_app_invariants.sh +145 -13
  285. package/ds-canonical/hooks/check_datatable_invariants.sh +6 -3
  286. package/ds-canonical/hooks/check_ds_anchor_preflight.sh +2 -1
  287. package/ds-canonical/hooks/check_dynamic_tailwind_class.sh +47 -0
  288. package/ds-canonical/hooks/check_escape_marker_abuse.sh +27 -0
  289. package/ds-canonical/hooks/check_field_family_invariants.sh +61 -1
  290. package/ds-canonical/hooks/check_layout_space_magic_numbers.sh +28 -4
  291. package/ds-canonical/hooks/check_naming_and_abstraction.sh +1 -1
  292. package/ds-canonical/hooks/check_opacity_token_usage.sh +28 -0
  293. package/ds-canonical/hooks/check_pixel_quantified_audit.sh +3 -2
  294. package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +6 -1
  295. package/ds-canonical/hooks/check_ssot_header_declaration.sh +3 -1
  296. package/ds-canonical/hooks/check_story_determinism.sh +2 -0
  297. package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +8 -7
  298. package/ds-canonical/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  299. package/ds-canonical/hooks/lib/_story_compile_drift.sh +1 -1
  300. package/ds-canonical/hooks/lib/_token_hygiene.sh +10 -1
  301. package/ds-canonical/hooks/stop_self_audit.sh +31 -0
  302. package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +24 -0
  303. package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +44 -0
  304. package/ds-canonical/hooks/tests/test_check_codex_brief_invariants.sh +43 -2
  305. package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +112 -0
  306. package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +9 -2
  307. package/ds-canonical/hooks/tests/test_check_dynamic_tailwind_class.sh +76 -0
  308. package/ds-canonical/hooks/tests/test_check_escape_marker_abuse.sh +24 -0
  309. package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +27 -2
  310. package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +39 -0
  311. package/ds-canonical/hooks/tests/test_check_tabs_content_chrome_body_double_gap.sh +76 -0
  312. package/ds-canonical/references/audit-coverage-vs-24-checklist.md +1 -1
  313. package/ds-canonical/references/build-ui-canonicals.md +2 -1
  314. package/ds-canonical/references/failure-class-registry.json +145 -0
  315. package/ds-canonical/references/governance-audit-coverage.md +33 -0
  316. package/ds-canonical/references/item-anatomy-recipe.md +2 -2
  317. package/ds-canonical/references/scenario-definition.md +6 -9
  318. package/ds-canonical/references/ssot-consultation.md +2 -2
  319. package/ds-canonical/references/ssot-index.md +5 -4
  320. package/ds-canonical/references/story-baseline-registry.json +8 -2
  321. package/ds-canonical/references/structural-token-retention.md +6 -9
  322. package/ds-canonical/rules/meta-patterns.md +8 -8
  323. package/ds-canonical/rules/self-verify.md +4 -3
  324. package/ds-canonical/rules/story-rules.md +2 -2
  325. package/ds-canonical/rules/ui-development.md +2 -2
  326. package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +3 -3
  327. package/ds-canonical/skills/code-quality-audit/SKILL.md +3 -3
  328. package/ds-canonical/skills/codex-collab/SKILL.md +9 -7
  329. package/ds-canonical/skills/codex-collab/references/brief-template.md +1 -1
  330. package/ds-canonical/skills/codify-principle/SKILL.md +2 -2
  331. package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
  332. package/ds-canonical/skills/component-quality-gate/references/checklist.md +2 -2
  333. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +51 -58
  334. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +29 -0
  335. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +29 -10
  336. package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +21 -0
  337. package/ds-canonical/skills/delivery-handoff/SKILL.md +1 -1
  338. package/ds-canonical/skills/design-system-audit/SKILL.md +26 -25
  339. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +13 -1
  340. package/ds-canonical/skills/design-system-audit/references/rule-placement.md +1 -1
  341. package/ds-canonical/skills/governance-health/SKILL.md +1 -1
  342. package/ds-canonical/skills/knowledge-prune/SKILL.md +3 -0
  343. package/ds-canonical/skills/knowledge-prune/references/prune-dimensions-d5-d10.md +1 -0
  344. package/ds-canonical/skills/new-component/SKILL.md +5 -5
  345. package/ds-canonical/skills/new-component/references/new-component-checklist.md +1 -1
  346. package/ds-canonical/skills/product-ui-audit/SKILL.md +3 -3
  347. package/ds-canonical/skills/propose-options/SKILL.md +3 -3
  348. package/ds-canonical/skills/prototype/SKILL.md +1 -1
  349. package/ds-canonical/skills/scan-similar-bugs/SKILL.md +2 -2
  350. package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +3 -3
  351. package/ds-canonical/skills/story-writing/SKILL.md +3 -3
  352. package/ds-canonical/skills/visual-audit/SKILL.md +2 -2
  353. package/ds-story-manifest.json +29 -20
  354. package/llms-full.txt +22 -1
  355. package/llms.txt +5 -4
  356. package/package.json +7 -3
  357. package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
  358. package/src/components/Accordion/accordion.stories.tsx +16 -1
  359. package/src/components/Alert/alert.principles.stories.tsx +1 -1
  360. package/src/components/Alert/alert.spec.md +8 -10
  361. package/src/components/Alert/alert.stories.tsx +28 -28
  362. package/src/components/Alert/alert.tsx +1 -1
  363. package/src/components/AppShell/_demo-helpers.tsx +6 -3
  364. package/src/components/AppShell/app-shell.spec.md +4 -4
  365. package/src/components/AppShell/app-shell.tsx +28 -2
  366. package/src/components/AspectRatio/aspect-ratio.spec.md +1 -1
  367. package/src/components/AspectRatio/aspect-ratio.stories.tsx +7 -89
  368. package/src/components/Avatar/avatar.anatomy.stories.tsx +7 -3
  369. package/src/components/Avatar/avatar.principles.stories.tsx +19 -15
  370. package/src/components/Avatar/avatar.spec.md +2 -2
  371. package/src/components/Avatar/avatar.stories.tsx +8 -6
  372. package/src/components/Avatar/avatar.tsx +13 -5
  373. package/src/components/Badge/badge.principles.stories.tsx +1 -1
  374. package/src/components/Badge/badge.spec.md +2 -0
  375. package/src/components/Badge/badge.stories.tsx +4 -2
  376. package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +6 -4
  377. package/src/components/Breadcrumb/breadcrumb.stories.tsx +6 -5
  378. package/src/components/Breadcrumb/breadcrumb.tsx +3 -2
  379. package/src/components/BulkActionBar/bulk-action-bar.spec.md +4 -2
  380. package/src/components/Button/button.principles.stories.tsx +1 -1
  381. package/src/components/Button/button.spec.md +2 -2
  382. package/src/components/Button/button.tsx +18 -3
  383. package/src/components/Calendar/calendar.anatomy.stories.tsx +12 -10
  384. package/src/components/Calendar/calendar.principles.stories.tsx +14 -6
  385. package/src/components/Calendar/calendar.spec.md +5 -4
  386. package/src/components/Calendar/calendar.stories.tsx +7 -4
  387. package/src/components/Calendar/calendar.tsx +26 -7
  388. package/src/components/Carousel/carousel.anatomy.stories.tsx +5 -4
  389. package/src/components/Carousel/carousel.spec.md +2 -2
  390. package/src/components/Carousel/carousel.tsx +11 -3
  391. package/src/components/Chart/chart.anatomy.stories.tsx +7 -4
  392. package/src/components/Chart/chart.principles.stories.tsx +1 -1
  393. package/src/components/Chart/chart.stories.tsx +2 -8
  394. package/src/components/Chart/chart.tsx +3 -0
  395. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +28 -49
  396. package/src/components/Checkbox/checkbox.principles.stories.tsx +1 -1
  397. package/src/components/Checkbox/checkbox.spec.md +13 -26
  398. package/src/components/Checkbox/checkbox.stories.tsx +11 -8
  399. package/src/components/Checkbox/checkbox.tsx +18 -13
  400. package/src/components/Chip/chip.anatomy.stories.tsx +44 -24
  401. package/src/components/Chip/chip.principles.stories.tsx +1 -1
  402. package/src/components/Chip/chip.spec.md +5 -4
  403. package/src/components/Chip/chip.tsx +5 -1
  404. package/src/components/CircularProgress/circular-progress.principles.stories.tsx +7 -4
  405. package/src/components/CircularProgress/circular-progress.spec.md +3 -3
  406. package/src/components/CircularProgress/circular-progress.stories.tsx +2 -2
  407. package/src/components/Coachmark/coachmark.anatomy.stories.tsx +2 -2
  408. package/src/components/Coachmark/coachmark.principles.stories.tsx +2 -1
  409. package/src/components/Coachmark/coachmark.spec.md +5 -5
  410. package/src/components/Coachmark/coachmark.stories.tsx +3 -1
  411. package/src/components/Coachmark/coachmark.tsx +10 -3
  412. package/src/components/Combobox/combobox.anatomy.stories.tsx +2 -2
  413. package/src/components/Combobox/combobox.tsx +53 -19
  414. package/src/components/Command/command.anatomy.stories.tsx +2 -2
  415. package/src/components/Command/command.principles.stories.tsx +1 -1
  416. package/src/components/Command/command.stories.tsx +42 -10
  417. package/src/components/DataTable/cell-registry.tsx +86 -63
  418. package/src/components/DataTable/column-types.ts +10 -1
  419. package/src/components/DataTable/data-table-column-visibility-panel.tsx +1 -1
  420. package/src/components/DataTable/data-table-filter-group.tsx +231 -0
  421. package/src/components/DataTable/data-table-filter-panel.tsx +16 -430
  422. package/src/components/DataTable/data-table-filter-value-picker.tsx +237 -0
  423. package/src/components/DataTable/data-table-interaction-layer.tsx +15 -19
  424. package/src/components/DataTable/data-table.anatomy.stories.tsx +15 -13
  425. package/src/components/DataTable/data-table.principles.stories.tsx +9 -9
  426. package/src/components/DataTable/data-table.spec.md +33 -13
  427. package/src/components/DataTable/data-table.stories.tsx +16 -17
  428. package/src/components/DataTable/data-table.tsx +107 -61
  429. package/src/components/DataTable/filter-operators.spec.md +3 -3
  430. package/src/components/DataTable/index.ts +3 -0
  431. package/src/components/DateGrid/date-grid.anatomy.stories.tsx +4 -4
  432. package/src/components/DateGrid/date-grid.principles.stories.tsx +1 -1
  433. package/src/components/DateGrid/date-grid.spec.md +1 -1
  434. package/src/components/DateGrid/date-grid.tsx +3 -1
  435. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +8 -8
  436. package/src/components/DatePicker/date-picker.principles.stories.tsx +3 -3
  437. package/src/components/DatePicker/date-picker.spec.md +3 -3
  438. package/src/components/DatePicker/date-picker.stories.tsx +4 -5
  439. package/src/components/DatePicker/date-picker.tsx +99 -45
  440. package/src/components/DescriptionList/description-list.anatomy.stories.tsx +12 -10
  441. package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
  442. package/src/components/DescriptionList/description-list.spec.md +3 -3
  443. package/src/components/DescriptionList/description-list.stories.tsx +7 -6
  444. package/src/components/Dialog/dialog.anatomy.stories.tsx +1 -0
  445. package/src/components/Dialog/dialog.spec.md +9 -0
  446. package/src/components/Dialog/dialog.stories.tsx +66 -5
  447. package/src/components/Dialog/dialog.tsx +60 -25
  448. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +1 -1
  449. package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +8 -6
  450. package/src/components/DropdownMenu/dropdown-menu.spec.md +5 -5
  451. package/src/components/DropdownMenu/dropdown-menu.tsx +18 -9
  452. package/src/components/Empty/empty.anatomy.stories.tsx +1 -1
  453. package/src/components/Empty/empty.spec.md +2 -2
  454. package/src/components/Field/field-context.ts +69 -5
  455. package/src/components/Field/field-controls.spec.md +62 -8
  456. package/src/components/Field/field-edit-keys.ts +66 -0
  457. package/src/components/Field/field-types.ts +58 -9
  458. package/src/components/Field/field-wrapper.tsx +50 -42
  459. package/src/components/Field/field.anatomy.stories.tsx +9 -6
  460. package/src/components/Field/field.spec.md +1 -1
  461. package/src/components/Field/field.stories.tsx +1 -1
  462. package/src/components/Field/field.tsx +2 -1
  463. package/src/components/Field/form-validation.spec.md +3 -3
  464. package/src/components/Field/index.ts +1 -0
  465. package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +6 -6
  466. package/src/components/FieldControlGroup/field-control-group.spec.md +9 -4
  467. package/src/components/FieldControlGroup/field-control-group.tsx +1 -1
  468. package/src/components/FileItem/file-item.anatomy.stories.tsx +1 -1
  469. package/src/components/FileItem/file-item.spec.md +5 -8
  470. package/src/components/FileItem/file-item.stories.tsx +36 -25
  471. package/src/components/FileItem/file-item.tsx +8 -6
  472. package/src/components/FileUpload/file-upload.anatomy.stories.tsx +6 -6
  473. package/src/components/FileUpload/file-upload.principles.stories.tsx +5 -5
  474. package/src/components/FileUpload/file-upload.spec.md +1 -1
  475. package/src/components/FileUpload/file-upload.tsx +1 -1
  476. package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +4 -3
  477. package/src/components/FileViewer/file-viewer.principles.stories.tsx +3 -3
  478. package/src/components/FileViewer/file-viewer.spec.md +30 -12
  479. package/src/components/FileViewer/file-viewer.stories.tsx +1 -2
  480. package/src/components/FileViewer/file-viewer.tsx +12 -4
  481. package/src/components/FileViewer/image-renderer.tsx +35 -7
  482. package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -2
  483. package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -3
  484. package/src/components/HoverCard/hover-card.spec.md +5 -5
  485. package/src/components/HoverCard/hover-card.stories.tsx +16 -16
  486. package/src/components/HoverCard/hover-card.tsx +5 -3
  487. package/src/components/InlineEdit/index.ts +5 -0
  488. package/src/components/InlineEdit/inline-edit.spec.md +149 -0
  489. package/src/components/InlineEdit/inline-edit.stories.tsx +246 -0
  490. package/src/components/InlineEdit/inline-edit.tsx +287 -0
  491. package/src/components/Input/input.anatomy.stories.tsx +8 -7
  492. package/src/components/Input/input.principles.stories.tsx +2 -12
  493. package/src/components/Input/input.spec.md +13 -18
  494. package/src/components/Input/input.tsx +69 -22
  495. package/src/components/LinkInput/link-input.anatomy.stories.tsx +1 -1
  496. package/src/components/LinkInput/link-input.principles.stories.tsx +2 -2
  497. package/src/components/LinkInput/link-input.tsx +11 -10
  498. package/src/components/Menu/menu-item.anatomy.stories.tsx +3 -3
  499. package/src/components/Menu/menu-item.principles.stories.tsx +1 -1
  500. package/src/components/Menu/menu-item.spec.md +22 -15
  501. package/src/components/Menu/menu-item.stories.tsx +39 -11
  502. package/src/components/Menu/menu-item.tsx +38 -4
  503. package/src/components/Notice/notice.principles.stories.tsx +1 -1
  504. package/src/components/Notice/notice.spec.md +16 -3
  505. package/src/components/NumberInput/number-input.anatomy.stories.tsx +3 -3
  506. package/src/components/NumberInput/number-input.principles.stories.tsx +1 -1
  507. package/src/components/NumberInput/number-input.spec.md +4 -4
  508. package/src/components/NumberInput/number-input.tsx +19 -12
  509. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +10 -8
  510. package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +3 -3
  511. package/src/components/OverflowIndicator/overflow-indicator.spec.md +4 -2
  512. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +71 -63
  513. package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -8
  514. package/src/components/Pagination/pagination.spec.md +1 -1
  515. package/src/components/Pagination/pagination.stories.tsx +2 -6
  516. package/src/components/Pagination/pagination.tsx +1 -1
  517. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +4 -4
  518. package/src/components/PeoplePicker/people-picker.principles.stories.tsx +2 -2
  519. package/src/components/PeoplePicker/people-picker.spec.md +6 -6
  520. package/src/components/PeoplePicker/people-picker.tsx +56 -16
  521. package/src/components/PeoplePicker/person-display.tsx +32 -16
  522. package/src/components/Popover/popover.anatomy.stories.tsx +2 -2
  523. package/src/components/Popover/popover.tsx +3 -1
  524. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +12 -23
  525. package/src/components/ProfileCard/profile-card.spec.md +3 -3
  526. package/src/components/ProfileCard/profile-card.tsx +6 -6
  527. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +3 -1
  528. package/src/components/ProgressBar/progress-bar.principles.stories.tsx +1 -1
  529. package/src/components/ProgressBar/progress-bar.stories.tsx +50 -42
  530. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +10 -28
  531. package/src/components/RadioGroup/radio-group.stories.tsx +29 -32
  532. package/src/components/RadioGroup/radio-group.tsx +41 -15
  533. package/src/components/Rating/rating.spec.md +11 -3
  534. package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
  535. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
  536. package/src/components/ScrollArea/scroll-area.spec.md +7 -3
  537. package/src/components/ScrollArea/scroll-area.stories.tsx +1 -1
  538. package/src/components/ScrollArea/scroll-area.tsx +17 -4
  539. package/src/components/Select/select.anatomy.stories.tsx +3 -3
  540. package/src/components/Select/select.spec.md +29 -17
  541. package/src/components/Select/select.stories.tsx +33 -0
  542. package/src/components/Select/select.tsx +190 -36
  543. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +4 -4
  544. package/src/components/SelectMenu/select-menu.spec.md +15 -7
  545. package/src/components/SelectMenu/select-menu.tsx +16 -3
  546. package/src/components/SelectionControl/boolean-value.tsx +39 -0
  547. package/src/components/SelectionControl/index.ts +1 -0
  548. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +2 -2
  549. package/src/components/SelectionControl/selection-item.principles.stories.tsx +2 -2
  550. package/src/components/SelectionControl/selection-item.spec.md +3 -3
  551. package/src/components/SelectionControl/selection-item.stories.tsx +3 -3
  552. package/src/components/Separator/separator.spec.md +2 -2
  553. package/src/components/Separator/separator.stories.tsx +6 -27
  554. package/src/components/Sheet/sheet.anatomy.stories.tsx +1 -1
  555. package/src/components/Sheet/sheet.principles.stories.tsx +1 -1
  556. package/src/components/Sheet/sheet.spec.md +2 -2
  557. package/src/components/Sheet/sheet.tsx +9 -5
  558. package/src/components/Sidebar/sidebar.anatomy.stories.tsx +16 -12
  559. package/src/components/Sidebar/sidebar.principles.stories.tsx +10 -8
  560. package/src/components/Sidebar/sidebar.spec.md +13 -15
  561. package/src/components/Sidebar/sidebar.stories.tsx +8 -7
  562. package/src/components/Sidebar/sidebar.tsx +37 -25
  563. package/src/components/Skeleton/skeleton.stories.tsx +4 -11
  564. package/src/components/Slider/slider.anatomy.stories.tsx +3 -3
  565. package/src/components/Slider/slider.principles.stories.tsx +2 -2
  566. package/src/components/Slider/slider.spec.md +5 -5
  567. package/src/components/Slider/slider.tsx +3 -1
  568. package/src/components/Steps/steps.anatomy.stories.tsx +4 -4
  569. package/src/components/Steps/steps.principles.stories.tsx +1 -1
  570. package/src/components/Steps/steps.spec.md +1 -1
  571. package/src/components/Switch/switch.anatomy.stories.tsx +7 -7
  572. package/src/components/Switch/switch.principles.stories.tsx +4 -4
  573. package/src/components/Switch/switch.spec.md +8 -8
  574. package/src/components/Switch/switch.stories.tsx +9 -24
  575. package/src/components/Switch/switch.tsx +17 -13
  576. package/src/components/Tabs/tabs.anatomy.stories.tsx +10 -7
  577. package/src/components/Tabs/tabs.spec.md +1 -1
  578. package/src/components/Tabs/tabs.tsx +21 -1
  579. package/src/components/Textarea/textarea.anatomy.stories.tsx +1 -1
  580. package/src/components/Textarea/textarea.principles.stories.tsx +1 -1
  581. package/src/components/Textarea/textarea.spec.md +4 -4
  582. package/src/components/Textarea/textarea.tsx +72 -46
  583. package/src/components/TimePicker/time-columns.tsx +6 -2
  584. package/src/components/TimePicker/time-picker.principles.stories.tsx +1 -1
  585. package/src/components/TimePicker/time-picker.spec.md +3 -3
  586. package/src/components/TimePicker/time-picker.tsx +16 -10
  587. package/src/components/Toast/toast.stories.tsx +7 -4
  588. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +4 -4
  589. package/src/components/Tooltip/tooltip.principles.stories.tsx +3 -3
  590. package/src/components/Tooltip/tooltip.spec.md +1 -1
  591. package/src/components/Tooltip/tooltip.stories.tsx +4 -39
  592. package/src/components/Tooltip/tooltip.tsx +8 -6
  593. package/src/components/TreeView/tree-view.anatomy.stories.tsx +6 -3
  594. package/src/components/TreeView/tree-view.spec.md +42 -11
  595. package/src/components/TreeView/tree-view.stories.tsx +1 -0
  596. package/src/components/TreeView/tree-view.tsx +322 -17
  597. package/src/index.ts +588 -60
  598. package/src/patterns/action-bar/action-bar.spec.md +9 -0
  599. package/src/patterns/action-bar/action-bar.stories.tsx +6 -3
  600. package/src/patterns/element-anatomy/inline-action.spec.md +2 -0
  601. package/src/patterns/element-anatomy/item-anatomy.spec.md +14 -5
  602. package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -4
  603. package/src/patterns/element-anatomy/item-anatomy.tsx +7 -6
  604. package/src/patterns/header-canonical/header-canonical.spec.md +5 -4
  605. package/src/patterns/overlay-surface/overlay-surface.spec.md +22 -1
  606. package/src/styles/tokens.css +3 -0
  607. package/src/tokens/README.md +1 -1
  608. package/src/tokens/color/color.spec.md +4 -4
  609. package/src/tokens/color/color.stories.tsx +3 -3
  610. package/src/tokens/density/density.stories.tsx +16 -3
  611. package/src/tokens/layoutSpace/layoutSpace.spec.md +3 -1
  612. package/src/tokens/motion/motion.css +33 -21
  613. package/src/tokens/motion/motion.spec.md +32 -15
  614. package/src/tokens/motion/motion.stories.tsx +58 -5
  615. package/src/tokens/motion/motion.ts +7 -6
  616. package/src/tokens/motion/overlay-motion.ts +26 -0
  617. package/src/tokens/orphan-tokens.spec.md +4 -4
  618. package/src/tokens/token-system.spec.md +1 -0
  619. package/src/tokens/uiSize/uiSize.css +1 -1
  620. package/src/tokens/uiSize/uiSize.spec.md +1 -1
  621. package/src/tokens/uiSize/uiSize.stories.tsx +4 -2
  622. package/src/tokens/utility-registry.json +160 -23
@@ -1,5 +1,8 @@
1
1
  // @benchmark-unverified-blanket: file-level retraction per M22 (d) — claims herein not individually URL-cited; treat as unverified visual/usage rumor unless retrofit per-claim. Hook escape preserved.
2
2
  // @anatomy-exempt: anatomy specs / token 對照表格用 raw <table>,非業務資料表。業務資料表才用 <DataTable>。
3
+ // @overlay-open-skip: 本檔絕大多數 story 直接 render ProfileCard(內容不藏在浮層,snapshot 可見);
4
+ // 唯一 HoverCard demo 只示範「hover 整合」消費方式,open-state 內容已由同檔直接 render 的
5
+ // stories 完整快照,forced defaultOpen 反而讓浮層蓋住旁邊的說明。
3
6
  // @anatomy-rationale:
4
7
  // SizeMatrix N/A — ProfileCard 是固定寬度(320px)hover content template,
5
8
  // 不提供 size prop;所有尺寸 token 已於 Overview「Layout Token」段列出
@@ -51,12 +54,7 @@ export const Overview: Story = {
51
54
  subtitle="Design Engineer · Engineering"
52
55
  status="online"
53
56
  statusMessage="目前 Sprint 23 衝刺中,訊息可能稍慢回覆"
54
- actions={
55
- <>
56
- <Button variant="primary" size="sm" startIcon={MessageCircle}>傳訊</Button>
57
- <Button variant="tertiary" size="sm" startIcon={UserPlus}>追蹤</Button>
58
- </>
59
- }
57
+ actions={<ProfileCardDefaultActions />}
60
58
  fields={[
61
59
  { label: 'Email', value: 'ada.chen@example.com' },
62
60
  { label: '團隊', value: 'Engineering' },
@@ -228,18 +226,13 @@ export const SectionMatrix: Story = {
228
226
 
229
227
  <div>
230
228
  <H3>+ Actions</H3>
231
- <Desc>加上快速動作——留言區 hover 顯示「傳訊」/「追蹤」,減少跳轉 profile 頁的摩擦。</Desc>
229
+ <Desc>加上快速動作——留言區 hover 顯示「Chat」/「Audio call」(canonical `ProfileCardDefaultActions`),減少跳轉 profile 頁的摩擦。</Desc>
232
230
  <div className="border border-dashed border-divider rounded-md p-4 inline-block">
233
231
  <ProfileCard
234
232
  name="Diana Lin"
235
233
  subtitle="Engineering Manager"
236
234
  status="online"
237
- actions={
238
- <>
239
- <Button variant="primary" size="sm" startIcon={MessageCircle}>傳訊</Button>
240
- <Button variant="tertiary" size="sm" startIcon={UserPlus}>追蹤</Button>
241
- </>
242
- }
235
+ actions={<ProfileCardDefaultActions />}
243
236
  />
244
237
  </div>
245
238
  </div>
@@ -271,12 +264,7 @@ export const SectionMatrix: Story = {
271
264
  subtitle="Design Engineer · Engineering"
272
265
  status="online"
273
266
  statusMessage="目前專案 Sprint 23 衝刺中"
274
- actions={
275
- <>
276
- <Button variant="primary" size="sm" startIcon={MessageCircle}>傳訊</Button>
277
- <Button variant="tertiary" size="sm" startIcon={UserPlus}>追蹤</Button>
278
- </>
279
- }
267
+ actions={<ProfileCardDefaultActions />}
280
268
  fields={[
281
269
  { label: 'Email', value: 'ada.chen@example.com' },
282
270
  { label: '團隊', value: 'Engineering' },
@@ -366,14 +354,14 @@ export const HoverCardIntegration: Story = {
366
354
  </Desc>
367
355
  <div className="border border-border rounded-lg p-6 flex items-center gap-8">
368
356
  {[
369
- { name: 'Ada Chen(範例人名)', subtitle: 'Design Engineer', status: 'online' as const },
370
- { name: 'Alice Wang', subtitle: 'Frontend Engineer', status: 'busy' as const },
371
- { name: 'Bob Chen', subtitle: 'PM, Growth', status: 'away' as const },
357
+ { name: 'Ada Chen', subtitle: 'Design Engineer', status: 'online' as const, avatarUrl: 'https://i.pravatar.cc/80?u=ada-chen' },
358
+ { name: 'Alice Wang', subtitle: 'Frontend Engineer', status: 'busy' as const, avatarUrl: 'https://i.pravatar.cc/80?u=alice-wang' },
359
+ { name: 'Bob Chen', subtitle: 'PM, Growth', status: 'away' as const, avatarUrl: 'https://i.pravatar.cc/80?u=bob-chen' },
372
360
  ].map(p => (
373
361
  <HoverCard key={p.name}>
374
362
  <HoverCardTrigger asChild>
375
363
  <span className="inline-block cursor-pointer">
376
- <Avatar alt={p.name} size={40} status={p.status} />
364
+ <Avatar src={p.avatarUrl} alt={p.name} size={40} status={p.status} />
377
365
  </span>
378
366
  </HoverCardTrigger>
379
367
  <HoverCardContent align="start" className="p-0">{/* sideOffset 不 override — spec 禁止事項(default 即 OVERLAY_SIDE_OFFSET) */}
@@ -381,6 +369,7 @@ export const HoverCardIntegration: Story = {
381
369
  name={p.name}
382
370
  subtitle={p.subtitle}
383
371
  status={p.status}
372
+ avatar={{ src: p.avatarUrl, alt: p.name }}
384
373
  fields={[
385
374
  { label: 'Email', value: `${p.name.split(' ')[0].toLowerCase()}@example.com` },
386
375
  { label: '團隊', value: 'Engineering' },
@@ -57,13 +57,13 @@ ProfileCard 是**三層 chrome 結構**(2026-04-23 canonical):
57
57
  │ BODY(可垂直捲動) │ ← Status section(v12 conditional)+ Info fields(always-render)
58
58
  │ ↕ 空間不足時此區捲動 │ Status undefined → 整 status block skip
59
59
  ├─────────────────────────────┤
60
- │ FOOTER(固定不捲) │ ← View more(hover context 必含,詳「View More」)
60
+ │ FOOTER(固定不捲) │ ← View more( onViewMore 時顯示,詳「View More」)
61
61
  └─────────────────────────────┘
62
62
  ```
63
63
 
64
64
  - **Header 固定**:Profile + Actions 一體,**不捲動**(使用者的視覺 anchor:誰 + 可對他做什麼)
65
65
  - **Body 可捲動**:Status section + Info fields。以 `<ScrollArea>` 包(cross-OS overlay 捲軸)
66
- - **Footer 固定**:View more **永遠可見**(hover preview 的 escape hatch 到完整 profile)
66
+ - **Footer 固定**:傳入 `onViewMore` 時 View more 固定於底(條件渲染 `{onViewMore && …}`,未傳則不渲染 footer)——是 hover preview 到完整 profile 的 escape hatch(對齊本 spec「View More」段 + `profile-card.tsx` footer 條件渲染)
67
67
 
68
68
  **Status section v12 conditional rule(2026-05-14 user 拍板)**:`status` 在 production 一定會被設定(每個 user 都有 presence state)。如果 status undefined,**唯一可能性 = 資料還沒讀到(loading transient)**,**不**是「user 沒設定狀態」。所以 status undefined 期間 → **整 status block 隱藏**(等資料到才 render),**禁** render「Status not set」這種 placeholder 文字(語義錯,user presence 不會「沒設定」)。**此規則 ProfileCard-specific 不外推至 DS 其他元件**(FileItem / DescriptionList / DataTable cell 各自 placeholder 邏輯 unrelated)。
69
69
 
@@ -134,7 +134,7 @@ ProfileCard 的 default actions **是 `Chat + Audio call`**(chat app 標配,cano
134
134
 
135
135
  - **Name / Subtitle 超長**:自然換行撐高 header,不截斷(text column 最小高度對齊 avatar,見「Profile Header」)
136
136
  - **Status / statusMessage 缺值**:status undefined = loading transient → 整 status block 隱藏(v12 rule,見「結構」);ProfileCard **無整卡 loading prop**,資料未到的整卡呈現由 consumer 決定
137
- - **Info fields 缺值**:default fields 永遠 render,缺資料顯 `—` placeholder(section 結構不收合);consumer `fields` label 撞 default 時 consumer 值 win(dedup canonical,詳 `profile-card.tsx`)
137
+ - **Info fields 缺值**:default fields 永遠 render,缺資料顯半形 `-` placeholder(`text-foreground`——對齊 DS 空值顯示 canonical:不可編輯供檢視的空值同 readonly 值色;section 結構不收合);consumer `fields` label 撞 default 時 consumer 值 win(dedup canonical,詳 `profile-card.tsx`)
138
138
  - **內容過長**:Body 在固定高度內以 ScrollArea 捲動,不 clamp 行數(見「Status 區」)
139
139
 
140
140
  ---
@@ -105,7 +105,7 @@ const STATUS_LABEL: Record<StatusType, string> = {
105
105
  * 各自不一致(同 person 在 DataTable / PeoplePicker / avatar.principles 看起來不同)。
106
106
  *
107
107
  * v11 canonical(歷史):ProfileCard 當時 always renders 4 default sections — 缺 data → 顯
108
- * `EMPTY_PLACEHOLDER`("")。現行:default fields 縮為 2(v15.7)+ status 條件 render(v12),
108
+ * `EMPTY_PLACEHOLDER`("-")。現行:default fields 縮為 2(v15.7)+ status 條件 render(v12),
109
109
  * 「視覺結構 SSOT 在此元件,不依賴 consumer」原則不變。
110
110
  *
111
111
  * ── 對齊 world-class ──
@@ -128,7 +128,7 @@ const DEFAULT_FIELD_LABEL: Record<ProfileCardDefaultFieldKey, string> = {
128
128
  employeeNumber: 'Employee number',
129
129
  }
130
130
 
131
- const FIELD_PLACEHOLDER = ''
131
+ const FIELD_PLACEHOLDER = '-'
132
132
 
133
133
  export interface ProfileCardProps extends React.HTMLAttributes<HTMLDivElement> {
134
134
  name: string
@@ -139,7 +139,7 @@ export interface ProfileCardProps extends React.HTMLAttributes<HTMLDivElement> {
139
139
  actions?: React.ReactNode
140
140
  /**
141
141
  * Consumer 傳的 field 資料(partial)。預設 keys 走 `NAMECARD_DEFAULT_FIELD_KEYS` —
142
- * 只有 id / employeeNumber 兩個 default field 永遠 render(缺資料顯 `—`);email / phone /
142
+ * 只有 id / employeeNumber 兩個 default field 永遠 render(缺資料顯 `-`);email / phone /
143
143
  * department / location 等其他欄位一律 opt-in by consumer 透過本 prop 傳入。Consumer 想新增
144
144
  * 自訂 field 直接傳入(在 default 之後 append),想 override default key value 也直接傳。
145
145
  */
@@ -178,7 +178,7 @@ const ProfileCard = React.forwardRef<HTMLDivElement, ProfileCardProps>(
178
178
  //
179
179
  // **Dedup canonical(2026-05-07 v15.8 fix Bug E)**:consumer 的 `fields` array 若含
180
180
  // label 撞 default(eg. 「ID」「Employee number」),consumer 值 win — defaults 那一行
181
- // 跳過(否則 same label 連 render 兩次,如 default placeholder `—` + consumer 真值)。
181
+ // 跳過(否則 same label 連 render 兩次,如 default placeholder `-` + consumer 真值)。
182
182
  // 這是遷移期 forgiving 行為:DEV warn 提示應改用 `defaultFieldValues`,但 production
183
183
  // 不破壞既有 consumer。對齊 React `key` 唯一性 + Linear / Slack profile card 一 label
184
184
  // 一 row idiom。
@@ -292,7 +292,7 @@ const ProfileCard = React.forwardRef<HTMLDivElement, ProfileCardProps>(
292
292
  message 是一組;沒 status 就沒 status message)。缺 statusMessage 顯 placeholder。 */}
293
293
  <DescriptionList>
294
294
  <DescriptionItem label="Status message">
295
- {statusMessage ?? <span className="text-fg-muted">{FIELD_PLACEHOLDER}</span>}
295
+ {statusMessage ?? <span className="text-foreground">{FIELD_PLACEHOLDER}</span>}
296
296
  </DescriptionItem>
297
297
  </DescriptionList>
298
298
  </div>
@@ -304,7 +304,7 @@ const ProfileCard = React.forwardRef<HTMLDivElement, ProfileCardProps>(
304
304
  {allFields.map((f) => (
305
305
  <DescriptionItem key={f.label} label={f.label}>
306
306
  {f.value === FIELD_PLACEHOLDER
307
- ? <span className="text-fg-muted">{FIELD_PLACEHOLDER}</span>
307
+ ? <span className="text-foreground">{FIELD_PLACEHOLDER}</span>
308
308
  : f.value}
309
309
  </DescriptionItem>
310
310
  ))}
@@ -74,8 +74,10 @@ export const Overview = {
74
74
  <div className="h-full rounded-full bg-info" style={{ width: '45%' }} />
75
75
  </div>
76
76
  </div>
77
+ {/* 2026-07-14 dim-55 修:`--magenta`/`--magenta-subtle` 不存在(semantic magenta namespace
78
+ 只有 hover/active)→ anatomy 圖解標記屬 categorical 靜態色,消費 primitive step token */}
77
79
  <span className="rounded px-2 py-0.5 text-[11px] font-mono border border-dashed"
78
- style={{ borderColor: 'var(--magenta)', backgroundColor: 'var(--magenta-subtle)', color: 'var(--magenta)' }}>affix</span>
80
+ style={{ borderColor: 'var(--color-magenta-6)', backgroundColor: 'var(--color-magenta-1)', color: 'var(--color-magenta-7)' }}>affix</span>
79
81
  </div>
80
82
  <span className="text-[10px] text-fg-muted font-mono">wrapper: flex items-center gap-2 · bar: flex-1 min-w-0</span>
81
83
  </div>
@@ -129,7 +129,7 @@ export const UsageGuidance: Story = {
129
129
  </div>
130
130
  </div>
131
131
  </Frame>
132
- <Label>✅ 每檔一條,整體進度由使用者自然感知(2/3 完成)</Label>
132
+ <Label>✅ 每檔一條,整體進度由使用者自然感知(1 檔完成、2 檔進行中)</Label>
133
133
  </Rule>
134
134
 
135
135
  <Rule
@@ -1,6 +1,10 @@
1
+ // @story-baseline: packages/design-system/src/components/DataTable/data-table.anatomy.stories.tsx#AlignmentRule
1
2
  import type { Meta, StoryObj } from '@storybook/react'
3
+ import type { ColumnDef } from '@tanstack/react-table'
2
4
  import { FileText, Table as TableIcon } from 'lucide-react'
3
5
  import { ProgressBar } from './progress-bar'
6
+ import { DataTable } from '@/design-system/components/DataTable/data-table'
7
+ import '@/design-system/components/DataTable/column-types' // ColumnMeta declaration merging
4
8
 
5
9
  const meta: Meta<typeof ProgressBar> = {
6
10
  title: 'Design System/Components/ProgressBar/展示',
@@ -70,50 +74,54 @@ export const BatchTask: Story = {
70
74
  }
71
75
 
72
76
  // ── 真實情境 3: DataTable cell inline 進度 ─────────────────────────────
77
+ // 2026-07-14 audit(R1 A.2):手刻 table markup → 消費真 <DataTable>(對齊 Skeleton
78
+ // TableRowLoading 同款 consumer-自訂-cell 模式;columns 不設 meta.type 走自訂 cell)。
73
79
 
74
- export const InlineTableCell: Story = {
75
- name: 'DataTable 儲存格內進度',
76
- render: () => {
77
- const rows = [
78
- { name: 'Acme Corp 專案', quota: 45, status: 'inProgress' as const },
79
- { name: 'Globex 整合', quota: 78, status: 'inProgress' as const },
80
- { name: 'Initech 改版', quota: 100, status: 'success' as const },
81
- { name: 'Umbrella 導入', quota: 12, status: 'inProgress' as const },
82
- { name: 'Wonka 客製化', quota: 95, status: 'error' as const },
83
- ]
84
- return (
85
- <div className="flex flex-col gap-4 w-[560px]">
86
- <SectionTitle>配額使用率(DataTable inline)</SectionTitle>
87
- <SectionDesc>
88
- Table cell 內顯示配額使用率(4px 細線不搶走主要欄位的閱讀重量)。value affix 讓使用者快速讀數字。
89
- </SectionDesc>
90
- <div className="border border-border rounded-md overflow-hidden bg-surface">
91
- <table className="w-full text-body">
92
- <thead className="bg-muted text-caption text-fg-secondary">
93
- <tr>
94
- <th className="text-left px-4 py-2 font-medium">專案</th>
95
- <th className="text-left px-4 py-2 font-medium w-[240px]">配額使用率</th>
96
- </tr>
97
- </thead>
98
- <tbody>
99
- {rows.map((r) => (
100
- <tr key={r.name} className="border-t border-divider">
101
- <td className="px-4 py-3">
102
- <div className="flex items-center gap-2">
103
- <FileText size={16} className="text-fg-muted shrink-0" />
104
- {r.name}
105
- </div>
106
- </td>
107
- <td className="px-4 py-3">
108
- <ProgressBar value={r.quota} status={r.status} affix="value" />
109
- </td>
110
- </tr>
111
- ))}
112
- </tbody>
113
- </table>
114
- </div>
80
+ interface QuotaRow {
81
+ name: string
82
+ quota: number
83
+ status: 'inProgress' | 'success' | 'error'
84
+ }
85
+
86
+ const quotaRows: QuotaRow[] = [
87
+ { name: 'Acme Corp 專案', quota: 45, status: 'inProgress' },
88
+ { name: 'Globex 整合', quota: 78, status: 'inProgress' },
89
+ { name: 'Initech 改版', quota: 100, status: 'success' },
90
+ { name: 'Umbrella 導入', quota: 12, status: 'inProgress' },
91
+ { name: 'Wonka 客製化', quota: 95, status: 'error' },
92
+ ]
93
+
94
+ const quotaColumns: ColumnDef<QuotaRow>[] = [
95
+ {
96
+ id: 'name',
97
+ header: '專案',
98
+ cell: ({ row }) => (
99
+ <div className="flex items-center gap-2">
100
+ <FileText size={16} className="text-fg-muted shrink-0" />
101
+ {row.original.name}
115
102
  </div>
116
- )
103
+ ),
117
104
  },
105
+ {
106
+ id: 'quota',
107
+ header: '配額使用率',
108
+ meta: { width: 240 },
109
+ cell: ({ row }) => (
110
+ <ProgressBar value={row.original.quota} status={row.original.status} affix="value" />
111
+ ),
112
+ },
113
+ ]
114
+
115
+ export const InlineTableCell: Story = {
116
+ name: 'DataTable 儲存格內進度',
117
+ render: () => (
118
+ <div className="flex flex-col gap-4 w-[560px]">
119
+ <SectionTitle>配額使用率(DataTable inline)</SectionTitle>
120
+ <SectionDesc>
121
+ Table cell 內顯示配額使用率(4px 細線不搶走主要欄位的閱讀重量)。value affix 讓使用者快速讀數字。
122
+ </SectionDesc>
123
+ <DataTable columns={quotaColumns} data={quotaRows} getRowId={(r) => r.name} height="auto" />
124
+ </div>
125
+ ),
118
126
  }
119
127
 
@@ -1,7 +1,6 @@
1
1
  import type { Meta } from '@storybook/react'
2
2
  import { useState } from 'react'
3
3
  import { RadioGroup, RadioGroupItem } from './radio-group'
4
- import { SelectionItem } from '@/design-system/components/SelectionControl/selection-item'
5
4
 
6
5
  const meta: Meta = {
7
6
  title: 'Design System/Components/RadioGroup/設計規格',
@@ -287,20 +286,18 @@ const InspectorInner = () => {
287
286
  {/* Live preview */}
288
287
  <div className="px-10 py-8 rounded-lg bg-canvas border border-divider flex items-center justify-center gap-6">
289
288
  <RadioGroup defaultValue={checked === 'checked' ? 'preview' : undefined} className="flex gap-4">
290
- <SelectionItem
289
+ <RadioGroupItem
291
290
  size={size}
292
- control={<RadioGroupItem value="preview" id="preview-radio" size={size} disabled={state === 'disabled'} />}
291
+ value="preview"
293
292
  label="信用卡"
294
293
  description={withDescription ? '支援 Visa / Mastercard / JCB,結帳時直接扣款' : undefined}
295
- htmlFor="preview-radio"
296
294
  disabled={state === 'disabled'}
297
295
  />
298
- <SelectionItem
296
+ <RadioGroupItem
299
297
  size={size}
300
- control={<RadioGroupItem value="other" id="preview-other" size={size} disabled={state === 'disabled'} />}
298
+ value="other"
301
299
  label="ATM 轉帳"
302
300
  description={withDescription ? '取得虛擬帳號後 3 天內完成付款' : undefined}
303
- htmlFor="preview-other"
304
301
  disabled={state === 'disabled'}
305
302
  />
306
303
  </RadioGroup>
@@ -534,26 +531,9 @@ export const SizeMatrix = {
534
531
  <div key={sz} className="flex flex-col gap-2">
535
532
  <span className="text-[11px] text-fg-muted font-mono">size="{sz}" ({SIZE_SPECS[sz].controlPx}px)</span>
536
533
  <RadioGroup defaultValue="a">
537
- <SelectionItem
538
- size={sz}
539
- control={<RadioGroupItem value="a" id={`sz-${sz}-a`} size={sz} />}
540
- label="即時"
541
- htmlFor={`sz-${sz}-a`}
542
- />
543
- <SelectionItem
544
- size={sz}
545
- control={<RadioGroupItem value="b" id={`sz-${sz}-b`} size={sz} />}
546
- label="每日摘要"
547
- description="每天晚上 9 點寄一次"
548
- htmlFor={`sz-${sz}-b`}
549
- />
550
- <SelectionItem
551
- size={sz}
552
- control={<RadioGroupItem value="c" id={`sz-${sz}-c`} size={sz} disabled />}
553
- label="每週摘要"
554
- htmlFor={`sz-${sz}-c`}
555
- disabled
556
- />
534
+ <RadioGroupItem size={sz} value="a" label="即時" />
535
+ <RadioGroupItem size={sz} value="b" label="每日摘要" description="每天晚上 9 點寄一次" />
536
+ <RadioGroupItem size={sz} value="c" label="每週摘要" disabled />
557
537
  </RadioGroup>
558
538
  </div>
559
539
  ))}
@@ -629,8 +609,10 @@ const StateBehaviorInner = () => {
629
609
  {/* Whole group disabled */}
630
610
  <div className="flex flex-col gap-3">
631
611
  <span className="text-caption font-medium text-fg-secondary">行為 3:整組 disabled(Field context 接管)</span>
612
+ {/* 架構理由(移出 user-visible Desc,per story-rules.md 人話原則):item 經 useResolvedFieldDisabled
613
+ 繼承 Field 的 disabled;SSOT = field-controls.spec.md cascade 段。 */}
632
614
  <Desc>
633
- 整個 RadioGroup 放在 disabled 的 Field 內時,所有 item 經 useResolvedFieldDisabled 繼承 disabled——consumer 不需逐 item 傳 disabled(SSOT:field-controls.spec.md cascade 段)。下方示意為靜態模擬(逐 item 傳 disabled 重現相同視覺);實際使用以 {'<Field disabled>'} 包裹即可。
615
+ 整組放進停用的 Field 時,裡面每個選項會自動一起變灰,不需逐一設定。下方為靜態示意(逐 item 傳 disabled 重現相同視覺);實際使用以 {'<Field disabled>'} 包裹即可。
634
616
  </Desc>
635
617
  <div className="flex gap-6 items-start">
636
618
  <div className="px-6 py-5 rounded-lg bg-canvas border border-divider min-w-[280px]">
@@ -1,7 +1,6 @@
1
1
  // @story-trait-rationale: hasSizes 由 anatomy.stories.tsx SizeMatrix auto-compile owns size showcase(2026-05-15 F-migration);Default scenario 由 WithLabel / HorizontalLayout 等真實 form 情境 story 覆蓋。
2
2
  import type { Meta, StoryObj } from '@storybook/react'
3
3
  import { RadioGroup, RadioGroupItem } from './radio-group'
4
- import { SelectionItem } from '@/design-system/components/SelectionControl/selection-item'
5
4
 
6
5
  const meta: Meta<typeof RadioGroupItem> = {
7
6
  title: 'Design System/Components/RadioGroup/展示',
@@ -12,6 +11,10 @@ const meta: Meta<typeof RadioGroupItem> = {
12
11
  export default meta
13
12
  type Story = StoryObj<typeof RadioGroupItem>
14
13
 
14
+ // 2026-07-14 dim-68 修:展示層原直用 internal <SelectionItem control={...} htmlFor>(selection-item.spec.md
15
+ // 「何時用」明文禁止裸用)→ 收斂為公開 <RadioGroupItem value label description>(自動 wire SelectionItem
16
+ // + id/htmlFor),與同元件 principles / anatomy 層一致 — 三層 story 一律示範公開 API。
17
+
15
18
  // @story-trait-rationale: pre-existing trait gaps tracked separately; this PR scope = add Modes story with display card.
16
19
  /* ── 四模式 ── */
17
20
  export const Modes: Story = {
@@ -21,35 +24,35 @@ export const Modes: Story = {
21
24
  <div>
22
25
  <h3 className="text-body font-bold text-foreground mb-2">edit</h3>
23
26
  <RadioGroup defaultValue="yearly" aria-label="付款方案(edit mode demo)">
24
- <SelectionItem control={<RadioGroupItem value="monthly" id="m-edit" />} label="月付方案" htmlFor="m-edit" />
25
- <SelectionItem control={<RadioGroupItem value="yearly" id="y-edit" />} label="年付方案" description="每年 $2,990,省下兩個月" htmlFor="y-edit" />
26
- <SelectionItem control={<RadioGroupItem value="lifetime" id="l-edit" />} label="終身方案" htmlFor="l-edit" />
27
+ <RadioGroupItem value="monthly" label="月付方案" />
28
+ <RadioGroupItem value="yearly" label="年付方案" description="每年 $2,990,省下兩個月" />
29
+ <RadioGroupItem value="lifetime" label="終身方案" />
27
30
  </RadioGroup>
28
31
  </div>
29
32
  <div>
30
33
  <h3 className="text-body font-bold text-foreground mb-2">display</h3>
31
34
  <RadioGroup mode="display" value="yearly" aria-label="付款方案(display mode demo)">
32
- <SelectionItem control={<RadioGroupItem value="monthly" id="m-disp" />} label="月付方案" htmlFor="m-disp" />
33
- <SelectionItem control={<RadioGroupItem value="yearly" id="y-disp" />} label="年付方案" description="每年 $2,990,省下兩個月" htmlFor="y-disp" />
34
- <SelectionItem control={<RadioGroupItem value="lifetime" id="l-disp" />} label="終身方案" htmlFor="l-disp" />
35
+ <RadioGroupItem value="monthly" label="月付方案" />
36
+ <RadioGroupItem value="yearly" label="年付方案" description="每年 $2,990,省下兩個月" />
37
+ <RadioGroupItem value="lifetime" label="終身方案" />
35
38
  </RadioGroup>
36
39
  </div>
37
40
  <div>
38
41
  <h3 className="text-body font-bold text-foreground mb-2">readonly</h3>
39
- <RadioGroup value="yearly" aria-label="付款方案(readonly mode demo)">
40
- <SelectionItem control={<RadioGroupItem value="monthly" id="m-ro" readOnly />} label="月付方案" htmlFor="m-ro" />
41
- <SelectionItem control={<RadioGroupItem value="yearly" id="y-ro" readOnly />} label="年付方案" htmlFor="y-ro" />
42
- <SelectionItem control={<RadioGroupItem value="lifetime" id="l-ro" readOnly />} label="終身方案" htmlFor="l-ro" />
42
+ <RadioGroup mode="readonly" value="yearly" aria-label="付款方案(readonly mode demo)">
43
+ <RadioGroupItem value="monthly" label="月付方案" />
44
+ <RadioGroupItem value="yearly" label="年付方案" />
45
+ <RadioGroupItem value="lifetime" label="終身方案" />
43
46
  </RadioGroup>
44
47
  </div>
45
48
  <div>
46
49
  <h3 className="text-body font-bold text-foreground mb-2">disabled</h3>
47
50
  {/* mode="disabled" → Radix Root disabled 原生 propagate 全 item(radio 控件真停用);
48
- SelectionItem disabled 另管 label 降色 雙傳對齊「停用」story 寫法 */}
51
+ RadioGroupDisabledContext 同步讓每個 item label/description text-fg-disabled */}
49
52
  <RadioGroup mode="disabled" value="yearly" aria-label="付款方案(disabled mode demo)">
50
- <SelectionItem control={<RadioGroupItem value="monthly" id="m-dis" />} label="月付方案" htmlFor="m-dis" disabled />
51
- <SelectionItem control={<RadioGroupItem value="yearly" id="y-dis" />} label="年付方案" htmlFor="y-dis" disabled />
52
- <SelectionItem control={<RadioGroupItem value="lifetime" id="l-dis" />} label="終身方案" htmlFor="l-dis" disabled />
53
+ <RadioGroupItem value="monthly" label="月付方案" />
54
+ <RadioGroupItem value="yearly" label="年付方案" />
55
+ <RadioGroupItem value="lifetime" label="終身方案" />
53
56
  </RadioGroup>
54
57
  </div>
55
58
  </div>
@@ -58,7 +61,7 @@ export const Modes: Story = {
58
61
 
59
62
  // @story-trait-rationale: States retired 2026-05-17 per audit Dim 24 —
60
63
  // anatomy.stories.tsx SizeMatrix + StateBehavior own size/state trait grid。
61
- // 展示層保留 typical real-product Group 情境(Vertical/Horizontal/Modes/Disabled)。
64
+ // 展示層保留 typical real-product Group 情境(Vertical/Horizontal/Modes)。
62
65
 
63
66
  /* ── 垂直 Group ── */
64
67
  export const VerticalGroup: Story = {
@@ -69,9 +72,9 @@ export const VerticalGroup: Story = {
69
72
  <div key={size}>
70
73
  <p className="text-caption text-fg-muted mb-1">size="{size}"</p>
71
74
  <RadioGroup defaultValue="monthly">
72
- <SelectionItem size={size} control={<RadioGroupItem value="monthly" id={`${size}-monthly`} size={size} />} label="月付方案" htmlFor={`${size}-monthly`} />
73
- <SelectionItem size={size} control={<RadioGroupItem value="yearly" id={`${size}-yearly`} size={size} />} label="年付方案" description="每年 $2,990,省下兩個月" htmlFor={`${size}-yearly`} />
74
- <SelectionItem size={size} control={<RadioGroupItem value="lifetime" id={`${size}-lifetime`} size={size} />} label="終身方案" htmlFor={`${size}-lifetime`} />
75
+ <RadioGroupItem size={size} value="monthly" label="月付方案" />
76
+ <RadioGroupItem size={size} value="yearly" label="年付方案" description="每年 $2,990,省下兩個月" />
77
+ <RadioGroupItem size={size} value="lifetime" label="終身方案" />
75
78
  </RadioGroup>
76
79
  </div>
77
80
  ))}
@@ -84,20 +87,14 @@ export const Horizontal: Story = {
84
87
  name: '水平排列',
85
88
  render: () => (
86
89
  <RadioGroup defaultValue="light" className="flex gap-6 max-w-md">
87
- <SelectionItem control={<RadioGroupItem value="light" id="h-light" />} label="淺色" htmlFor="h-light" />
88
- <SelectionItem control={<RadioGroupItem value="dark" id="h-dark" />} label="深色" htmlFor="h-dark" />
89
- <SelectionItem control={<RadioGroupItem value="system" id="h-system" />} label="系統" htmlFor="h-system" />
90
+ <RadioGroupItem value="light" label="淺色" />
91
+ <RadioGroupItem value="dark" label="深色" />
92
+ <RadioGroupItem value="system" label="系統" />
90
93
  </RadioGroup>
91
94
  ),
92
95
  }
93
96
 
94
- /* ── Disabled ── */
95
- export const Disabled: Story = {
96
- name: '停用',
97
- render: () => (
98
- <RadioGroup defaultValue="bank" className="max-w-sm">
99
- <SelectionItem control={<RadioGroupItem value="bank" id="dis-a" disabled />} label="銀行轉帳" description="帳單已開立,付款方式鎖定" htmlFor="dis-a" disabled />
100
- <SelectionItem control={<RadioGroupItem value="invoice" id="dis-b" disabled />} label="月結發票" description="需企業方案才能使用" htmlFor="dis-b" disabled />
101
- </RadioGroup>
102
- ),
103
- }
97
+ // @story-trait-rationale: Disabled retired 2026-07-14 per audit Dim 24 —
98
+ // disabled 覆蓋已由 Modes story disabled 列 + anatomy StateBehavior
99
+ // 「Mutual Exclusion + Disabled Item Matrix」owns;對齊 Checkbox / Switch
100
+ // 同 Family retire 的獨立 Disabled story。
@@ -10,7 +10,8 @@ import { useFieldContext, useResolvedFieldMode, useResolvedFieldDisabled, useRes
10
10
  import { SelectionItem } from "@/design-system/components/SelectionControl/selection-item"
11
11
  import type { LucideIcon } from "lucide-react"
12
12
  import type { AvatarData } from "@/design-system/components/Avatar/avatar"
13
- import { EMPTY_DISPLAY, fieldWrapperStyles } from "@/design-system/components/Field/field-wrapper"
13
+ import { fieldWrapperStyles } from "@/design-system/components/Field/field-wrapper"
14
+ import { useFieldEmptyDisplay, fieldEmptyColorClass } from '@/design-system/components/Field/field-context'
14
15
 
15
16
  // ── RadioGroup display mode ─────────────────────────────────────────────────
16
17
  // RadioGroup mode='display' 時:Group 不渲染 Radix primitive(無 radio 視覺),
@@ -44,6 +45,11 @@ export interface RadioGroupProps
44
45
  // (item 已支援 readOnly prop + data-[readonly] 樣式;Radix Root 無 readOnly,故用 context)。
45
46
  const RadioGroupReadonlyContext = React.createContext(false)
46
47
 
48
+ // group-level disabled(standalone <RadioGroup disabled>)→ context 傳給 items,讓 SelectionItem
49
+ // label/description 也降 text-fg-disabled(Radix Root disabled 只 propagate 給 radio 圈、不碰 label 色)。
50
+ // 對齊本檔 RadioGroupReadonlyContext 既有模式 + spec「Disabled」邊界案例(Group-level disabled 視覺繼承 SelectionItem SSOT text-fg-disabled)。
51
+ const RadioGroupDisabledContext = React.createContext(false)
52
+
47
53
  // walk children 找 control.value === selectedValue 的 SelectionItem label(display / readonly-in-Field 共用)
48
54
  function findSelectedRadioLabel(children: React.ReactNode, selectedValue: string | undefined): React.ReactNode {
49
55
  let selectedLabel: React.ReactNode = null
@@ -73,6 +79,7 @@ const RadioGroup = React.forwardRef<
73
79
  >(({ className, mode, variant: _chrome, value, defaultValue, ...props }, ref) => {
74
80
  // 2026-06-08 SSOT cascade:resolvedMode 經 resolver hook 讀 fieldCtx(原 root 完全不讀 → <Field disabled>/<Field mode> 失效)
75
81
  const resolvedMode = useResolvedFieldMode({ mode, disabled: (props as { disabled?: boolean }).disabled })
82
+ const emptyDisplay = useFieldEmptyDisplay()
76
83
  const fieldCtx = useFieldContext()
77
84
  // readonly 灰框 size:走 SSOT resolver(RadioGroup 無 size prop → ctx > 'md')
78
85
  const resolvedBoxSize = useResolvedFieldSize(undefined, 'md') as 'sm' | 'md' | 'lg'
@@ -100,7 +107,7 @@ const RadioGroup = React.forwardRef<
100
107
  if (resolvedMode === 'display') {
101
108
  const selectedValue = (value ?? defaultValue) as string | undefined
102
109
  if (!selectedValue) {
103
- return <div {...restDomProps} ref={ref as React.Ref<HTMLDivElement>} role="group" className={cn('grid', className)}><span className="text-fg-muted">{EMPTY_DISPLAY}</span></div>
110
+ return <div {...restDomProps} ref={ref as React.Ref<HTMLDivElement>} role="group" className={cn('grid', className)}><span className={fieldEmptyColorClass(resolvedMode)}>{emptyDisplay}</span></div>
104
111
  }
105
112
  const selectedLabel = findSelectedRadioLabel(props.children, selectedValue)
106
113
  return (
@@ -136,7 +143,7 @@ const RadioGroup = React.forwardRef<
136
143
  >
137
144
  {selectedValue
138
145
  ? <span className="text-foreground">{selectedLabel ?? selectedValue}</span>
139
- : <span className="text-fg-muted">{EMPTY_DISPLAY}</span>}
146
+ : <span className={fieldEmptyColorClass(resolvedMode)}>{emptyDisplay}</span>}
140
147
  </div>
141
148
  )
142
149
  }
@@ -145,20 +152,34 @@ const RadioGroup = React.forwardRef<
145
152
  // mode='readonly' → context 傳 readOnly 給 items(item 渲染為 data-[readonly] 鎖互動 + aria-readonly)。
146
153
  return (
147
154
  <RadioGroupReadonlyContext.Provider value={resolvedMode === 'readonly'}>
148
- <RadioGroupPrimitive.Root
149
- className={cn("grid", className)}
150
- value={value}
151
- defaultValue={defaultValue}
152
- {...props}
153
- disabled={resolvedMode === 'disabled'}
154
- ref={ref}
155
- />
155
+ <RadioGroupDisabledContext.Provider value={resolvedMode === 'disabled'}>
156
+ <RadioGroupPrimitive.Root
157
+ className={cn("grid", className)}
158
+ value={value}
159
+ defaultValue={defaultValue}
160
+ // Field 內:role="radiogroup" <div> 無法被 <label for> 命名 → 自讀 fieldCtx 接
161
+ // aria-labelledby / aria-invalid / aria-describedby(field-context.ts「下游 control 需自讀
162
+ // labelId」;對齊 slider.tsx / Rating / TimePicker 的 fieldLabelId 接線 + 上方 readonly-in-Field 分支)。
163
+ // standalone(無 Field)時皆 undefined,consumer 的 {...props} aria-* 照舊生效(置於 spread 前故可被覆蓋)。
164
+ aria-labelledby={fieldCtx?.labelId}
165
+ aria-invalid={fieldCtx?.invalid || undefined}
166
+ aria-describedby={fieldCtx?.descriptionId}
167
+ // a11y(2026-07-14 dim-10):readonly 語意放 radiogroup(aria-readonly 合法 role;
168
+ // 對齊上方 readonly-in-Field 分支 L133)。item(role=radio)不帶 aria-readonly —
169
+ // axe 實證 radio 不允許該屬性,item 靠 data-readonly + tabIndex + click guard 鎖互動。
170
+ aria-readonly={resolvedMode === 'readonly' || undefined}
171
+ {...props}
172
+ disabled={resolvedMode === 'disabled'}
173
+ ref={ref}
174
+ />
175
+ </RadioGroupDisabledContext.Provider>
156
176
  </RadioGroupReadonlyContext.Provider>
157
177
  )
158
178
  })
159
179
  RadioGroup.displayName = 'RadioGroup'
160
180
  // Field layout 宣告:RadioGroup 是 block primitive(多項堆疊),
161
- // 進入 <Field> 時 control area 自動切 items-start + padding-top 公式對齊。
181
+ // 進入 <Field> 時 control area 自動切 items-start(block 分支不設 min-h、不加 padding-top,
182
+ // 高度由內容決定;額外加 paddingTop 會 double padding — field.tsx block control area SSOT)。
162
183
  // Convention 詳見 components/Field/field.spec.md「Control area:Inline vs Block」段落。
163
184
  ;(RadioGroup as unknown as { fieldLayout: 'block' }).fieldLayout = 'block'
164
185
 
@@ -261,7 +282,10 @@ const RadioGroupItem = React.forwardRef<
261
282
  // RadioGroupItem 的 label 是「該選項」的 label(每 item 各自擁有),
262
283
  // FieldLabel 則是整個 RadioGroup 的 label。
263
284
  // 因此 RadioGroupItem 的 label 不因 Field context 被忽略。
264
- const resolvedDisabled = useResolvedFieldDisabled(disabled)
285
+ // group-level disabled(standalone <RadioGroup disabled>)也要降 label/description 色 —— Radix Root
286
+ // disabled 只 propagate 給 radio 圈,label 色由 SelectionItem disabled 決定,故讀 RadioGroupDisabledContext 補上。
287
+ const groupDisabled = React.useContext(RadioGroupDisabledContext)
288
+ const resolvedDisabled = useResolvedFieldDisabled(disabled) || groupDisabled
265
289
  // group-level readonly(RadioGroup mode='readonly')或 item-level readOnly,任一 true 即鎖互動。
266
290
  const groupReadonly = React.useContext(RadioGroupReadonlyContext)
267
291
  const effectiveReadonly = readOnly || groupReadonly
@@ -274,7 +298,9 @@ const RadioGroupItem = React.forwardRef<
274
298
  id={inputId}
275
299
  ref={ref}
276
300
  disabled={resolvedDisabled}
277
- aria-readonly={effectiveReadonly || undefined}
301
+ // a11y(2026-07-14 dim-10):item(role=radio)不帶 aria-readonly axe 實證 radio 不允許
302
+ // 該屬性(readonly 語意由 Root role=radiogroup 宣告,見上方 L167-170)。item 靠
303
+ // data-readonly + tabIndex + click guard 鎖互動。
278
304
  data-readonly={effectiveReadonly || undefined}
279
305
  tabIndex={effectiveReadonly ? -1 : undefined}
280
306
  className={cn(radioItemVariants({ size }), className)}
@@ -331,7 +357,7 @@ export const radioGroupMeta = {
331
357
  },
332
358
  sizes: {
333
359
  // iconSize = 渲染指示器尺寸(對齊 checkbox/switch meta 慣例:checkbox iconSize=真 Check glyph 12/12/16)。
334
- // Radio 指示器是 filled dot 非 glyph,真值 = dotSize 8/8/10(radio-group.tsx:179);
360
+ // Radio 指示器是 filled dot 非 glyph,真值 = 上方 `const dotSize` map 8/8/10;
335
361
  // 控件框 16/16/20 與 Checkbox 對齊但那是 box 非「指示器」,不入此鍵(避免 metadata 語意 drift)。
336
362
  sm: { fieldHeight: 28, iconSize: 8, typography: 'body' },
337
363
  md: { fieldHeight: 32, iconSize: 8, typography: 'body' },