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

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 (604) 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-panel.d.ts.map +1 -1
  53. package/dist/components/DataTable/data-table-filter-panel.js +607 -0
  54. package/dist/components/DataTable/data-table-filter-panel.js.map +1 -0
  55. package/dist/components/DataTable/data-table-interaction-layer.d.ts +11 -15
  56. package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
  57. package/dist/components/DataTable/data-table-interaction-layer.js +1 -3
  58. package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
  59. package/dist/components/DataTable/data-table-sort-manager.js +140 -0
  60. package/dist/components/DataTable/data-table-sort-manager.js.map +1 -0
  61. package/dist/components/DataTable/data-table.d.ts +5 -6
  62. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  63. package/dist/components/DataTable/data-table.js +36 -15
  64. package/dist/components/DataTable/data-table.js.map +1 -1
  65. package/dist/components/DataTable/filter-operators.js +140 -0
  66. package/dist/components/DataTable/filter-operators.js.map +1 -0
  67. package/dist/components/DataTable/filter-tree.js +312 -0
  68. package/dist/components/DataTable/filter-tree.js.map +1 -0
  69. package/dist/components/DataTable/index.d.ts +3 -0
  70. package/dist/components/DataTable/index.d.ts.map +1 -1
  71. package/dist/components/DataTable/index.js +12 -1
  72. package/dist/components/DataTable/index.js.map +1 -1
  73. package/dist/components/DataTable/lib/column-meta.js +25 -0
  74. package/dist/components/DataTable/lib/column-meta.js.map +1 -0
  75. package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
  76. package/dist/components/DateGrid/date-grid.js +3 -1
  77. package/dist/components/DateGrid/date-grid.js.map +1 -1
  78. package/dist/components/DatePicker/date-picker.d.ts +7 -1
  79. package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
  80. package/dist/components/DatePicker/date-picker.js +105 -74
  81. package/dist/components/DatePicker/date-picker.js.map +1 -1
  82. package/dist/components/Dialog/dialog.d.ts +20 -3
  83. package/dist/components/Dialog/dialog.d.ts.map +1 -1
  84. package/dist/components/Dialog/dialog.js +38 -20
  85. package/dist/components/Dialog/dialog.js.map +1 -1
  86. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  87. package/dist/components/DropdownMenu/dropdown-menu.js +3 -1
  88. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  89. package/dist/components/Field/field-context.d.ts +45 -5
  90. package/dist/components/Field/field-context.d.ts.map +1 -1
  91. package/dist/components/Field/field-context.js +19 -0
  92. package/dist/components/Field/field-context.js.map +1 -1
  93. package/dist/components/Field/field-edit-keys.d.ts +21 -0
  94. package/dist/components/Field/field-edit-keys.d.ts.map +1 -0
  95. package/dist/components/Field/field-edit-keys.js +19 -0
  96. package/dist/components/Field/field-edit-keys.js.map +1 -0
  97. package/dist/components/Field/field-types.d.ts +20 -1
  98. package/dist/components/Field/field-types.d.ts.map +1 -1
  99. package/dist/components/Field/field-types.js.map +1 -1
  100. package/dist/components/Field/field-wrapper.d.ts +3 -2
  101. package/dist/components/Field/field-wrapper.d.ts.map +1 -1
  102. package/dist/components/Field/field-wrapper.js +38 -39
  103. package/dist/components/Field/field-wrapper.js.map +1 -1
  104. package/dist/components/Field/field.d.ts +2 -1
  105. package/dist/components/Field/field.d.ts.map +1 -1
  106. package/dist/components/Field/field.js.map +1 -1
  107. package/dist/components/FieldControlGroup/field-control-group.d.ts +1 -1
  108. package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
  109. package/dist/components/FileItem/file-item.d.ts.map +1 -1
  110. package/dist/components/FileItem/file-item.js +1 -1
  111. package/dist/components/FileItem/file-item.js.map +1 -1
  112. package/dist/components/FileUpload/file-upload.d.ts +1 -1
  113. package/dist/components/FileUpload/file-upload.js.map +1 -1
  114. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  115. package/dist/components/FileViewer/file-viewer.js +7 -2
  116. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  117. package/dist/components/FileViewer/image-renderer.d.ts.map +1 -1
  118. package/dist/components/FileViewer/image-renderer.js +22 -1
  119. package/dist/components/FileViewer/image-renderer.js.map +1 -1
  120. package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
  121. package/dist/components/HoverCard/hover-card.js +5 -3
  122. package/dist/components/HoverCard/hover-card.js.map +1 -1
  123. package/dist/components/InlineEdit/index.d.ts +2 -0
  124. package/dist/components/InlineEdit/index.d.ts.map +1 -0
  125. package/dist/components/InlineEdit/index.js +5 -0
  126. package/dist/components/InlineEdit/index.js.map +1 -0
  127. package/dist/components/InlineEdit/inline-edit.d.ts +59 -0
  128. package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -0
  129. package/dist/components/InlineEdit/inline-edit.js +164 -0
  130. package/dist/components/InlineEdit/inline-edit.js.map +1 -0
  131. package/dist/components/Input/input.d.ts +6 -11
  132. package/dist/components/Input/input.d.ts.map +1 -1
  133. package/dist/components/Input/input.js +43 -13
  134. package/dist/components/Input/input.js.map +1 -1
  135. package/dist/components/LinkInput/link-input.d.ts +2 -2
  136. package/dist/components/LinkInput/link-input.d.ts.map +1 -1
  137. package/dist/components/LinkInput/link-input.js +6 -5
  138. package/dist/components/LinkInput/link-input.js.map +1 -1
  139. package/dist/components/Menu/menu-item.d.ts +14 -2
  140. package/dist/components/Menu/menu-item.d.ts.map +1 -1
  141. package/dist/components/Menu/menu-item.js +25 -3
  142. package/dist/components/Menu/menu-item.js.map +1 -1
  143. package/dist/components/NumberInput/number-input.d.ts +3 -3
  144. package/dist/components/NumberInput/number-input.d.ts.map +1 -1
  145. package/dist/components/NumberInput/number-input.js +6 -5
  146. package/dist/components/NumberInput/number-input.js.map +1 -1
  147. package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
  148. package/dist/components/OverflowIndicator/overflow-indicator.js +2 -6
  149. package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
  150. package/dist/components/Pagination/pagination.js +1 -1
  151. package/dist/components/Pagination/pagination.js.map +1 -1
  152. package/dist/components/PeoplePicker/index.js +7 -1
  153. package/dist/components/PeoplePicker/index.js.map +1 -1
  154. package/dist/components/PeoplePicker/people-picker.d.ts +9 -2
  155. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  156. package/dist/components/PeoplePicker/people-picker.js +23 -10
  157. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  158. package/dist/components/PeoplePicker/person-display.d.ts +6 -3
  159. package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
  160. package/dist/components/PeoplePicker/person-display.js +19 -14
  161. package/dist/components/PeoplePicker/person-display.js.map +1 -1
  162. package/dist/components/Popover/popover.d.ts.map +1 -1
  163. package/dist/components/Popover/popover.js +3 -1
  164. package/dist/components/Popover/popover.js.map +1 -1
  165. package/dist/components/ProfileCard/profile-card.d.ts +2 -2
  166. package/dist/components/ProfileCard/profile-card.js +3 -3
  167. package/dist/components/ProfileCard/profile-card.js.map +1 -1
  168. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  169. package/dist/components/RadioGroup/radio-group.js +15 -9
  170. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  171. package/dist/components/ScrollArea/scroll-area.d.ts +11 -1
  172. package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
  173. package/dist/components/ScrollArea/scroll-area.js +6 -3
  174. package/dist/components/ScrollArea/scroll-area.js.map +1 -1
  175. package/dist/components/Select/select.d.ts +46 -5
  176. package/dist/components/Select/select.d.ts.map +1 -1
  177. package/dist/components/Select/select.js +109 -28
  178. package/dist/components/Select/select.js.map +1 -1
  179. package/dist/components/SelectMenu/select-menu.d.ts +3 -1
  180. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  181. package/dist/components/SelectMenu/select-menu.js +8 -1
  182. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  183. package/dist/components/SelectionControl/boolean-value.d.ts +11 -0
  184. package/dist/components/SelectionControl/boolean-value.d.ts.map +1 -0
  185. package/dist/components/SelectionControl/boolean-value.js +23 -0
  186. package/dist/components/SelectionControl/boolean-value.js.map +1 -0
  187. package/dist/components/SelectionControl/index.d.ts +1 -0
  188. package/dist/components/SelectionControl/index.d.ts.map +1 -1
  189. package/dist/components/SelectionControl/index.js +2 -0
  190. package/dist/components/SelectionControl/index.js.map +1 -1
  191. package/dist/components/Sheet/index.js +2 -1
  192. package/dist/components/Sheet/sheet.d.ts +7 -1
  193. package/dist/components/Sheet/sheet.d.ts.map +1 -1
  194. package/dist/components/Sheet/sheet.js +5 -2
  195. package/dist/components/Sheet/sheet.js.map +1 -1
  196. package/dist/components/Sidebar/sidebar.d.ts +9 -4
  197. package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
  198. package/dist/components/Sidebar/sidebar.js +8 -10
  199. package/dist/components/Sidebar/sidebar.js.map +1 -1
  200. package/dist/components/Slider/slider.d.ts.map +1 -1
  201. package/dist/components/Slider/slider.js.map +1 -1
  202. package/dist/components/Switch/switch.d.ts +6 -6
  203. package/dist/components/Switch/switch.d.ts.map +1 -1
  204. package/dist/components/Switch/switch.js +3 -2
  205. package/dist/components/Switch/switch.js.map +1 -1
  206. package/dist/components/Tabs/tabs.d.ts.map +1 -1
  207. package/dist/components/Tabs/tabs.js +15 -1
  208. package/dist/components/Tabs/tabs.js.map +1 -1
  209. package/dist/components/Textarea/textarea.d.ts +2 -2
  210. package/dist/components/Textarea/textarea.d.ts.map +1 -1
  211. package/dist/components/Textarea/textarea.js +50 -42
  212. package/dist/components/Textarea/textarea.js.map +1 -1
  213. package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
  214. package/dist/components/TimePicker/time-columns.js +42 -38
  215. package/dist/components/TimePicker/time-columns.js.map +1 -1
  216. package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
  217. package/dist/components/TimePicker/time-picker.js +8 -6
  218. package/dist/components/TimePicker/time-picker.js.map +1 -1
  219. package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
  220. package/dist/components/Tooltip/tooltip.js +7 -5
  221. package/dist/components/Tooltip/tooltip.js.map +1 -1
  222. package/dist/components/TreeView/tree-view.d.ts +56 -1
  223. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  224. package/dist/components/TreeView/tree-view.js +211 -12
  225. package/dist/components/TreeView/tree-view.js.map +1 -1
  226. package/dist/index.d.ts +115 -58
  227. package/dist/index.d.ts.map +1 -1
  228. package/dist/index.js +93 -108
  229. package/dist/index.js.map +1 -1
  230. package/dist/patterns/element-anatomy/item-anatomy.d.ts +7 -6
  231. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
  232. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  233. package/dist/tokens/categorical-color.js +15 -0
  234. package/dist/tokens/categorical-color.js.map +1 -1
  235. package/dist/tokens/motion/motion.d.ts +7 -6
  236. package/dist/tokens/motion/motion.d.ts.map +1 -1
  237. package/dist/tokens/motion/motion.js +6 -6
  238. package/dist/tokens/motion/motion.js.map +1 -1
  239. package/dist/tokens/motion/overlay-motion.d.ts +19 -0
  240. package/dist/tokens/motion/overlay-motion.d.ts.map +1 -0
  241. package/dist/tokens/motion/overlay-motion.js +9 -0
  242. package/dist/tokens/motion/overlay-motion.js.map +1 -0
  243. package/dist/tokens/uiSize/icon-size.js +5 -0
  244. package/dist/tokens/uiSize/icon-size.js.map +1 -0
  245. package/ds-canonical/fork/governance.lock +31 -19
  246. package/ds-canonical/fork/hooks/_log-fire.sh +46 -0
  247. package/ds-canonical/fork/hooks/block_prototype_imports.py +15 -4
  248. package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +145 -13
  249. package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +2 -1
  250. package/ds-canonical/fork/hooks/check_dynamic_tailwind_class.sh +47 -0
  251. package/ds-canonical/fork/hooks/check_escape_marker_abuse.sh +27 -0
  252. package/ds-canonical/fork/hooks/check_field_family_invariants.sh +61 -1
  253. package/ds-canonical/fork/hooks/check_layout_space_magic_numbers.sh +28 -4
  254. package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +28 -0
  255. package/ds-canonical/fork/hooks/check_story_determinism.sh +2 -0
  256. package/ds-canonical/fork/hooks/check_story_invariants.sh +119 -0
  257. package/ds-canonical/fork/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  258. package/ds-canonical/fork/manifest.json +15 -0
  259. package/ds-canonical/fork/preamble.md +20 -18
  260. package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +3 -3
  261. package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +3 -3
  262. package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +1 -1
  263. package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +3 -3
  264. package/ds-canonical/fork/skills/propose-options/SKILL.md +3 -3
  265. package/ds-canonical/fork/skills/prototype/SKILL.md +1 -1
  266. package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +2 -2
  267. package/ds-canonical/fork/skills/visual-audit/SKILL.md +2 -2
  268. package/ds-canonical/hooks/README.md +1 -1
  269. package/ds-canonical/hooks/block_prototype_imports.py +15 -4
  270. package/ds-canonical/hooks/check_audit_post_report_validator.sh +65 -7
  271. package/ds-canonical/hooks/check_codex_brief_invariants.sh +28 -1
  272. package/ds-canonical/hooks/check_consumer_app_invariants.sh +145 -13
  273. package/ds-canonical/hooks/check_ds_anchor_preflight.sh +2 -1
  274. package/ds-canonical/hooks/check_dynamic_tailwind_class.sh +47 -0
  275. package/ds-canonical/hooks/check_escape_marker_abuse.sh +27 -0
  276. package/ds-canonical/hooks/check_field_family_invariants.sh +61 -1
  277. package/ds-canonical/hooks/check_layout_space_magic_numbers.sh +28 -4
  278. package/ds-canonical/hooks/check_naming_and_abstraction.sh +1 -1
  279. package/ds-canonical/hooks/check_opacity_token_usage.sh +28 -0
  280. package/ds-canonical/hooks/check_pixel_quantified_audit.sh +3 -2
  281. package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +6 -1
  282. package/ds-canonical/hooks/check_ssot_header_declaration.sh +3 -1
  283. package/ds-canonical/hooks/check_story_determinism.sh +2 -0
  284. package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +8 -7
  285. package/ds-canonical/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  286. package/ds-canonical/hooks/lib/_story_compile_drift.sh +1 -1
  287. package/ds-canonical/hooks/lib/_token_hygiene.sh +10 -1
  288. package/ds-canonical/hooks/stop_self_audit.sh +31 -0
  289. package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +24 -0
  290. package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +44 -0
  291. package/ds-canonical/hooks/tests/test_check_codex_brief_invariants.sh +43 -2
  292. package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +112 -0
  293. package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +9 -2
  294. package/ds-canonical/hooks/tests/test_check_dynamic_tailwind_class.sh +76 -0
  295. package/ds-canonical/hooks/tests/test_check_escape_marker_abuse.sh +24 -0
  296. package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +27 -2
  297. package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +39 -0
  298. package/ds-canonical/hooks/tests/test_check_tabs_content_chrome_body_double_gap.sh +76 -0
  299. package/ds-canonical/references/audit-coverage-vs-24-checklist.md +1 -1
  300. package/ds-canonical/references/build-ui-canonicals.md +2 -1
  301. package/ds-canonical/references/failure-class-registry.json +145 -0
  302. package/ds-canonical/references/governance-audit-coverage.md +33 -0
  303. package/ds-canonical/references/item-anatomy-recipe.md +2 -2
  304. package/ds-canonical/references/scenario-definition.md +6 -9
  305. package/ds-canonical/references/ssot-consultation.md +2 -2
  306. package/ds-canonical/references/ssot-index.md +5 -4
  307. package/ds-canonical/references/story-baseline-registry.json +8 -2
  308. package/ds-canonical/references/structural-token-retention.md +6 -9
  309. package/ds-canonical/rules/meta-patterns.md +8 -8
  310. package/ds-canonical/rules/self-verify.md +4 -3
  311. package/ds-canonical/rules/story-rules.md +2 -2
  312. package/ds-canonical/rules/ui-development.md +2 -2
  313. package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +3 -3
  314. package/ds-canonical/skills/code-quality-audit/SKILL.md +3 -3
  315. package/ds-canonical/skills/codex-collab/SKILL.md +9 -7
  316. package/ds-canonical/skills/codex-collab/references/brief-template.md +1 -1
  317. package/ds-canonical/skills/codify-principle/SKILL.md +2 -2
  318. package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
  319. package/ds-canonical/skills/component-quality-gate/references/checklist.md +2 -2
  320. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +51 -58
  321. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +29 -0
  322. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +29 -10
  323. package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +21 -0
  324. package/ds-canonical/skills/delivery-handoff/SKILL.md +1 -1
  325. package/ds-canonical/skills/design-system-audit/SKILL.md +26 -25
  326. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +13 -1
  327. package/ds-canonical/skills/design-system-audit/references/rule-placement.md +1 -1
  328. package/ds-canonical/skills/governance-health/SKILL.md +1 -1
  329. package/ds-canonical/skills/knowledge-prune/SKILL.md +3 -0
  330. package/ds-canonical/skills/knowledge-prune/references/prune-dimensions-d5-d10.md +1 -0
  331. package/ds-canonical/skills/new-component/SKILL.md +5 -5
  332. package/ds-canonical/skills/new-component/references/new-component-checklist.md +1 -1
  333. package/ds-canonical/skills/product-ui-audit/SKILL.md +3 -3
  334. package/ds-canonical/skills/propose-options/SKILL.md +3 -3
  335. package/ds-canonical/skills/prototype/SKILL.md +1 -1
  336. package/ds-canonical/skills/scan-similar-bugs/SKILL.md +2 -2
  337. package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +3 -3
  338. package/ds-canonical/skills/story-writing/SKILL.md +3 -3
  339. package/ds-canonical/skills/visual-audit/SKILL.md +2 -2
  340. package/ds-story-manifest.json +29 -20
  341. package/llms-full.txt +22 -1
  342. package/llms.txt +5 -4
  343. package/package.json +7 -3
  344. package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
  345. package/src/components/Accordion/accordion.stories.tsx +16 -1
  346. package/src/components/Alert/alert.principles.stories.tsx +1 -1
  347. package/src/components/Alert/alert.spec.md +8 -10
  348. package/src/components/Alert/alert.stories.tsx +28 -28
  349. package/src/components/Alert/alert.tsx +1 -1
  350. package/src/components/AppShell/_demo-helpers.tsx +6 -3
  351. package/src/components/AppShell/app-shell.spec.md +4 -4
  352. package/src/components/AppShell/app-shell.tsx +28 -2
  353. package/src/components/AspectRatio/aspect-ratio.spec.md +1 -1
  354. package/src/components/AspectRatio/aspect-ratio.stories.tsx +7 -89
  355. package/src/components/Avatar/avatar.anatomy.stories.tsx +7 -3
  356. package/src/components/Avatar/avatar.principles.stories.tsx +19 -15
  357. package/src/components/Avatar/avatar.spec.md +2 -2
  358. package/src/components/Avatar/avatar.stories.tsx +8 -6
  359. package/src/components/Avatar/avatar.tsx +13 -5
  360. package/src/components/Badge/badge.principles.stories.tsx +1 -1
  361. package/src/components/Badge/badge.spec.md +2 -0
  362. package/src/components/Badge/badge.stories.tsx +4 -2
  363. package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +6 -4
  364. package/src/components/Breadcrumb/breadcrumb.stories.tsx +6 -5
  365. package/src/components/Breadcrumb/breadcrumb.tsx +3 -2
  366. package/src/components/BulkActionBar/bulk-action-bar.spec.md +4 -2
  367. package/src/components/Button/button.principles.stories.tsx +1 -1
  368. package/src/components/Button/button.spec.md +2 -2
  369. package/src/components/Button/button.tsx +18 -3
  370. package/src/components/Calendar/calendar.anatomy.stories.tsx +12 -10
  371. package/src/components/Calendar/calendar.principles.stories.tsx +14 -6
  372. package/src/components/Calendar/calendar.spec.md +5 -4
  373. package/src/components/Calendar/calendar.stories.tsx +7 -4
  374. package/src/components/Calendar/calendar.tsx +26 -7
  375. package/src/components/Carousel/carousel.anatomy.stories.tsx +5 -4
  376. package/src/components/Carousel/carousel.spec.md +2 -2
  377. package/src/components/Carousel/carousel.tsx +11 -3
  378. package/src/components/Chart/chart.anatomy.stories.tsx +7 -4
  379. package/src/components/Chart/chart.principles.stories.tsx +1 -1
  380. package/src/components/Chart/chart.stories.tsx +2 -8
  381. package/src/components/Chart/chart.tsx +3 -0
  382. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +28 -49
  383. package/src/components/Checkbox/checkbox.principles.stories.tsx +1 -1
  384. package/src/components/Checkbox/checkbox.spec.md +11 -26
  385. package/src/components/Checkbox/checkbox.stories.tsx +11 -8
  386. package/src/components/Checkbox/checkbox.tsx +18 -13
  387. package/src/components/Chip/chip.anatomy.stories.tsx +44 -24
  388. package/src/components/Chip/chip.principles.stories.tsx +1 -1
  389. package/src/components/Chip/chip.spec.md +5 -4
  390. package/src/components/Chip/chip.tsx +5 -1
  391. package/src/components/CircularProgress/circular-progress.principles.stories.tsx +7 -4
  392. package/src/components/CircularProgress/circular-progress.spec.md +3 -3
  393. package/src/components/CircularProgress/circular-progress.stories.tsx +2 -2
  394. package/src/components/Coachmark/coachmark.anatomy.stories.tsx +2 -2
  395. package/src/components/Coachmark/coachmark.principles.stories.tsx +2 -1
  396. package/src/components/Coachmark/coachmark.spec.md +5 -5
  397. package/src/components/Coachmark/coachmark.stories.tsx +3 -1
  398. package/src/components/Coachmark/coachmark.tsx +10 -3
  399. package/src/components/Combobox/combobox.anatomy.stories.tsx +2 -2
  400. package/src/components/Combobox/combobox.tsx +53 -19
  401. package/src/components/Command/command.anatomy.stories.tsx +2 -2
  402. package/src/components/Command/command.principles.stories.tsx +1 -1
  403. package/src/components/Command/command.stories.tsx +42 -10
  404. package/src/components/DataTable/cell-registry.tsx +86 -63
  405. package/src/components/DataTable/column-types.ts +10 -1
  406. package/src/components/DataTable/data-table-column-visibility-panel.tsx +1 -1
  407. package/src/components/DataTable/data-table-filter-panel.tsx +4 -1
  408. package/src/components/DataTable/data-table-interaction-layer.tsx +15 -19
  409. package/src/components/DataTable/data-table.anatomy.stories.tsx +15 -13
  410. package/src/components/DataTable/data-table.principles.stories.tsx +9 -9
  411. package/src/components/DataTable/data-table.spec.md +32 -12
  412. package/src/components/DataTable/data-table.stories.tsx +16 -17
  413. package/src/components/DataTable/data-table.tsx +103 -60
  414. package/src/components/DataTable/index.ts +3 -0
  415. package/src/components/DateGrid/date-grid.anatomy.stories.tsx +4 -4
  416. package/src/components/DateGrid/date-grid.principles.stories.tsx +1 -1
  417. package/src/components/DateGrid/date-grid.spec.md +1 -1
  418. package/src/components/DateGrid/date-grid.tsx +3 -1
  419. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +8 -8
  420. package/src/components/DatePicker/date-picker.principles.stories.tsx +3 -3
  421. package/src/components/DatePicker/date-picker.spec.md +3 -3
  422. package/src/components/DatePicker/date-picker.stories.tsx +4 -5
  423. package/src/components/DatePicker/date-picker.tsx +99 -45
  424. package/src/components/DescriptionList/description-list.anatomy.stories.tsx +12 -10
  425. package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
  426. package/src/components/DescriptionList/description-list.spec.md +3 -3
  427. package/src/components/DescriptionList/description-list.stories.tsx +7 -6
  428. package/src/components/Dialog/dialog.anatomy.stories.tsx +1 -0
  429. package/src/components/Dialog/dialog.spec.md +9 -0
  430. package/src/components/Dialog/dialog.stories.tsx +66 -5
  431. package/src/components/Dialog/dialog.tsx +60 -25
  432. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +1 -1
  433. package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +8 -6
  434. package/src/components/DropdownMenu/dropdown-menu.spec.md +5 -5
  435. package/src/components/DropdownMenu/dropdown-menu.tsx +18 -9
  436. package/src/components/Empty/empty.anatomy.stories.tsx +1 -1
  437. package/src/components/Empty/empty.spec.md +2 -2
  438. package/src/components/Field/field-context.ts +69 -5
  439. package/src/components/Field/field-controls.spec.md +62 -8
  440. package/src/components/Field/field-edit-keys.ts +66 -0
  441. package/src/components/Field/field-types.ts +58 -9
  442. package/src/components/Field/field-wrapper.tsx +50 -42
  443. package/src/components/Field/field.anatomy.stories.tsx +9 -6
  444. package/src/components/Field/field.spec.md +1 -1
  445. package/src/components/Field/field.stories.tsx +1 -1
  446. package/src/components/Field/field.tsx +2 -1
  447. package/src/components/Field/form-validation.spec.md +3 -3
  448. package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +6 -6
  449. package/src/components/FieldControlGroup/field-control-group.spec.md +9 -4
  450. package/src/components/FieldControlGroup/field-control-group.tsx +1 -1
  451. package/src/components/FileItem/file-item.anatomy.stories.tsx +1 -1
  452. package/src/components/FileItem/file-item.spec.md +5 -8
  453. package/src/components/FileItem/file-item.stories.tsx +36 -25
  454. package/src/components/FileItem/file-item.tsx +8 -6
  455. package/src/components/FileUpload/file-upload.anatomy.stories.tsx +6 -6
  456. package/src/components/FileUpload/file-upload.principles.stories.tsx +5 -5
  457. package/src/components/FileUpload/file-upload.spec.md +1 -1
  458. package/src/components/FileUpload/file-upload.tsx +1 -1
  459. package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +4 -3
  460. package/src/components/FileViewer/file-viewer.principles.stories.tsx +3 -3
  461. package/src/components/FileViewer/file-viewer.spec.md +30 -12
  462. package/src/components/FileViewer/file-viewer.stories.tsx +1 -2
  463. package/src/components/FileViewer/file-viewer.tsx +12 -4
  464. package/src/components/FileViewer/image-renderer.tsx +35 -7
  465. package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -2
  466. package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -3
  467. package/src/components/HoverCard/hover-card.spec.md +5 -5
  468. package/src/components/HoverCard/hover-card.stories.tsx +16 -16
  469. package/src/components/HoverCard/hover-card.tsx +5 -3
  470. package/src/components/InlineEdit/index.ts +5 -0
  471. package/src/components/InlineEdit/inline-edit.spec.md +149 -0
  472. package/src/components/InlineEdit/inline-edit.stories.tsx +246 -0
  473. package/src/components/InlineEdit/inline-edit.tsx +287 -0
  474. package/src/components/Input/input.anatomy.stories.tsx +8 -7
  475. package/src/components/Input/input.principles.stories.tsx +2 -12
  476. package/src/components/Input/input.spec.md +13 -18
  477. package/src/components/Input/input.tsx +69 -22
  478. package/src/components/LinkInput/link-input.anatomy.stories.tsx +1 -1
  479. package/src/components/LinkInput/link-input.principles.stories.tsx +2 -2
  480. package/src/components/LinkInput/link-input.tsx +11 -10
  481. package/src/components/Menu/menu-item.anatomy.stories.tsx +3 -3
  482. package/src/components/Menu/menu-item.principles.stories.tsx +1 -1
  483. package/src/components/Menu/menu-item.spec.md +22 -15
  484. package/src/components/Menu/menu-item.stories.tsx +39 -11
  485. package/src/components/Menu/menu-item.tsx +38 -4
  486. package/src/components/Notice/notice.principles.stories.tsx +1 -1
  487. package/src/components/Notice/notice.spec.md +16 -3
  488. package/src/components/NumberInput/number-input.anatomy.stories.tsx +3 -3
  489. package/src/components/NumberInput/number-input.principles.stories.tsx +1 -1
  490. package/src/components/NumberInput/number-input.spec.md +4 -4
  491. package/src/components/NumberInput/number-input.tsx +19 -12
  492. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +10 -8
  493. package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +3 -3
  494. package/src/components/OverflowIndicator/overflow-indicator.spec.md +4 -2
  495. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +71 -63
  496. package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -8
  497. package/src/components/Pagination/pagination.spec.md +1 -1
  498. package/src/components/Pagination/pagination.stories.tsx +2 -6
  499. package/src/components/Pagination/pagination.tsx +1 -1
  500. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +4 -4
  501. package/src/components/PeoplePicker/people-picker.principles.stories.tsx +2 -2
  502. package/src/components/PeoplePicker/people-picker.spec.md +6 -6
  503. package/src/components/PeoplePicker/people-picker.tsx +56 -16
  504. package/src/components/PeoplePicker/person-display.tsx +32 -16
  505. package/src/components/Popover/popover.anatomy.stories.tsx +2 -2
  506. package/src/components/Popover/popover.tsx +3 -1
  507. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +12 -23
  508. package/src/components/ProfileCard/profile-card.spec.md +3 -3
  509. package/src/components/ProfileCard/profile-card.tsx +6 -6
  510. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +3 -1
  511. package/src/components/ProgressBar/progress-bar.principles.stories.tsx +1 -1
  512. package/src/components/ProgressBar/progress-bar.stories.tsx +50 -42
  513. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +10 -28
  514. package/src/components/RadioGroup/radio-group.stories.tsx +29 -32
  515. package/src/components/RadioGroup/radio-group.tsx +41 -15
  516. package/src/components/Rating/rating.spec.md +11 -3
  517. package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
  518. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
  519. package/src/components/ScrollArea/scroll-area.spec.md +7 -3
  520. package/src/components/ScrollArea/scroll-area.stories.tsx +1 -1
  521. package/src/components/ScrollArea/scroll-area.tsx +17 -4
  522. package/src/components/Select/select.anatomy.stories.tsx +3 -3
  523. package/src/components/Select/select.spec.md +27 -17
  524. package/src/components/Select/select.stories.tsx +33 -0
  525. package/src/components/Select/select.tsx +190 -36
  526. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +4 -4
  527. package/src/components/SelectMenu/select-menu.spec.md +15 -7
  528. package/src/components/SelectMenu/select-menu.tsx +16 -3
  529. package/src/components/SelectionControl/boolean-value.tsx +39 -0
  530. package/src/components/SelectionControl/index.ts +1 -0
  531. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +2 -2
  532. package/src/components/SelectionControl/selection-item.principles.stories.tsx +2 -2
  533. package/src/components/SelectionControl/selection-item.spec.md +3 -3
  534. package/src/components/SelectionControl/selection-item.stories.tsx +3 -3
  535. package/src/components/Separator/separator.spec.md +2 -2
  536. package/src/components/Separator/separator.stories.tsx +6 -27
  537. package/src/components/Sheet/sheet.anatomy.stories.tsx +1 -1
  538. package/src/components/Sheet/sheet.principles.stories.tsx +1 -1
  539. package/src/components/Sheet/sheet.spec.md +2 -2
  540. package/src/components/Sheet/sheet.tsx +9 -5
  541. package/src/components/Sidebar/sidebar.anatomy.stories.tsx +16 -12
  542. package/src/components/Sidebar/sidebar.principles.stories.tsx +10 -8
  543. package/src/components/Sidebar/sidebar.spec.md +13 -15
  544. package/src/components/Sidebar/sidebar.stories.tsx +8 -7
  545. package/src/components/Sidebar/sidebar.tsx +37 -25
  546. package/src/components/Skeleton/skeleton.stories.tsx +4 -11
  547. package/src/components/Slider/slider.anatomy.stories.tsx +3 -3
  548. package/src/components/Slider/slider.principles.stories.tsx +2 -2
  549. package/src/components/Slider/slider.spec.md +5 -5
  550. package/src/components/Slider/slider.tsx +3 -1
  551. package/src/components/Steps/steps.anatomy.stories.tsx +4 -4
  552. package/src/components/Steps/steps.principles.stories.tsx +1 -1
  553. package/src/components/Steps/steps.spec.md +1 -1
  554. package/src/components/Switch/switch.anatomy.stories.tsx +7 -7
  555. package/src/components/Switch/switch.principles.stories.tsx +4 -4
  556. package/src/components/Switch/switch.spec.md +8 -8
  557. package/src/components/Switch/switch.stories.tsx +9 -24
  558. package/src/components/Switch/switch.tsx +17 -13
  559. package/src/components/Tabs/tabs.anatomy.stories.tsx +10 -7
  560. package/src/components/Tabs/tabs.spec.md +1 -1
  561. package/src/components/Tabs/tabs.tsx +21 -1
  562. package/src/components/Textarea/textarea.anatomy.stories.tsx +1 -1
  563. package/src/components/Textarea/textarea.principles.stories.tsx +1 -1
  564. package/src/components/Textarea/textarea.spec.md +4 -4
  565. package/src/components/Textarea/textarea.tsx +72 -46
  566. package/src/components/TimePicker/time-columns.tsx +6 -2
  567. package/src/components/TimePicker/time-picker.principles.stories.tsx +1 -1
  568. package/src/components/TimePicker/time-picker.spec.md +3 -3
  569. package/src/components/TimePicker/time-picker.tsx +16 -10
  570. package/src/components/Toast/toast.stories.tsx +7 -4
  571. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +4 -4
  572. package/src/components/Tooltip/tooltip.principles.stories.tsx +3 -3
  573. package/src/components/Tooltip/tooltip.spec.md +1 -1
  574. package/src/components/Tooltip/tooltip.stories.tsx +4 -39
  575. package/src/components/Tooltip/tooltip.tsx +8 -6
  576. package/src/components/TreeView/tree-view.anatomy.stories.tsx +6 -3
  577. package/src/components/TreeView/tree-view.spec.md +42 -11
  578. package/src/components/TreeView/tree-view.stories.tsx +1 -0
  579. package/src/components/TreeView/tree-view.tsx +322 -17
  580. package/src/index.ts +584 -60
  581. package/src/patterns/action-bar/action-bar.spec.md +9 -0
  582. package/src/patterns/action-bar/action-bar.stories.tsx +6 -3
  583. package/src/patterns/element-anatomy/inline-action.spec.md +2 -0
  584. package/src/patterns/element-anatomy/item-anatomy.spec.md +14 -5
  585. package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -4
  586. package/src/patterns/element-anatomy/item-anatomy.tsx +7 -6
  587. package/src/patterns/header-canonical/header-canonical.spec.md +5 -4
  588. package/src/patterns/overlay-surface/overlay-surface.spec.md +22 -1
  589. package/src/styles/tokens.css +3 -0
  590. package/src/tokens/README.md +1 -1
  591. package/src/tokens/color/color.spec.md +3 -3
  592. package/src/tokens/color/color.stories.tsx +3 -3
  593. package/src/tokens/density/density.stories.tsx +16 -3
  594. package/src/tokens/layoutSpace/layoutSpace.spec.md +3 -1
  595. package/src/tokens/motion/motion.css +33 -21
  596. package/src/tokens/motion/motion.spec.md +32 -15
  597. package/src/tokens/motion/motion.stories.tsx +58 -5
  598. package/src/tokens/motion/motion.ts +7 -6
  599. package/src/tokens/motion/overlay-motion.ts +26 -0
  600. package/src/tokens/orphan-tokens.spec.md +4 -4
  601. package/src/tokens/token-system.spec.md +1 -0
  602. package/src/tokens/uiSize/uiSize.spec.md +1 -1
  603. package/src/tokens/uiSize/uiSize.stories.tsx +4 -2
  604. package/src/tokens/utility-registry.json +160 -23
@@ -141,27 +141,16 @@ Checkbox/Radio 控件本體不畫 label——label 由 `SelectionItem` 承載:
141
141
 
142
142
  **icon / avatar prefix(2026-06-12 M30 轉發)**:一級 `icon`(LucideIcon)/ `avatar`(AvatarData)props 直接轉發 `SelectionItem` 既有三槽 canonical 的 prefix 槽(互斥;尺寸與 inline/block 對齊規則 SSOT = `selection-item.spec.md`「3-slot 結構」+ selection-item.tsx jsDoc)。RadioGroupItem 同。
143
143
 
144
- 對齊機制:
145
- 1. 外層 `<div>` 設 `text-body` / `text-body-lg`(建立 line-height context)
146
- 2. 控件包在 `h-[1lh]` 的容器內(容器高度 = 一行文字高度)
147
- 3. `flex items-center`(控件在文字行高內垂直置中)
148
- 4. 外層 `flex items-start`(多行時控件對齊第一行)
149
-
150
- `1lh` 在 `<div>` 上正常繼承,改字體自動重算。
144
+ 對齊機制(`text-body[-lg]` 建立 `1lh` context / 控件包 `h-[1lh]` 容器垂直置中 / 外層 `items-start` 多行對齊第一行)**SSOT → `../SelectionControl/selection-item.spec.md`「結構 / 字體」**,本 spec 不重述(2026-07-14 收斂原重述段,措辭已現 drift)。
151
145
 
152
146
  ---
153
147
 
154
148
  ## SelectionItem 佈局
155
149
 
156
- 垂直排列和水平排列共用 `SelectionItem`。
157
-
158
- | | 垂直 | 水平 |
159
- |---|---|---|
160
- | Item 間距 | 0(padding 處理) | 16px(gap-4,見 Orientation 段) |
161
- | Item padding | `py = (field-height - 1lh) / 2` | 同左 |
162
- | Label ↔ Description | 2px(`--item-gap-label-desc-reading` / `-reading-lg`,size-aware) | 同左 |
163
- | 單行高度 | = field-height(對齊 Input) | 同左 |
164
- | 多行高度 | padding 維持不變,總高度 = `1lh × line-count + py × 2` | — |
150
+ 垂直排列和水平排列共用 `SelectionItem`,各值 SSOT 不重述:
151
+ - **Item padding / 單行高度 = field-height / 多行撐高公式** → `selection-item.spec.md`「Padding 公式」(`py = (field-height - 1lh) / 2`)
152
+ - **Label Description 2px gap** → `item-anatomy.spec.md`「Label ↔ Desc 間距」(`--item-gap-label-desc-reading[-lg]`,size-aware)
153
+ - **Item 間距**(垂直 0 / 水平 `gap-4`)→ 下方「群組模式」zero-gap 鐵律 + Orientation 段
165
154
 
166
155
  ---
167
156
 
@@ -226,9 +215,9 @@ Checkbox / Radio 在 form 內承載的常常是:
226
215
 
227
216
  典型場景:SelectMenu 的「全選」checkbox——當部分選項被勾選時顯示 indeterminate。
228
217
 
229
- Indeterminate 是由父層邏輯控制的狀態,Checkbox 本身不會自動進入 indeterminate——必須明確傳入 `checked="indeterminate"`。**常見誤解**:「部分子項已選」不可用 disabled + checked 混搭表達——半選是可互動狀態,disabled 是鎖互動,語意不同。
218
+ Indeterminate 是由父層邏輯控制的狀態,Checkbox 本身不會自動進入 indeterminate——必須明確傳入 `checked="indeterminate"`(controlled 與 uncontrolled `defaultChecked="indeterminate"` 皆正確渲染 Minus——圖示切換由 Radix `data-state` CSS 驅動,2026-07-14 修復原「只讀 `props.checked`」的 uncontrolled known-gap)。**常見誤解**:「部分子項已選」不可用 disabled + checked 混搭表達——半選是可互動狀態,disabled 是鎖互動,語意不同。
230
219
 
231
- **狀態切換視覺**(code 真值):unchecked ↔ checked / indeterminate 之間色彩走 `transition-colors` 150ms;Check ↔ Minus 圖示為條件渲染即時 swap,無過渡動畫。
220
+ **狀態切換視覺**(code 真值):unchecked ↔ checked / indeterminate 之間色彩走 `transition-colors` 150ms;Check ↔ Minus 圖示由 `data-state` CSS 即時 swap,無過渡動畫。
232
221
 
233
222
  ### Radio
234
223
 
@@ -255,8 +244,8 @@ Indeterminate 是由父層邏輯控制的狀態,Checkbox 本身不會自動進
255
244
 
256
245
  `mode?: 'edit' | 'display' | 'readonly' | 'disabled'`(默認 inherit Field context 或 `'edit'`),對齊 `field-types.ts` FieldMode(完整 4-mode canonical SSOT → `Field/field-controls.spec.md`;本段鏡像 switch.spec.md 同名段):
257
246
  - `edit`(預設)— 可勾選的 Checkbox。
258
- - `display` — **純展示**:渲染 (checked)/ (其他),非互動、無 input chrome,供 DataTable boolean cell 非編輯態共用。
259
- - `readonly` — **Field 內(無 inline label)**= `fieldWrapperStyles` readonly 灰框 + ✓/—(與 Input readonly 同一視覺語言,2026-06-12 user 拍板;世界級:Salesforce output ✓ glyph / SAP 靜態文字);**standalone / 有 inline label**(SelectionItem row)= 正常色鎖互動(同下方 Read-only)。
247
+ - `display` — **純展示**:渲染 **Check icon(true=勾)/ X icon(false=叉)**,中性 `text-foreground` 色,非互動、無 input chrome,供 DataTable boolean cell 非編輯態共用。boolean 值符號 SSOT = `../SelectionControl/boolean-value.tsx`(勾/叉 icon + 中性色;M22 世界級:MUI X DataGrid Check/Close icon 中性色 / React-admin TrueIcon-FalseIcon;false 中性非紅 = 「否」值非「錯誤」)。
248
+ - `readonly` — **Field 內(無 inline label)**= `fieldWrapperStyles` readonly 灰框 + 勾/叉 icon(與 Input readonly 同一視覺語言,2026-06-12 user 拍板;世界級:Salesforce output ✓ glyph / SAP 靜態文字);**standalone / 有 inline label**(SelectionItem row)= 正常色鎖互動(同下方 Read-only)。
260
249
  - `disabled` — 落到真 disabled chrome(`effectiveDisabled`,2026-06-12 修:mode='disabled' 直傳〔如 DataTable disabled cell〕與 `disabled` prop 等效,降色 + 不可 focus)。
261
250
 
262
251
  CheckboxGroup 是純 layout primitive — **不**持有 group-level selection state(無 `value` / `defaultValue` / `onValueChange`)。每個 `<Checkbox>` child 各自管自己的 `checked` / `defaultChecked` / `onCheckedChange`;CheckboxGroup 只透過 `CheckboxGroupContext` 告知 child「你在 group 裡」(保留各自 label)。
@@ -312,12 +301,6 @@ Horizontal 需 `gap-4` 因 row 的 py 不擴散到左右。
312
301
  ### 用法範例
313
302
 
314
303
  ```tsx
315
- <CheckboxGroup>
316
- <Checkbox label="待處理" defaultChecked />
317
- <Checkbox label="進行中" defaultChecked />
318
- <Checkbox label="已完成" />
319
- </CheckboxGroup>
320
-
321
304
  <Field orientation="horizontal">
322
305
  <FieldLabel>通知方式</FieldLabel>
323
306
  <CheckboxGroup orientation="horizontal">
@@ -328,6 +311,8 @@ Horizontal 需 `gap-4` 因 row 的 py 不擴散到左右。
328
311
  </Field>
329
312
  ```
330
313
 
314
+ (垂直 group / defaultChecked 等更多場景 → `checkbox.stories.tsx`)
315
+
331
316
  ---
332
317
 
333
318
  ## 禁止事項
@@ -1,6 +1,8 @@
1
+ // @story-trait-rationale: hasSizes/hasInteractiveStates 由 anatomy.stories.tsx SizeMatrix + StateBehavior
2
+ // owns 完整 trait grid;展示層 States 保留為 compact all-states overview(對齊 Switch 同 Family 檔頭豁免,
3
+ // 2026-07-14 audit Dim 46 補),跟 anatomy focused subsection 不同教學,不另開抽象 Default/AllSizes。
1
4
  import type { Meta, StoryObj } from '@storybook/react'
2
5
  import { Checkbox } from './checkbox'
3
- import { SelectionItem } from '@/design-system/components/SelectionControl/selection-item'
4
6
 
5
7
  const meta: Meta<typeof Checkbox> = {
6
8
  title: 'Design System/Components/Checkbox/展示',
@@ -24,7 +26,7 @@ export const Modes: Story = {
24
26
  <div>
25
27
  <h3 className="text-body font-bold text-foreground mb-2">display</h3>
26
28
  <Checkbox mode="display" checked />
27
- <p className="text-caption text-fg-muted mt-1">純視覺 glyph(✓ / —);語意由 context(如 DataTable 表頭 + 行標籤)提供,display 不暴露獨立 aria-label。需螢幕報讀器可讀的勾選請用 edit / readonly 模式。</p>
29
+ <p className="text-caption text-fg-muted mt-1">純視覺 glyph(勾/叉 icon,Check/X);語意由 context(如 DataTable 表頭 + 行標籤)提供,display 不暴露獨立 aria-label。需螢幕報讀器可讀的勾選請用 edit / readonly 模式。</p>
28
30
  </div>
29
31
  <div>
30
32
  <h3 className="text-body font-bold text-foreground mb-2">readonly</h3>
@@ -86,9 +88,10 @@ export const VerticalGroup: Story = {
86
88
  <div key={size}>
87
89
  <p className="text-caption text-fg-muted mb-1">size="{size}"</p>
88
90
  <div className="grid">
89
- <SelectionItem size={size} control={<Checkbox id={`${size}-a`} size={size} />} label="Electronics" htmlFor={`${size}-a`} />
90
- <SelectionItem size={size} control={<Checkbox id={`${size}-b`} size={size} />} label="Furniture" description="桌椅、收納、辦公家具" htmlFor={`${size}-b`} />
91
- <SelectionItem size={size} control={<Checkbox id={`${size}-c`} size={size} />} label="Food & Beverage" htmlFor={`${size}-c`} />
91
+ {/* 公開 API:`<Checkbox label>` 自動包 SelectionItem + wire id/htmlFor(selection-item.spec.md 禁裸用) */}
92
+ <Checkbox size={size} label="Electronics" />
93
+ <Checkbox size={size} label="Furniture" description="桌椅、收納、辦公家具" />
94
+ <Checkbox size={size} label="Food & Beverage" />
92
95
  </div>
93
96
  </div>
94
97
  ))}
@@ -101,9 +104,9 @@ export const Horizontal: Story = {
101
104
  name: '水平排列',
102
105
  render: () => (
103
106
  <div className="flex gap-4 max-w-md">
104
- <SelectionItem control={<Checkbox id="h-a" />} label="Electronics" htmlFor="h-a" />
105
- <SelectionItem control={<Checkbox id="h-b" />} label="Furniture" htmlFor="h-b" />
106
- <SelectionItem control={<Checkbox id="h-c" />} label="Food" htmlFor="h-c" />
107
+ <Checkbox label="Electronics" />
108
+ <Checkbox label="Furniture" />
109
+ <Checkbox label="Food" />
107
110
  </div>
108
111
  ),
109
112
  }
@@ -9,6 +9,7 @@ import type { FieldMode, FieldVariant } from "@/design-system/components/Field/f
9
9
  import { useFieldContext, useResolvedFieldDisabled, useResolvedFieldMode, useResolvedFieldSize } from "@/design-system/components/Field/field-context"
10
10
  import { fieldWrapperStyles } from "@/design-system/components/Field/field-wrapper"
11
11
  import { SelectionItem } from "@/design-system/components/SelectionControl/selection-item"
12
+ import { BooleanValueIcon } from "@/design-system/components/SelectionControl/boolean-value"
12
13
  import type { LucideIcon } from "lucide-react"
13
14
  import type { AvatarData } from "@/design-system/components/Avatar/avatar"
14
15
  import { CheckboxGroupContext } from "./checkbox-group"
@@ -110,7 +111,7 @@ export interface CheckboxProps
110
111
  /**
111
112
  * Field mode(2026-05-05 Phase B3 align):
112
113
  * edit — 一般可互動 checkbox(預設)
113
- * display — **純展示**:渲染 / (無互動 primitive、無 input chrome);
114
+ * display — **純展示**:渲染 Check / X icon(true=勾 / false=叉,無互動 primitive、無 input chrome);
114
115
  * 對齊 Carbon read-only / DataTable boolean cell 場景。取代既有 BooleanDisplay。
115
116
  * readonly — 同 readOnly prop:checkbox 視覺保留 + 鎖互動 + a11y readonly signal
116
117
  * disabled — 同 disabled prop:降色 + 鎖互動
@@ -208,16 +209,19 @@ const Checkbox = React.forwardRef<
208
209
  } = props
209
210
 
210
211
  // ── mode='display'(下移至所有 hooks 之後,per #35 Rules of Hooks)──────────
211
- // 純展示模式:無互動 primitive、渲染 / (checked=true → ✓ / 其他 )。取代 BooleanDisplay
212
+ // 純展示模式:無互動 primitive、渲染 Check / X icon(true=勾 / false=叉,中性 foreground )。
213
+ // boolean 值展示符號 SSOT = SelectionControl/boolean-value.tsx(勾/叉 icon + 中性色 + M22 世界級對照)。取代 BooleanDisplay。
212
214
  if (resolvedMode === 'display') {
213
215
  const isChecked = checkedProp === true
214
- return isChecked
215
- ? <span {...restDomProps} ref={ref as React.Ref<HTMLSpanElement>} className="text-foreground">✓</span>
216
- : <span {...restDomProps} ref={ref as React.Ref<HTMLSpanElement>} className="text-fg-muted">—</span>
216
+ return (
217
+ <span {...restDomProps} ref={ref as React.Ref<HTMLSpanElement>} className="inline-flex">
218
+ <BooleanValueIcon checked={isChecked} size={resolvedBoxSize} />
219
+ </span>
220
+ )
217
221
  }
218
222
 
219
- // ── mode='readonly' in Field(2026-06-12 user 拍板「灰框 + ✓/—」)─────────────
220
- // Field 內 readonly boolean = readonly 灰框 chrome + display 同款值語言 ✓/—。
223
+ // ── mode='readonly' in Field(2026-06-12 拍板「灰框 + 勾/叉」;2026-07-09 ✓/— glyph → Check/X icon)
224
+ // Field 內 readonly boolean = readonly 灰框 chrome + display 同款值語言(勾/叉 icon)。
221
225
  // 灰框消費 fieldWrapperStyles 同一 cva = 與 Input readonly 字面同源(SSOT,改一處全動)。
222
226
  // 理由:同一張 readonly 表單裡文字控件有 bg-readonly 灰框鎖定訊號,boolean 保留全彩
223
227
  // 控件會誤導「仍可操作」(世界級 0/4 用原樣鎖互動:Salesforce=✓ 靜態 glyph /
@@ -244,7 +248,7 @@ const Checkbox = React.forwardRef<
244
248
  className,
245
249
  )}
246
250
  >
247
- {isChecked ? <span className="text-foreground">✓</span> : <span className="text-fg-muted">—</span>}
251
+ <BooleanValueIcon checked={isChecked} size={boxSize} />
248
252
  </div>
249
253
  )
250
254
  }
@@ -273,11 +277,12 @@ const Checkbox = React.forwardRef<
273
277
  props.onClick?.(event)
274
278
  }}
275
279
  >
276
- <CheckboxPrimitive.Indicator className="grid place-content-center text-current">
277
- {props.checked === 'indeterminate'
278
- ? <Minus style={{ width: iconPx, height: iconPx }} strokeWidth={iconStrokeWidth} />
279
- : <Check style={{ width: iconPx, height: iconPx }} strokeWidth={iconStrokeWidth} />
280
- }
280
+ {/* 圖示切換走 Radix data-state(CSS),非 props.checked(JS)—— uncontrolled
281
+ defaultChecked="indeterminate" 時 props.checked=undefined,JS 判斷會錯渲 Check;
282
+ data-state 涵蓋 controlled/uncontrolled 全部轉換(Radix SSOT)。 */}
283
+ <CheckboxPrimitive.Indicator className="group/indicator grid place-content-center text-current">
284
+ <Minus className="hidden group-data-[state=indeterminate]/indicator:block" style={{ width: iconPx, height: iconPx }} strokeWidth={iconStrokeWidth} />
285
+ <Check className="hidden group-data-[state=checked]/indicator:block" style={{ width: iconPx, height: iconPx }} strokeWidth={iconStrokeWidth} />
281
286
  </CheckboxPrimitive.Indicator>
282
287
  </CheckboxPrimitive.Root>
283
288
  )
@@ -1,6 +1,7 @@
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
3
  import type { Meta, StoryObj } from '@storybook/react'
4
+ import { useState } from 'react'
4
5
  import { Star, Tag as TagIcon } from 'lucide-react'
5
6
  import { Chip, ChipGroup } from './chip'
6
7
  import { H3, Desc, Td, Th, TokenCell, Swatch } from '@/design-system/stories-helpers/anatomy/anatomy-utils'
@@ -108,23 +109,31 @@ export const Inspector: InspectorStory = {
108
109
  description: 'overflow 行為:wrap(換行,預設)/ scroll(fade mask)/ menu(收入 Dropdown)',
109
110
  },
110
111
  },
111
- render: (args) => {
112
- const groupProps =
113
- args.type === 'multiple'
114
- ? ({ type: 'multiple' as const, defaultValue: args.selected ? ['featured'] : [] })
115
- : ({ type: 'single' as const, defaultValue: args.selected ? 'featured' : '' })
116
- return (
117
- <div className="max-w-md border border-border rounded-md p-3">
118
- <ChipGroup layout={args.layout} {...groupProps}>
119
- <Chip value="featured" startIcon={args.withStartIcon ? Star : undefined}>精選</Chip>
120
- <Chip value="new" startIcon={args.withStartIcon ? TagIcon : undefined}>新品</Chip>
121
- <Chip value="sale">特價</Chip>
122
- <Chip value="limited">限量</Chip>
123
- <Chip value="discontinued" disabled={args.disabled}>下架</Chip>
124
- </ChipGroup>
125
- </div>
126
- )
127
- },
112
+ // 2026-07-14 dim-26 修:原 mount-only defaultValue — Controls 切 selected 不生效,且
113
+ // layout=menu 違反 chip.spec.md:190「menu 模式需要 controlled ChipGroup(value + onValueChange)」
114
+ // (chip.tsx:298 runtime warn)。改 controlled inner(repo anatomy 慣例 useState Inner)+
115
+ // key remount Controls 切換 type / selected 即時反映。
116
+ render: (args) => <InspectorControlled key={`${args.type}-${args.selected}`} {...args} />,
117
+ }
118
+
119
+ const InspectorControlled = (args: InspectorArgs) => {
120
+ const [multiValue, setMultiValue] = useState<string[]>(args.selected ? ['featured'] : [])
121
+ const [singleValue, setSingleValue] = useState<string>(args.selected ? 'featured' : '')
122
+ const groupProps =
123
+ args.type === 'multiple'
124
+ ? ({ type: 'multiple' as const, value: multiValue, onValueChange: setMultiValue })
125
+ : ({ type: 'single' as const, value: singleValue, onValueChange: setSingleValue })
126
+ return (
127
+ <div className="max-w-md border border-border rounded-md p-3">
128
+ <ChipGroup layout={args.layout} {...groupProps}>
129
+ <Chip value="featured" startIcon={args.withStartIcon ? Star : undefined}>精選</Chip>
130
+ <Chip value="new" startIcon={args.withStartIcon ? TagIcon : undefined}>新品</Chip>
131
+ <Chip value="sale">特價</Chip>
132
+ <Chip value="limited">限量</Chip>
133
+ <Chip value="discontinued" disabled={args.disabled}>下架</Chip>
134
+ </ChipGroup>
135
+ </div>
136
+ )
128
137
  }
129
138
 
130
139
  export const ColorMatrix: Story = {
@@ -366,6 +375,19 @@ export const StateBehavior: Story = {
366
375
  ),
367
376
  }
368
377
 
378
+ // menu layout 必為 controlled(spec 禁止事項:uncontrolled menu 無法同步狀態);故獨立成元件用 useState
379
+ const MENU_LAYOUT_OPTIONS = ['電子產品', '家具', '食品', '服飾', '書籍', '運動', '玩具', '美妝', '家電']
380
+ function MenuLayoutExample() {
381
+ const [value, setValue] = useState<string[]>(['電子產品'])
382
+ return (
383
+ <ChipGroup type="multiple" layout="menu" value={value} onValueChange={(v) => setValue(v as string[])}>
384
+ {MENU_LAYOUT_OPTIONS.map((label) => (
385
+ <Chip key={label} value={label}>{label}</Chip>
386
+ ))}
387
+ </ChipGroup>
388
+ )
389
+ }
390
+
369
391
  export const LayoutMatrix: Story = {
370
392
  name: '排版(換行 vs 捲動 vs 選單)',
371
393
  render: () => (
@@ -374,7 +396,8 @@ export const LayoutMatrix: Story = {
374
396
  <H3>wrap(預設)</H3>
375
397
  <Desc>超出容器自然換行。適合空間充裕的 filter panel。</Desc>
376
398
  <div className="max-w-md border border-border rounded-md p-3">
377
- <ChipGroup type="multiple" defaultValue={['a']}>
399
+ {/* defaultValue 必對應真實 chip value(chip value=中文 label);原 'a' 無對應 → 初始 0 選取的死示範 */}
400
+ <ChipGroup type="multiple" defaultValue={['電子產品']}>
378
401
  {['電子產品', '家具', '食品', '服飾', '書籍', '運動', '玩具', '美妝', '家電'].map(label => (
379
402
  <Chip key={label} value={label}>{label}</Chip>
380
403
  ))}
@@ -386,7 +409,8 @@ export const LayoutMatrix: Story = {
386
409
  <H3>scroll</H3>
387
410
  <Desc>水平捲動 + fade mask(共用 `horizontal-overflow` pattern,跟 Tabs 一致)。適合空間受限但希望保留 chip 視覺的場景。</Desc>
388
411
  <div className="max-w-md border border-border rounded-md p-3">
389
- <ChipGroup type="multiple" layout="scroll" defaultValue={['a']}>
412
+ {/* defaultValue 必對應真實 chip value(chip value=中文 label);原 'a' 無對應 → 初始 0 選取的死示範 */}
413
+ <ChipGroup type="multiple" layout="scroll" defaultValue={['電子產品']}>
390
414
  {['電子產品', '家具', '食品', '服飾', '書籍', '運動', '玩具', '美妝', '家電'].map(label => (
391
415
  <Chip key={label} value={label}>{label}</Chip>
392
416
  ))}
@@ -398,11 +422,7 @@ export const LayoutMatrix: Story = {
398
422
  <H3>menu(show-all navigator dropdown)</H3>
399
423
  <Desc>所有 chip 留在單行水平捲動容器,全部可見可點(不隱藏);dropdown 永遠列出全部 chip 供快速勾選(對齊 Chrome tab dropdown / VS Code editor tabs)。適合 chip 很多但使用者不常切後面的場景。</Desc>
400
424
  <div className="max-w-md border border-border rounded-md p-3">
401
- <ChipGroup type="multiple" layout="menu" defaultValue={['a']}>
402
- {['電子產品', '家具', '食品', '服飾', '書籍', '運動', '玩具', '美妝', '家電'].map(label => (
403
- <Chip key={label} value={label}>{label}</Chip>
404
- ))}
405
- </ChipGroup>
425
+ <MenuLayoutExample />
406
426
  </div>
407
427
  </div>
408
428
  </div>
@@ -198,7 +198,7 @@ export const SelectedStyleRule: Story = {
198
198
  <div>
199
199
  <Rule
200
200
  title="選中 = primary text + border,底色不變"
201
- note="對齊 SegmentedControl / Tabs 的選中 canonical(primary base 同時染文字和線條;semantic.css SSOT,2026-07-06 拍板自 hover 階改 base——瞬時弱、持續強)。用 bg 強調會讓 chip 看起來變成「按鈕」,混淆多選濾鏡的語意"
201
+ note="對齊 SegmentedControl / Tabs 的選中 canonical:primary 底色同時染文字和線條(瞬時 hover 用弱色、持續選中用強色)。用 bg 強調會讓 chip 看起來變成「按鈕」,混淆多選濾鏡的語意"
202
202
  >
203
203
  <ChipGroup type="multiple" defaultValue={['react', 'ts']}>
204
204
  <Chip value="react">React</Chip>
@@ -2,7 +2,8 @@
2
2
  component: Chip
3
3
  family: 3
4
4
  variants: {}
5
- sizes: {}
5
+ sizes:
6
+ sm: { when: "單一尺寸(h-field-sm 28/32 依 density、icon 16、text-body)— 對齊 chip.tsx componentMeta" }
6
7
  traits:
7
8
  - hasInteractiveStates
8
9
  benchmark:
@@ -201,11 +202,11 @@ Chip 的 overflow 處理有三種模式:
201
202
  - ❌ 把 Chip 塞進 Field 當 form control——規模語意不對,用 SegmentedControl
202
203
  - ❌ Menu 模式搭配 uncontrolled(只給 `defaultValue`)——menu items 無法同步狀態,TS 不擋但 runtime 會看到 menu 勾選失效
203
204
 
204
- ## 為何無 Inspector
205
+ ## 設計規格 story 結構
205
206
 
206
- Chip 決策維度是「selection 行為(single / multi / menu)」× layout(連體 / 間隔)× overflow——已在 `SelectionMatrix` / `LayoutMatrix` 兩張結構矩陣覆蓋。互動 Inspector 無法呈現 selection model 的差異(需要 side-by-side 對照)
207
+ Chip 決策維度是「selection type(`single` / `multiple`)」×「layout(`wrap` / `scroll` / `menu`)」× overflow——由 `Inspector`(互動切換 type / selected / disabled / startIcon / layout)、`SelectionMatrix`、`LayoutMatrix` 三者覆蓋。
207
208
 
208
- ColorMatrix 已建:展示 default / hover / selected / disabled 四狀態的 bg / border / text / icon token 對照,採 pill-canonical 規則(`--primary-hover` 同步染 border + text,bg 維持 surface 不染色),對齊 SegmentedControl / Tabs 未選 hover
209
+ ColorMatrix:展示 default / hover / selected / disabled 四狀態的 bg / border / text / icon token 對照,採 pill-設計準則:selected `--primary` 同時染 border + text(selected × hover 深化為 `--primary-hover`),底色維持 `--surface` 不染色,對齊 SegmentedControl / Tabs。
209
210
 
210
211
  ---
211
212
 
@@ -80,7 +80,11 @@ const chipVariants = cva(
80
80
  )
81
81
 
82
82
  export interface ChipProps
83
- extends React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> {
83
+ // 2026-07-14 dim-9 修:Omit 'asChild' — chip.spec.md 禁止事項明載「❌ 用 asChild——不支援」,
84
+ // 且內部固定渲染 {icon}{label}{suffix} 多 children 結構,asChild(Radix Slot 要求單一
85
+ // element child)會 runtime throw(CLAUDE.md 失敗記憶「asChild ? Slot : Native」條)。
86
+ // 型別層 Omit 讓誤用在編譯期失敗,對齊 spec-vs-type 一致。
87
+ extends Omit<React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item>, 'asChild'> {
84
88
  /** 左側 icon(LucideIcon),最多一個 */
85
89
  startIcon?: LucideIcon
86
90
  /** 右側 badge(通常是計數指示器)*/
@@ -1,6 +1,6 @@
1
1
  // @principles-rationale: Merged WhenNotToUse + CircularVsSkeletonRule into a single
2
2
  // `UsageGuidance` story (3 sections — 何時用 / 何時不用 / vs 近親) per 2026-04-26 user
3
- // mandate. IndeterminateVsDeterminateRule / UsageScenarioRule / SizeMatchContextRule
3
+ // mandate. IndeterminateVsDeterminateRule / ConsumptionScenarioRule / SizeMatchContextRule
4
4
  // kept as separate principles.
5
5
  import React from 'react'
6
6
  import type { Meta, StoryObj } from '@storybook/react'
@@ -52,7 +52,7 @@ export const UsageGuidance: Story = {
52
52
  <Section title="何時用">
53
53
  <p className="text-caption text-fg-muted max-w-[720px] leading-relaxed mb-6">
54
54
  CircularProgress 用於「使用者觸發 async 動作後的即時回饋」與「全頁 / 浮層的 loading 訊號」。
55
- 詳細情境 → UsageScenarioRule(Button loading / Inline 表單驗證 / Empty 全頁 overlay)。
55
+ 詳細情境 → 「常見消費場景」story(Button loading / Inline 表單驗證 / Empty 全頁 overlay)。
56
56
  </p>
57
57
  </Section>
58
58
 
@@ -184,8 +184,11 @@ export const IndeterminateVsDeterminateRule: Story = {
184
184
  ),
185
185
  }
186
186
 
187
- export const UsageScenarioRule: Story = {
188
- name: '使用情境',
187
+ // 2026-07-14 rename per audit Dim 14:原 name「使用情境」與同檔 UsageGuidance「使用指引」/
188
+ // SizeMatchContextRule「尺寸對應使用情境」語意撞名,讀者難分。本 story 教的是「CircularProgress
189
+ // 內嵌於 Button / Input / Empty 的常見消費場景」,name 改為可區辨的人話。
190
+ export const ConsumptionScenarioRule: Story = {
191
+ name: '常見消費場景(內嵌於 Button / Input / Empty)',
189
192
  render: () => (
190
193
  <div>
191
194
  <Rule
@@ -191,7 +191,7 @@ Track 色鎖 `var(--secondary)`(= neutral-3,與 ProgressBar track 一致)。
191
191
 
192
192
  ## 視覺與幾何鐵律
193
193
 
194
- - **正方形不可妥協**:`style={{ width: size, height: size }}` 強制。本體絕不加 margin / padding
194
+ - **正方形**:外層 span `style={{ width: size, height: size }}` + 內層 `<svg width height>` 雙重鎖尺寸——svg 顯式 width / height 兜底,即使 consumer 傳 `style` 覆寫外層 span,圓形圖形仍維持正方比例。本體絕不加 margin / padding
195
195
  - **SVG 雙 circle**:track(`var(--secondary)`) + arc(`currentColor`),stroke-linecap round,rotate -90deg 從 12 點起始
196
196
  - **strokeWidth 動態 scale**:`Math.max(2, Math.round(size / 10))` 維持跨尺寸視覺比例(逐值結果由公式推導,不另列舉)
197
197
  - **Indeterminate arc**:固定 25%(`INDETERMINATE_ARC_RATIO=0.25`),外層 `animate-spin` 旋轉整個 span(Material 流派)
@@ -223,8 +223,8 @@ CircularProgress 是**最薄的 circular progress primitive**,刻意避免多維
223
223
 
224
224
  - **無 Inspector**:variant 只有 value 有無(indeterminate / determinate 兩態),互動切換式 Inspector 可展的決策點少。`UsageInButton` / `UsageInline` 已覆蓋真實 consumer context
225
225
  - **ColorMatrix N/A**:arc 預設固定 `text-info`(consumer 傳 `className="text-current"` 才繼承 host,見上方「顏色策略」),track 固定 `var(--secondary)`,無 own variant × state 色彩組合可 matrix 對照。色彩不隨狀態變色(完成 / 失敗由 consumer swap 整個元件),`UsageInButton` / `UsageInline` 真實 context 已示範,獨立 ColorMatrix story 會是冗餘
226
- - **SizeMatrix N/A — 無 separate SizeMatrix story**:size 是自由 number(非 sm/md/lg tier),由 Button / Input 等 consumer 容器內部依規則程式化縮放,`UsageInButton` / `UsageInline` 真實 context 已涵蓋 16 / 24 / 32 / 48 等常用值的行為差異,比靜態 matrix 更貼近消費情境
227
- - **無 StateBehavior**:無 hover / focus / active,唯一「狀態」是 value 變化(已在 Determinate story 動態演示)
226
+ - **SizeMatrix N/A — 無 separate SizeMatrix story**:size 是自由 number(非 sm/md/lg tier),由 Button / Input 等 consumer 容器內部依規則程式化縮放,`UsageInButton` / `UsageInline` 真實 context 已涵蓋 16(cell / upload row)/ 20(Input lg)/ 24(inline 預設)等常用值的行為差異,比靜態 matrix 更貼近消費情境(48 的全頁 overlay 尺寸見展示層 `FullScreenOverlay`)
227
+ - **無 StateBehavior**:無 hover / focus / active,唯一「狀態」是 value 變化(determinate 靜態值示範於 `UsageInline`「Determinate inline」段;元件不含 timer / RAF 動態演示,進度值由 consumer 傳入驅動)
228
228
 
229
229
  對應 anatomy story:`Overview` + `UsageInButton` + `UsageInline` + `Accessibility`(2026-05-17 per story-rules 6-canonical)。缺 canonical 5 多數項的 rationale 即本段。
230
230
 
@@ -15,8 +15,8 @@ import { DataTable } from '@/design-system/components/DataTable/data-table'
15
15
  * - 無 value → indeterminate 旋轉(取代舊 Spinner 用法)
16
16
  * - 有 value → determinate arc + track(可量化進度,如 inline 上傳 %)
17
17
  *
18
- * 範例均對標世界級產品的真實使用場景(Stripe 付款送出、GitHub PR merging、
19
- * Figma 雲端同步、Notion workspace loading、Google Drive 上傳)。
18
+ * 範例均對標世界級產品的真實使用場景(GitHub 儲存庫搜尋、檔案上傳佇列、
19
+ * 雲端同步狀態表格、workspace 切換載入)。
20
20
  * 設計規則詳見 `circular-progress.spec.md`。
21
21
  */
22
22
 
@@ -335,7 +335,7 @@ export const StateBehavior: Story = {
335
335
  <div>
336
336
  <H3>Focus / Esc / Click-outside(繼承 Popover)</H3>
337
337
  <Desc>
338
- Coachmark 大部分行為繼承 Popover(Radix),但刻意抑制 CTA 自動 focus(onOpenAutoFocus preventDefault focus content 容器本身)——避免使用者還在讀 body 時 CTA 被 auto-focus 偷觸發,Tab 第一下即達第一個 CTA(焦點不停 trigger,否則 non-modal focus-outside dismiss 會誤關閉浮層;2026-07-05 D4 修);關閉時 return to trigger;Esc 關閉浮層(透過 Radix onOpenChange,效果等同退出,但不觸發 onSkip callback);預設 non-modal,使用者可忽略繼續主流程。
338
+ Coachmark 大部分互動行為繼承 Popover。開啟時焦點落在內容區、不會自動跳到按鈕,避免你還在讀內容時就誤觸推進——按 Tab 才移到按鈕(單步、無標題列時一下即達推進鍵;有標題列會先到右上的關閉 X,多步則先經「上一步 / 略過」)。關閉後焦點回到觸發元素;按 Esc 關閉(效果等同退出,但不會觸發 onSkip);預設不鎖背景,你可以忽略它繼續原本的操作。技術細節(Radix API 名稱與修正紀錄) `coachmark.spec.md`「A11y 預設」段與 coachmark.tsx。
339
339
  </Desc>
340
340
  </div>
341
341
  </div>
@@ -350,7 +350,7 @@ export const Accessibility = {
350
350
  render: () => (
351
351
  <div className="max-w-3xl text-body text-fg-secondary">
352
352
  <h3 className="text-h5 text-foreground mb-2">無障礙設計</h3>
353
- <p className="whitespace-pre-line">{"詳 `coachmark.spec.md` 「A11y 預設」段。摘要:\n\n- 焦點管理 :刻意抑制 CTA 自動 focus(onOpenAutoFocus preventDefault 後 focus content 容器本身)——避免 user 還在讀 body 時 CTA 被偷觸發;Tab 第一下即達第一個 CTA(焦點不停 trigger,否則 non-modal focus-outside dismiss 會誤關閉;2026-07-05 D4 );關閉時 return to trigger\n- Esc 關閉 :預設啟用——user 按 Esc 透過 Radix onOpenChange 關閉浮層(效果等同退出),但不觸發 onSkip callback(Esc 是「關閉浮層」非「明確 skip」)\n- ARIA :trigger 自動 aria-expanded / aria-controls ,content role=\"dialog\" (Radix 預設)\n- Step 計數 tabular-nums :螢幕閱讀器讀「2 of 3」語意清楚"}</p>
353
+ <p className="whitespace-pre-line">{"詳 `coachmark.spec.md` 「A11y 預設」段。摘要:\n\n- 焦點管理 :開啟時焦點落在內容區、不自動跳到按鈕,避免你還在讀內容時誤觸;按 Tab 才移到按鈕(單步、無標題列時一下即達推進鍵;有標題列 / 多步會先到關閉 X / 上一步 / 略過);關閉後焦點回到觸發元素\n- Esc 關閉 :預設啟用——user 按 Esc 透過 Radix onOpenChange 關閉浮層(效果等同退出),但不觸發 onSkip callback(Esc 是「關閉浮層」非「明確 skip」)\n- ARIA :trigger 自動 aria-expanded / aria-controls ,content role=\"dialog\" (Radix 預設)\n- Step 計數 tabular-nums :螢幕閱讀器讀「2 of 3」語意清楚"}</p>
354
354
  </div>
355
355
  ),
356
356
  }
@@ -279,7 +279,8 @@ export const MultiStepBestPracticesRule: Story = {
279
279
  >
280
280
  <Coachmark
281
281
  open
282
- image={<MediaGradient from="var(--color-blue-6)" to="var(--color-cyan-6)" icon={FolderPlus} label="Workspace" />}
282
+ // 2026-07-14 Dim 55:--color-cyan-6 不存在(12 hue 無 cyan) 改既有 turquoise
283
+ image={<MediaGradient from="var(--color-blue-6)" to="var(--color-turquoise-6)" icon={FolderPlus} label="Workspace" />}
283
284
  title="建立你的第一個 Workspace"
284
285
  description="Workspace 是團隊協作的主要空間,所有專案、文件、成員都在這裡集中管理。"
285
286
  step={{ current: 1, total: 3 }}
@@ -100,7 +100,7 @@ SSOT 規則:**Coachmark 不重寫 Popover 的任何視覺 token**,只加自己
100
100
 
101
101
  ## Props 結構
102
102
 
103
- - `children` — trigger anchor(用 Popover asChild 定位)
103
+ - `children` — trigger anchor(用 Popover asChild 定位)。**必為單一 anchor element**(型別 `ReactElement`;asChild Slot 契約,對齊 Popover / Tooltip / HoverCard——多元素 / fragment / string 會 `React.Children.only` runtime 炸,型別收緊讓錯誤提前到 compile 期)
104
104
  - `kind` — `'tips' | 'new-features' | ReactNode`;有值則渲染 Header(tour-level title)
105
105
  - `image` — ReactNode 媒體區;不傳則不渲染
106
106
  - `mediaRatio` — Media 長寬比(預設 `16/9`,見「Media 區規則」)
@@ -153,7 +153,7 @@ const steps = [
153
153
 
154
154
  **設計建議**:
155
155
  - **≤ 5 步**——超過使用者疲勞,改用靜態 onboarding 頁面
156
- - **Skip 只在第一步提供**——進到 step 2+ Skip 自動隱藏(canonical,見上方「CTA 語義表」);想退出走 Esc / header Close 按鈕
156
+ - **Skip 在傳 `onPrev` 時隱藏**——由 `onPrev` 是否存在決定(非讀 `step.current`):有 `onPrev`(通常為第 2+ 步)即自動隱藏 Skip;單步驟也不顯示(canonical,見上方「CTA 語義表」)。想退出走 Esc / header Close 按鈕
157
157
  - **最後一步 `isLastStep`**——Next → Done 語意切換,讓使用者知道「這是最後一步」
158
158
  - **每步 anchor 到對應 feature**——不 anchor 或 anchor 到無關元素 = 失去「教 X 怎麼用」的精準性
159
159
  - **Multi-step 建議傳 `kind="tips"` 或 `"new-features"`**——header 讓使用者一眼看出 tour 性質 / 何時結束的預期
@@ -165,8 +165,8 @@ const steps = [
165
165
  Previous(可選)→ Skip(可選)→ Next / Done。對齊 Ant Tour / Intercom convention: <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
166
166
 
167
167
  - **Previous 最左**——回到上一步(負方向,視覺權重低)
168
- - **Skip 中間**——exit escape hatch,tertiary 不搶焦點;**僅第一步顯示**( CTA 語義表)
169
- - **Next / Done 最右**——推進主動線(正方向,primary 視覺權重高);**Coachmark 抑制 CTA 自動 focus**(`onOpenAutoFocus` preventDefault 後 focus content 容器本身,非第一個 CTA),避免使用者還在讀 body 時按 Enter 誤推進;想推進者按一下 Tab 即達 CTA 再 Enter(焦點已在 content 內,不觸發 non-modal focus-outside dismiss;2026-07-05 D4 修)
168
+ - **Skip 中間**——exit escape hatch,tertiary 不搶焦點;**未傳 `onPrev` 時顯示**( `onPrev` 或單步則隱藏,見 CTA 語義表)
169
+ - **Next / Done 最右**——推進主動線(正方向,primary 視覺權重高);**Coachmark 抑制 CTA 自動 focus**(`onOpenAutoFocus` preventDefault 後 focus content 容器本身,非第一個 CTA),避免使用者還在讀 body 時按 Enter 誤推進;想推進者按 Tab 即達 CTA 再 Enter(單步無 header 一下即達;有 header 或多步時 Close X / Previous / Skip 在推進 CTA 前,需多按幾下;焦點已在 content 內,不觸發 non-modal focus-outside dismiss;2026-07-05 D4 修)
170
170
 
171
171
  第 1 步通常無 Previous;最後步 Next 改 Done(由 `isLastStep` 控制)。單步驟 CTA 改 `'知道了'`。
172
172
 
@@ -203,7 +203,7 @@ Previous(可選)→ Skip(可選)→ Next / Done。對齊 Ant Tour / Intercom con
203
203
 
204
204
  ## A11y 預設
205
205
 
206
- - **焦點管理**:Coachmark **刻意抑制 CTA 自動 focus**(`onOpenAutoFocus` preventDefault 後 focus content 容器本身,對齊 `dialog.tsx` 的 `?? content` fallback canonical)——避免使用者還在讀 body 時 CTA 被 auto-focus 偷觸發(焦點在容器上按 Enter 無動作);Tab 第一下即達 content 內第一個 CTA。焦點**不**停在 trigger:non-modal Popover 焦點在 content 樹外時按 Tab 會觸發 focus-outside dismiss 誤關閉浮層,CTA 鍵盤永遠到不了(2026-07-05 D4 修;dismiss 機制詳 `popover.spec.md` A11y 段)。關閉時焦點 return to trigger(Radix 預設 `onCloseAutoFocus`,未 override)
206
+ - **焦點管理**:Coachmark **刻意抑制 CTA 自動 focus**(`onOpenAutoFocus` preventDefault 後 focus content 容器本身,對齊 `dialog.tsx` 的 `?? content` fallback canonical)——避免使用者還在讀 body 時 CTA 被 auto-focus 偷觸發(焦點在容器上按 Enter 無動作);按 Tab 移到 content 內第一個 tabbable(單步無 header 即推進 CTA;有 header 會先到 PopoverHeader 右上 Close X,多步則先經 Previous / Skip)。焦點**不**停在 trigger:non-modal Popover 焦點在 content 樹外時按 Tab 會觸發 focus-outside dismiss 誤關閉浮層,CTA 鍵盤永遠到不了(2026-07-05 D4 修;dismiss 機制詳 `popover.spec.md` A11y 段)。關閉時焦點 return to trigger(Radix 預設 `onCloseAutoFocus`,未 override)
207
207
  - **Esc 關閉**:預設啟用——user 按 Esc 透過 Radix `onOpenChange` 關閉浮層(效果等同退出),**不觸發 `onSkip` callback**(Esc 是「關閉浮層」非「明確 skip」;若需區分 Esc-退出 vs Skip-按鈕 的追蹤事件,consumer 在 Skip 按鈕的 `onSkip` 處理)
208
208
  - **ARIA**:trigger 自動 `aria-expanded` / `aria-controls`,content `role="dialog"`(Radix 預設)
209
209
  - **Step 計數 tabular-nums**:螢幕閱讀器讀「2 of 3」語意清楚
@@ -46,7 +46,9 @@ const tourSteps = [
46
46
  {
47
47
  anchor: '建立 Workspace',
48
48
  icon: FolderPlus,
49
- media: { from: 'var(--color-blue-6)', to: 'var(--color-cyan-6)', label: 'Workspace' },
49
+ // 2026-07-14 audit Dim 55:原 `--color-cyan-6` 不存在(primitive 12 hue 無 cyan)→ 漸層
50
+ // 靜默斷掉。改用既有 turquoise(oklch hue 196,最接近 cyan 的 primitive)。
51
+ media: { from: 'var(--color-blue-6)', to: 'var(--color-turquoise-6)', label: 'Workspace' },
50
52
  title: '建立你的第一個 Workspace',
51
53
  description: 'Workspace 是團隊協作的主要空間,所有專案、文件、成員都在這裡集中管理。',
52
54
  },
@@ -36,7 +36,9 @@ import { OVERLAY_SIDE_OFFSET } from '@/design-system/tokens/elevation/overlay-ge
36
36
  * 同樣規則)。CTA = `isLastStep ? 'Done' : 'Next'`
37
37
  * 4. **抑制 CTA 自動 focus,焦點落在 content 容器** — `onOpenAutoFocus` preventDefault
38
38
  * 後 focus content 容器本身(非第一個 CTA),避免使用者還在讀 body 時按 Enter 誤推進;
39
- * Tab 第一下即達 content 內第一個 CTA。焦點不可停在 trigger:non-modal Popover
39
+ * Tab 才移到 content 內按鈕:**單步無 header** 時第一個 tabbable 即推進 CTA;**有 header
40
+ * (kind / headerTitle 會渲 PopoverHeader 右上 Close X)或多步** 時 DOM 順序上 Close X /
41
+ * Previous / Skip 在推進 CTA 之前,需多按幾下 Tab。焦點不可停在 trigger:non-modal Popover 下
40
42
  * 焦點在 DismissableLayer 外按 Tab 會觸發 focus-outside dismiss 誤關閉
41
43
  * (2026-07-05 D4;對齊 dialog.tsx handleOpenAutoFocus `?? content` fallback,見 spec「A11y 預設」)。
42
44
  *
@@ -56,8 +58,13 @@ export interface CoachmarkProps extends Omit<React.HTMLAttributes<HTMLDivElement
56
58
  /** 預設打開(uncontrolled initial state)— 2026-05-15 audit Dim 26 V1 fix per user verbatim「A:1」approval */
57
59
  defaultOpen?: boolean
58
60
  onOpenChange?: (open: boolean) => void
59
- /** 觸發 anchor 元素。通常傳 trigger element;Coachmark 浮層會定位於此 */
60
- children: React.ReactNode
61
+ /**
62
+ * 觸發 anchor 元素——**必為單一 React element**(內部走 `<PopoverTrigger asChild>` =
63
+ * Radix Slot 契約;傳 string / fragment / 多元素會 `React.Children.only` runtime 炸,
64
+ * 見 CLAUDE.md 失敗記憶索引「asChild + Slot」條)。與 Popover / Tooltip / HoverCard
65
+ * 同一錨點契約;型別收緊為 ReactElement 讓契約在 compile 期顯現。
66
+ */
67
+ children: React.ReactElement
61
68
  /** 頂部 media 區(圖片 / illustration / video 等);不傳則無 media */
62
69
  image?: React.ReactNode
63
70
  /**
@@ -291,9 +291,9 @@ export const Overview = {
291
291
  <span className="text-[11px] text-fg-secondary font-medium">空值</span>
292
292
  <div className="inline-flex items-center border-2 border-dashed border-primary/30 rounded-md px-3 py-2.5 gap-2">
293
293
  <span className="rounded px-2 py-1 text-[11px] font-mono border border-dashed"
294
- style={{ borderColor: 'var(--info)', backgroundColor: 'var(--info-subtle)', color: 'var(--info)' }}>— (em dash)</span>
294
+ style={{ borderColor: 'var(--info)', backgroundColor: 'var(--info-subtle)', color: 'var(--info)' }}>- (hyphen)</span>
295
295
  </div>
296
- <span className="text-[10px] text-fg-muted font-mono">text-fg-muted</span>
296
+ <span className="text-[10px] text-fg-muted font-mono">text-foreground</span>
297
297
  </div>
298
298
  </div>
299
299
  </div>