@qijenchen/design-system 0.1.0-beta.82 → 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 (612) 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 +37 -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 +17 -5
  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 +36 -0
  255. package/ds-canonical/fork/hooks/check_story_determinism.sh +39 -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 +20 -0
  259. package/ds-canonical/fork/preamble.md +22 -18
  260. package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +9 -3
  261. package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +3 -3
  262. package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +7 -0
  263. package/ds-canonical/fork/skills/performance-audit/SKILL.md +4 -2
  264. package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +3 -3
  265. package/ds-canonical/fork/skills/propose-options/SKILL.md +3 -3
  266. package/ds-canonical/fork/skills/prototype/SKILL.md +1 -1
  267. package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +2 -2
  268. package/ds-canonical/fork/skills/visual-audit/SKILL.md +10 -2
  269. package/ds-canonical/hooks/README.md +1 -1
  270. package/ds-canonical/hooks/block_prototype_imports.py +15 -4
  271. package/ds-canonical/hooks/check_audit_post_report_validator.sh +65 -7
  272. package/ds-canonical/hooks/check_benchmark_citation.sh +5 -3
  273. package/ds-canonical/hooks/check_codex_brief_invariants.sh +28 -1
  274. package/ds-canonical/hooks/check_consumer_app_invariants.sh +145 -13
  275. package/ds-canonical/hooks/check_ds_anchor_preflight.sh +17 -5
  276. package/ds-canonical/hooks/check_dynamic_tailwind_class.sh +47 -0
  277. package/ds-canonical/hooks/check_escape_marker_abuse.sh +27 -0
  278. package/ds-canonical/hooks/check_field_family_invariants.sh +61 -1
  279. package/ds-canonical/hooks/check_layout_space_magic_numbers.sh +28 -4
  280. package/ds-canonical/hooks/check_naming_and_abstraction.sh +1 -1
  281. package/ds-canonical/hooks/check_opacity_token_usage.sh +36 -0
  282. package/ds-canonical/hooks/check_pixel_quantified_audit.sh +3 -2
  283. package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +6 -1
  284. package/ds-canonical/hooks/check_propose_without_benchmark.sh +6 -2
  285. package/ds-canonical/hooks/check_ssot_header_declaration.sh +55 -0
  286. package/ds-canonical/hooks/check_story_determinism.sh +39 -0
  287. package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +8 -7
  288. package/ds-canonical/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  289. package/ds-canonical/hooks/lib/_story_compile_drift.sh +1 -1
  290. package/ds-canonical/hooks/lib/_token_hygiene.sh +10 -1
  291. package/ds-canonical/hooks/stop_self_audit.sh +31 -0
  292. package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +24 -0
  293. package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +44 -0
  294. package/ds-canonical/hooks/tests/test_check_benchmark_citation.sh +3 -3
  295. package/ds-canonical/hooks/tests/test_check_codex_brief_invariants.sh +43 -2
  296. package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +112 -0
  297. package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +9 -2
  298. package/ds-canonical/hooks/tests/test_check_dynamic_tailwind_class.sh +76 -0
  299. package/ds-canonical/hooks/tests/test_check_escape_marker_abuse.sh +24 -0
  300. package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +27 -2
  301. package/ds-canonical/hooks/tests/test_check_fork_user_plugin_install.sh +3 -1
  302. package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +41 -2
  303. package/ds-canonical/hooks/tests/test_check_ssot_header_declaration.sh +72 -0
  304. package/ds-canonical/hooks/tests/test_check_tabs_content_chrome_body_double_gap.sh +76 -0
  305. package/ds-canonical/references/audit-coverage-vs-24-checklist.md +1 -1
  306. package/ds-canonical/references/build-ui-canonicals.md +2 -1
  307. package/ds-canonical/references/failure-class-registry.json +145 -0
  308. package/ds-canonical/references/governance-audit-coverage.md +33 -0
  309. package/ds-canonical/references/item-anatomy-recipe.md +2 -2
  310. package/ds-canonical/references/scenario-definition.md +6 -9
  311. package/ds-canonical/references/ssot-consultation.md +2 -2
  312. package/ds-canonical/references/ssot-index.md +5 -4
  313. package/ds-canonical/references/story-baseline-registry.json +8 -2
  314. package/ds-canonical/references/structural-token-retention.md +6 -9
  315. package/ds-canonical/rules/meta-patterns.md +8 -8
  316. package/ds-canonical/rules/self-verify.md +4 -3
  317. package/ds-canonical/rules/spec-rules.md +1 -1
  318. package/ds-canonical/rules/story-rules.md +2 -2
  319. package/ds-canonical/rules/ui-development.md +4 -2
  320. package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +9 -3
  321. package/ds-canonical/skills/code-quality-audit/SKILL.md +3 -3
  322. package/ds-canonical/skills/codex-collab/SKILL.md +9 -7
  323. package/ds-canonical/skills/codex-collab/references/brief-template.md +1 -1
  324. package/ds-canonical/skills/codify-principle/SKILL.md +2 -2
  325. package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
  326. package/ds-canonical/skills/component-quality-gate/references/checklist.md +2 -2
  327. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +57 -68
  328. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +29 -0
  329. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +29 -10
  330. package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +21 -0
  331. package/ds-canonical/skills/delivery-handoff/SKILL.md +5 -0
  332. package/ds-canonical/skills/design-system-audit/SKILL.md +27 -26
  333. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +13 -1
  334. package/ds-canonical/skills/design-system-audit/references/rule-placement.md +1 -1
  335. package/ds-canonical/skills/governance-health/SKILL.md +2 -1
  336. package/ds-canonical/skills/knowledge-prune/SKILL.md +3 -0
  337. package/ds-canonical/skills/knowledge-prune/references/prune-dimensions-d5-d10.md +1 -0
  338. package/ds-canonical/skills/new-component/SKILL.md +7 -5
  339. package/ds-canonical/skills/new-component/references/new-component-checklist.md +1 -1
  340. package/ds-canonical/skills/performance-audit/SKILL.md +2 -2
  341. package/ds-canonical/skills/product-ui-audit/SKILL.md +3 -3
  342. package/ds-canonical/skills/propose-options/SKILL.md +3 -3
  343. package/ds-canonical/skills/prototype/SKILL.md +1 -1
  344. package/ds-canonical/skills/scan-similar-bugs/SKILL.md +2 -2
  345. package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +3 -3
  346. package/ds-canonical/skills/story-writing/SKILL.md +3 -3
  347. package/ds-canonical/skills/visual-audit/SKILL.md +10 -2
  348. package/ds-story-manifest.json +29 -20
  349. package/llms-full.txt +22 -1
  350. package/llms.txt +5 -4
  351. package/package.json +7 -3
  352. package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
  353. package/src/components/Accordion/accordion.stories.tsx +16 -1
  354. package/src/components/Alert/alert.principles.stories.tsx +1 -1
  355. package/src/components/Alert/alert.spec.md +8 -10
  356. package/src/components/Alert/alert.stories.tsx +28 -28
  357. package/src/components/Alert/alert.tsx +1 -1
  358. package/src/components/AppShell/_demo-helpers.tsx +6 -3
  359. package/src/components/AppShell/app-shell.spec.md +4 -4
  360. package/src/components/AppShell/app-shell.tsx +28 -2
  361. package/src/components/AspectRatio/aspect-ratio.spec.md +1 -1
  362. package/src/components/AspectRatio/aspect-ratio.stories.tsx +7 -89
  363. package/src/components/Avatar/avatar.anatomy.stories.tsx +7 -3
  364. package/src/components/Avatar/avatar.principles.stories.tsx +19 -15
  365. package/src/components/Avatar/avatar.spec.md +2 -2
  366. package/src/components/Avatar/avatar.stories.tsx +8 -6
  367. package/src/components/Avatar/avatar.tsx +13 -5
  368. package/src/components/Badge/badge.principles.stories.tsx +1 -1
  369. package/src/components/Badge/badge.spec.md +2 -0
  370. package/src/components/Badge/badge.stories.tsx +4 -2
  371. package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +6 -4
  372. package/src/components/Breadcrumb/breadcrumb.stories.tsx +6 -5
  373. package/src/components/Breadcrumb/breadcrumb.tsx +3 -2
  374. package/src/components/BulkActionBar/bulk-action-bar.spec.md +4 -2
  375. package/src/components/Button/button.principles.stories.tsx +1 -1
  376. package/src/components/Button/button.spec.md +2 -2
  377. package/src/components/Button/button.tsx +18 -3
  378. package/src/components/Calendar/calendar.anatomy.stories.tsx +12 -10
  379. package/src/components/Calendar/calendar.principles.stories.tsx +14 -6
  380. package/src/components/Calendar/calendar.spec.md +5 -4
  381. package/src/components/Calendar/calendar.stories.tsx +7 -4
  382. package/src/components/Calendar/calendar.tsx +26 -7
  383. package/src/components/Carousel/carousel.anatomy.stories.tsx +5 -4
  384. package/src/components/Carousel/carousel.spec.md +2 -2
  385. package/src/components/Carousel/carousel.tsx +11 -3
  386. package/src/components/Chart/chart.anatomy.stories.tsx +7 -4
  387. package/src/components/Chart/chart.principles.stories.tsx +1 -1
  388. package/src/components/Chart/chart.stories.tsx +2 -8
  389. package/src/components/Chart/chart.tsx +3 -0
  390. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +28 -49
  391. package/src/components/Checkbox/checkbox.principles.stories.tsx +1 -1
  392. package/src/components/Checkbox/checkbox.spec.md +11 -26
  393. package/src/components/Checkbox/checkbox.stories.tsx +11 -8
  394. package/src/components/Checkbox/checkbox.tsx +18 -13
  395. package/src/components/Chip/chip.anatomy.stories.tsx +44 -24
  396. package/src/components/Chip/chip.principles.stories.tsx +1 -1
  397. package/src/components/Chip/chip.spec.md +5 -4
  398. package/src/components/Chip/chip.tsx +5 -1
  399. package/src/components/CircularProgress/circular-progress.principles.stories.tsx +7 -4
  400. package/src/components/CircularProgress/circular-progress.spec.md +3 -3
  401. package/src/components/CircularProgress/circular-progress.stories.tsx +2 -2
  402. package/src/components/Coachmark/coachmark.anatomy.stories.tsx +2 -2
  403. package/src/components/Coachmark/coachmark.principles.stories.tsx +2 -1
  404. package/src/components/Coachmark/coachmark.spec.md +5 -5
  405. package/src/components/Coachmark/coachmark.stories.tsx +3 -1
  406. package/src/components/Coachmark/coachmark.tsx +10 -3
  407. package/src/components/Combobox/combobox.anatomy.stories.tsx +2 -2
  408. package/src/components/Combobox/combobox.tsx +53 -19
  409. package/src/components/Command/command.anatomy.stories.tsx +2 -2
  410. package/src/components/Command/command.principles.stories.tsx +1 -1
  411. package/src/components/Command/command.stories.tsx +42 -10
  412. package/src/components/DataTable/cell-registry.tsx +86 -63
  413. package/src/components/DataTable/column-types.ts +10 -1
  414. package/src/components/DataTable/data-table-column-visibility-panel.tsx +1 -1
  415. package/src/components/DataTable/data-table-filter-panel.tsx +4 -1
  416. package/src/components/DataTable/data-table-interaction-layer.tsx +15 -19
  417. package/src/components/DataTable/data-table.anatomy.stories.tsx +15 -13
  418. package/src/components/DataTable/data-table.principles.stories.tsx +9 -9
  419. package/src/components/DataTable/data-table.spec.md +32 -12
  420. package/src/components/DataTable/data-table.stories.tsx +16 -17
  421. package/src/components/DataTable/data-table.tsx +103 -60
  422. package/src/components/DataTable/index.ts +3 -0
  423. package/src/components/DateGrid/date-grid.anatomy.stories.tsx +4 -4
  424. package/src/components/DateGrid/date-grid.principles.stories.tsx +1 -1
  425. package/src/components/DateGrid/date-grid.spec.md +1 -1
  426. package/src/components/DateGrid/date-grid.tsx +3 -1
  427. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +8 -8
  428. package/src/components/DatePicker/date-picker.principles.stories.tsx +3 -3
  429. package/src/components/DatePicker/date-picker.spec.md +3 -3
  430. package/src/components/DatePicker/date-picker.stories.tsx +4 -5
  431. package/src/components/DatePicker/date-picker.tsx +99 -45
  432. package/src/components/DescriptionList/description-list.anatomy.stories.tsx +12 -10
  433. package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
  434. package/src/components/DescriptionList/description-list.spec.md +3 -3
  435. package/src/components/DescriptionList/description-list.stories.tsx +7 -6
  436. package/src/components/Dialog/dialog.anatomy.stories.tsx +1 -0
  437. package/src/components/Dialog/dialog.spec.md +9 -0
  438. package/src/components/Dialog/dialog.stories.tsx +66 -5
  439. package/src/components/Dialog/dialog.tsx +60 -25
  440. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +1 -1
  441. package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +8 -6
  442. package/src/components/DropdownMenu/dropdown-menu.spec.md +5 -5
  443. package/src/components/DropdownMenu/dropdown-menu.tsx +18 -9
  444. package/src/components/Empty/empty.anatomy.stories.tsx +1 -1
  445. package/src/components/Empty/empty.spec.md +2 -2
  446. package/src/components/Field/field-context.ts +69 -5
  447. package/src/components/Field/field-controls.spec.md +62 -8
  448. package/src/components/Field/field-edit-keys.ts +66 -0
  449. package/src/components/Field/field-types.ts +58 -9
  450. package/src/components/Field/field-wrapper.tsx +50 -42
  451. package/src/components/Field/field.anatomy.stories.tsx +9 -6
  452. package/src/components/Field/field.spec.md +1 -1
  453. package/src/components/Field/field.stories.tsx +1 -1
  454. package/src/components/Field/field.tsx +2 -1
  455. package/src/components/Field/form-validation.spec.md +3 -3
  456. package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +6 -6
  457. package/src/components/FieldControlGroup/field-control-group.spec.md +9 -4
  458. package/src/components/FieldControlGroup/field-control-group.tsx +1 -1
  459. package/src/components/FileItem/file-item.anatomy.stories.tsx +1 -1
  460. package/src/components/FileItem/file-item.spec.md +14 -8
  461. package/src/components/FileItem/file-item.stories.tsx +36 -25
  462. package/src/components/FileItem/file-item.tsx +8 -6
  463. package/src/components/FileUpload/file-upload.anatomy.stories.tsx +6 -6
  464. package/src/components/FileUpload/file-upload.principles.stories.tsx +5 -5
  465. package/src/components/FileUpload/file-upload.spec.md +1 -1
  466. package/src/components/FileUpload/file-upload.tsx +1 -1
  467. package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +4 -3
  468. package/src/components/FileViewer/file-viewer.principles.stories.tsx +3 -3
  469. package/src/components/FileViewer/file-viewer.spec.md +30 -12
  470. package/src/components/FileViewer/file-viewer.stories.tsx +1 -2
  471. package/src/components/FileViewer/file-viewer.tsx +12 -4
  472. package/src/components/FileViewer/image-renderer.tsx +35 -7
  473. package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -2
  474. package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -3
  475. package/src/components/HoverCard/hover-card.spec.md +5 -5
  476. package/src/components/HoverCard/hover-card.stories.tsx +16 -16
  477. package/src/components/HoverCard/hover-card.tsx +5 -3
  478. package/src/components/InlineEdit/index.ts +5 -0
  479. package/src/components/InlineEdit/inline-edit.spec.md +149 -0
  480. package/src/components/InlineEdit/inline-edit.stories.tsx +246 -0
  481. package/src/components/InlineEdit/inline-edit.tsx +287 -0
  482. package/src/components/Input/input.anatomy.stories.tsx +8 -7
  483. package/src/components/Input/input.principles.stories.tsx +2 -12
  484. package/src/components/Input/input.spec.md +13 -18
  485. package/src/components/Input/input.tsx +69 -22
  486. package/src/components/LinkInput/link-input.anatomy.stories.tsx +1 -1
  487. package/src/components/LinkInput/link-input.principles.stories.tsx +2 -2
  488. package/src/components/LinkInput/link-input.tsx +11 -10
  489. package/src/components/Menu/menu-item.anatomy.stories.tsx +3 -3
  490. package/src/components/Menu/menu-item.principles.stories.tsx +1 -1
  491. package/src/components/Menu/menu-item.spec.md +22 -15
  492. package/src/components/Menu/menu-item.stories.tsx +39 -11
  493. package/src/components/Menu/menu-item.tsx +38 -4
  494. package/src/components/Notice/notice.principles.stories.tsx +1 -1
  495. package/src/components/Notice/notice.spec.md +16 -3
  496. package/src/components/NumberInput/number-input.anatomy.stories.tsx +3 -3
  497. package/src/components/NumberInput/number-input.principles.stories.tsx +1 -1
  498. package/src/components/NumberInput/number-input.spec.md +4 -4
  499. package/src/components/NumberInput/number-input.tsx +19 -12
  500. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +10 -8
  501. package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +3 -3
  502. package/src/components/OverflowIndicator/overflow-indicator.spec.md +4 -2
  503. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +71 -63
  504. package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -8
  505. package/src/components/Pagination/pagination.spec.md +1 -1
  506. package/src/components/Pagination/pagination.stories.tsx +2 -6
  507. package/src/components/Pagination/pagination.tsx +1 -1
  508. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +4 -4
  509. package/src/components/PeoplePicker/people-picker.principles.stories.tsx +2 -2
  510. package/src/components/PeoplePicker/people-picker.spec.md +6 -6
  511. package/src/components/PeoplePicker/people-picker.tsx +56 -16
  512. package/src/components/PeoplePicker/person-display.tsx +32 -16
  513. package/src/components/Popover/popover.anatomy.stories.tsx +2 -2
  514. package/src/components/Popover/popover.tsx +3 -1
  515. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +12 -23
  516. package/src/components/ProfileCard/profile-card.spec.md +3 -3
  517. package/src/components/ProfileCard/profile-card.tsx +6 -6
  518. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +3 -1
  519. package/src/components/ProgressBar/progress-bar.principles.stories.tsx +1 -1
  520. package/src/components/ProgressBar/progress-bar.stories.tsx +50 -42
  521. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +10 -28
  522. package/src/components/RadioGroup/radio-group.stories.tsx +29 -32
  523. package/src/components/RadioGroup/radio-group.tsx +41 -15
  524. package/src/components/Rating/rating.spec.md +11 -3
  525. package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
  526. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
  527. package/src/components/ScrollArea/scroll-area.spec.md +7 -3
  528. package/src/components/ScrollArea/scroll-area.stories.tsx +1 -1
  529. package/src/components/ScrollArea/scroll-area.tsx +17 -4
  530. package/src/components/Select/select.anatomy.stories.tsx +3 -3
  531. package/src/components/Select/select.spec.md +27 -17
  532. package/src/components/Select/select.stories.tsx +33 -0
  533. package/src/components/Select/select.tsx +190 -36
  534. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +4 -4
  535. package/src/components/SelectMenu/select-menu.spec.md +15 -7
  536. package/src/components/SelectMenu/select-menu.tsx +16 -3
  537. package/src/components/SelectionControl/boolean-value.tsx +39 -0
  538. package/src/components/SelectionControl/index.ts +1 -0
  539. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +2 -2
  540. package/src/components/SelectionControl/selection-item.principles.stories.tsx +2 -2
  541. package/src/components/SelectionControl/selection-item.spec.md +3 -3
  542. package/src/components/SelectionControl/selection-item.stories.tsx +3 -3
  543. package/src/components/Separator/separator.spec.md +2 -2
  544. package/src/components/Separator/separator.stories.tsx +6 -27
  545. package/src/components/Sheet/sheet.anatomy.stories.tsx +1 -1
  546. package/src/components/Sheet/sheet.principles.stories.tsx +1 -1
  547. package/src/components/Sheet/sheet.spec.md +2 -2
  548. package/src/components/Sheet/sheet.tsx +9 -5
  549. package/src/components/Sidebar/sidebar.anatomy.stories.tsx +16 -12
  550. package/src/components/Sidebar/sidebar.principles.stories.tsx +10 -8
  551. package/src/components/Sidebar/sidebar.spec.md +13 -15
  552. package/src/components/Sidebar/sidebar.stories.tsx +8 -7
  553. package/src/components/Sidebar/sidebar.tsx +37 -25
  554. package/src/components/Skeleton/skeleton.stories.tsx +4 -11
  555. package/src/components/Slider/slider.anatomy.stories.tsx +3 -3
  556. package/src/components/Slider/slider.principles.stories.tsx +2 -2
  557. package/src/components/Slider/slider.spec.md +5 -5
  558. package/src/components/Slider/slider.tsx +3 -1
  559. package/src/components/Steps/steps.anatomy.stories.tsx +4 -4
  560. package/src/components/Steps/steps.principles.stories.tsx +1 -1
  561. package/src/components/Steps/steps.spec.md +1 -1
  562. package/src/components/Switch/switch.anatomy.stories.tsx +7 -7
  563. package/src/components/Switch/switch.principles.stories.tsx +4 -4
  564. package/src/components/Switch/switch.spec.md +8 -8
  565. package/src/components/Switch/switch.stories.tsx +9 -24
  566. package/src/components/Switch/switch.tsx +17 -13
  567. package/src/components/Tabs/tabs.anatomy.stories.tsx +10 -7
  568. package/src/components/Tabs/tabs.spec.md +1 -1
  569. package/src/components/Tabs/tabs.tsx +21 -1
  570. package/src/components/Textarea/textarea.anatomy.stories.tsx +1 -1
  571. package/src/components/Textarea/textarea.principles.stories.tsx +1 -1
  572. package/src/components/Textarea/textarea.spec.md +4 -4
  573. package/src/components/Textarea/textarea.tsx +72 -46
  574. package/src/components/TimePicker/time-columns.tsx +6 -2
  575. package/src/components/TimePicker/time-picker.principles.stories.tsx +1 -1
  576. package/src/components/TimePicker/time-picker.spec.md +3 -3
  577. package/src/components/TimePicker/time-picker.tsx +16 -10
  578. package/src/components/Toast/toast.stories.tsx +7 -4
  579. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +4 -4
  580. package/src/components/Tooltip/tooltip.principles.stories.tsx +3 -3
  581. package/src/components/Tooltip/tooltip.spec.md +1 -1
  582. package/src/components/Tooltip/tooltip.stories.tsx +4 -39
  583. package/src/components/Tooltip/tooltip.tsx +8 -6
  584. package/src/components/TreeView/tree-view.anatomy.stories.tsx +6 -3
  585. package/src/components/TreeView/tree-view.spec.md +42 -11
  586. package/src/components/TreeView/tree-view.stories.tsx +1 -0
  587. package/src/components/TreeView/tree-view.tsx +322 -17
  588. package/src/index.ts +584 -60
  589. package/src/patterns/action-bar/action-bar.spec.md +9 -0
  590. package/src/patterns/action-bar/action-bar.stories.tsx +6 -3
  591. package/src/patterns/element-anatomy/inline-action.spec.md +2 -0
  592. package/src/patterns/element-anatomy/item-anatomy.spec.md +14 -5
  593. package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -4
  594. package/src/patterns/element-anatomy/item-anatomy.tsx +7 -6
  595. package/src/patterns/header-canonical/header-canonical.spec.md +5 -4
  596. package/src/patterns/overlay-surface/overlay-surface.spec.md +22 -1
  597. package/src/styles/tokens.css +3 -0
  598. package/src/tokens/README.md +1 -1
  599. package/src/tokens/color/color.spec.md +3 -3
  600. package/src/tokens/color/color.stories.tsx +3 -3
  601. package/src/tokens/density/density.stories.tsx +16 -3
  602. package/src/tokens/layoutSpace/layoutSpace.spec.md +3 -1
  603. package/src/tokens/motion/motion.css +33 -21
  604. package/src/tokens/motion/motion.spec.md +32 -15
  605. package/src/tokens/motion/motion.stories.tsx +58 -5
  606. package/src/tokens/motion/motion.ts +7 -6
  607. package/src/tokens/motion/overlay-motion.ts +26 -0
  608. package/src/tokens/orphan-tokens.spec.md +4 -4
  609. package/src/tokens/token-system.spec.md +1 -0
  610. package/src/tokens/uiSize/uiSize.spec.md +1 -1
  611. package/src/tokens/uiSize/uiSize.stories.tsx +4 -2
  612. package/src/tokens/utility-registry.json +160 -23
@@ -3,14 +3,14 @@
3
3
  import * as React from 'react'
4
4
  import { X, Calendar as CalendarIcon, ArrowRight } from 'lucide-react'
5
5
  import { cn } from '@/lib/utils'
6
- import type { FieldMode, FieldVariant } from '@/design-system/components/Field/field-types'
7
- import { fieldWrapperStyles, bareInputStyles, EMPTY_DISPLAY, nakedCellRowModeAlign, fieldDisplayTextClass } from '@/design-system/components/Field/field-wrapper'
6
+ import type { FieldMode, FieldVariant, FieldVariantInternal, FieldWidth } from '@/design-system/components/Field/field-types'
7
+ import { fieldWrapperStyles, bareInputStyles, nakedCellRowModeAlign, fieldDisplayTextClass } from '@/design-system/components/Field/field-wrapper'
8
8
  import { ItemInlineAction, ItemSuffix } from '@/design-system/patterns/element-anatomy/item-anatomy'
9
9
  import { Popover, PopoverTrigger, PopoverAnchor, PopoverContent } from '@/design-system/components/Popover/popover'
10
10
  import { DateGrid } from '@/design-system/components/DateGrid/date-grid'
11
11
  import { Button } from '@/design-system/components/Button/button'
12
12
  import { SurfaceFooter } from '@/design-system/patterns/overlay-surface/overlay-surface'
13
- import { useFieldContext, useResolvedFieldSize, useResolvedFieldDisabled, useResolvedFieldMode, useResolvedFieldVariant, useResolvedFieldInvalid } from '@/design-system/components/Field/field-context'
13
+ import { useFieldContext, useResolvedFieldSize, useResolvedFieldDisabled, useResolvedFieldMode, useResolvedFieldVariant, useResolvedFieldInvalid, useFieldEmptyDisplay, fieldEmptyColorClass } from '@/design-system/components/Field/field-context'
14
14
  import {
15
15
  TimeColumns,
16
16
  isoToTimeParts,
@@ -53,7 +53,15 @@ function formatDate(
53
53
  value: string | number | Date,
54
54
  options: DateFormatOptions = {},
55
55
  ): string {
56
- const date = value instanceof Date ? value : new Date(value)
56
+ // TZ-safe:date-only / datetime ISO string isoToDate(local-time 語意,new Date(y,m-1,d))
57
+ // 而非 new Date('YYYY-MM-DD')(ECMAScript 以 UTC 解析 → 負時區 off-by-one,如 LA 顯前一天)。
58
+ // 非 ISO string(RFC 'Mar 12 2025' 等)fallback new Date();number timestamp 直接 new Date()。
59
+ const date =
60
+ value instanceof Date
61
+ ? value
62
+ : typeof value === 'string'
63
+ ? (isoToDate(value) ?? new Date(value))
64
+ : new Date(value)
57
65
  if (Number.isNaN(date.getTime())) return String(value)
58
66
  // 若 consumer 顯式傳 formatOptions / locale → 走 Intl.DateTimeFormat
59
67
  if (options.formatOptions || options.locale) {
@@ -103,11 +111,11 @@ function isoToDate(iso: string | null | undefined): Date | undefined {
103
111
  * 或 ISO datetime(YYYY-MM-DDTHH:MM[:SS])。
104
112
  *
105
113
  * 支援 format(per Material X DatePicker / Ant DatePicker typed input idiom):
106
- * - `YYYY-MM-DD` / `YYYY/MM/DD` / `YYYY.MM.DD`(ISO + 慣例 separator)
107
- * - `MM/DD/YYYY` / `MM-DD-YYYY`(US locale)
108
- * - `DD/MM/YYYY` / `DD-MM-YYYY`(EU locale)
114
+ * - `YYYY-MM-DD` / `YYYY/MM/DD` / `YYYY.MM.DD`(ISO + 慣例 separator,明確 parse branch)
109
115
  * - `YYYY-MM-DD HH:MM[:SS]` / `YYYY-MM-DDTHH:MM[:SS]`(datetime,showTime 才接)
110
- * - native `Date.parse()` fallback(handle 'Mar 12 2025' 等英文 RFC)
116
+ * - native `Date.parse()` fallback(handle 'Mar 12 2025' 等英文 RFC;US `MM/DD/YYYY` 亦由此判讀,ambiguous)
117
+ * ⚠️ 不支援 EU `DD/MM/YYYY`:無專屬 parser branch;native Date.parse 把 slash 日期當 US MM/DD,
118
+ * `31/12/2026`(月 > 12)直接 Invalid。v1 known-gap,需 EU 請走 formatOptions/locale 或另加 parser branch。
111
119
  *
112
120
  * Return:`{ iso, valid }`。Invalid → `valid=false` + `iso=null`,UI 顯 aria-invalid。
113
121
  * Partial input(打到一半)→ valid=false 但不顯 error UI(consumer 用 onBlur / Enter 才檢驗)。
@@ -123,6 +131,9 @@ function parseDateInput(input: string, opts: { allowTime: boolean }): { iso: str
123
131
  const [, y, m, d, hh, mm, ss] = isoDateMatch
124
132
  const date = new Date(Number(y), Number(m) - 1, Number(d), Number(hh ?? 0), Number(mm ?? 0), Number(ss ?? 0))
125
133
  if (isNaN(date.getTime()) || date.getMonth() !== Number(m) - 1) return { iso: null, valid: false }
134
+ // time 分量越界校驗:JS Date 會 silently normalize(25:99:99 → 隔日某時,getTime 仍 valid、
135
+ // getMonth 未必變),但回傳 iso 用的是原始越界字串 → 需在此擋掉 hh>23 / mm>59 / ss>59。
136
+ if (hh != null && (Number(hh) > 23 || Number(mm) > 59 || Number(ss ?? 0) > 59)) return { iso: null, valid: false }
126
137
  const datePart = dateToIso(date)
127
138
  if (hh != null && opts.allowTime) {
128
139
  const h2 = String(Number(hh)).padStart(2, '0')
@@ -290,6 +301,9 @@ export interface DatePickerProps
290
301
  mode?: FieldMode
291
302
  /** Field chrome variant. Default = context.variant ?? 'default'. Per-prop override. */
292
303
  variant?: FieldVariant
304
+ /** 寬度軸 — `fill` 填滿容器(default)/ `hug` 依內容收縮(value 寬 + slot 寬 + gap + 內 padding);
305
+ * chrome 與互動不變。SSOT → field-controls.spec.md「寬度軸(width: fill / hug)」。 */
306
+ width?: FieldWidth
293
307
  error?: boolean
294
308
  size?: 'sm' | 'md' | 'lg'
295
309
  /** ISO date(YYYY-MM-DD)或 ISO datetime(YYYY-MM-DDTHH:MM:SS,當 showTime=true) */
@@ -362,6 +376,7 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
362
376
  {
363
377
  mode,
364
378
  variant: variantProp,
379
+ width,
365
380
  error: errorProp = false,
366
381
  size: sizeProp,
367
382
  value,
@@ -396,7 +411,8 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
396
411
  const disabled = useResolvedFieldDisabled(disabledProp)
397
412
  // 2026-06-08 SSOT:mode 經 useResolvedFieldMode;修 <Field mode="display"> 漏 cascade
398
413
  const resolvedMode = useResolvedFieldMode({ mode, disabled })
399
- const variant: FieldVariant = useResolvedFieldVariant(variantProp)
414
+ const emptyDisplay = useFieldEmptyDisplay()
415
+ const variant: FieldVariantInternal = useResolvedFieldVariant(variantProp)
400
416
  const isEditable = resolvedMode === 'edit'
401
417
  // 2026-05-18 改 import ICON_SIZE SSOT(per user『做完』approval,消除 M17 違反 7+ 重複 ternary)
402
418
  const iconSize = ICON_SIZE[size as 'sm' | 'md' | 'lg']
@@ -408,11 +424,14 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
408
424
  // a11y:role="combobox" 必須有 accessible name(aria-label / labelledby / fieldCtx label)
409
425
  const accessibleName = ariaLabelProp ?? (ariaLabelledByProp ? undefined : (fieldCtx?.id ? undefined : resolvedPlaceholder))
410
426
 
411
- // Sync draft from value ONLY on open false→true(避免 popover 開啟期間 value 改變
412
- // clobber user 的編輯。Popover 關閉後下次再開時自動同步最新 value)
427
+ // Sync draft from value:closed 期間恆跟隨 + open false→true 同步(避免 popover 開啟期間
428
+ // value 改變 clobber user 的編輯)
429
+ // 2026-07-14 audit Dim 26(V4 state shadow):needConfirm trigger 讀 draft,原「只在 false→true
430
+ // 同步」使 controlled value 於關閉期間更新後,trigger 仍顯示舊值直到再次開啟 —— 改為
431
+ // 只要 open=false 就同步(與 range picker 分支 L83x 同款 canonical)。
413
432
  const lastOpenRef = React.useRef(open)
414
433
  React.useEffect(() => {
415
- if (!lastOpenRef.current && open) setDraft(value ?? null)
434
+ if (!open || !lastOpenRef.current) setDraft(value ?? null)
416
435
  lastOpenRef.current = open
417
436
  }, [open, value])
418
437
 
@@ -464,16 +483,16 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
464
483
  if (!showDisplayEndIcon) {
465
484
  // 2026-05-14 I2 fix(spec contract (e) display typography canonical):bare span 套
466
485
  // `fieldDisplayTextClass(size)`(sm/md→text-body,lg→text-body-lg)— 對齊 Field family 統一。
467
- if (!value) return <span className={cn(fieldDisplayTextClass(size), 'text-fg-muted', className)}>{EMPTY_DISPLAY}</span>
486
+ if (!value) return <span className={cn(fieldDisplayTextClass(size), fieldEmptyColorClass(resolvedMode), className)}>{emptyDisplay}</span>
468
487
  return <span className={cn(fieldDisplayTextClass(size), 'truncate', className)}>{displayCommitted}</span>
469
488
  }
470
489
  return (
471
490
  <div
472
- className={cn(fieldWrapperStyles({ mode: 'display', variant, size }), className)}
491
+ className={cn(fieldWrapperStyles({ mode: 'display', variant, width, size }), className)}
473
492
  data-field-mode="display"
474
493
  >
475
- <span className={cn(bareInputStyles, 'flex-1 min-w-0 truncate', !value && 'text-fg-muted')}>
476
- {value ? displayCommitted : EMPTY_DISPLAY}
494
+ <span className={cn(bareInputStyles, 'flex-1 min-w-0 truncate', !value && fieldEmptyColorClass(resolvedMode))}>
495
+ {value ? displayCommitted : emptyDisplay}
477
496
  </span>
478
497
  <ItemSuffix className="pointer-events-none">
479
498
  <CalendarIcon size={iconSize} className="text-fg-muted" aria-hidden />
@@ -486,7 +505,7 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
486
505
  if (!isEditable) {
487
506
  return (
488
507
  <div
489
- className={cn(fieldWrapperStyles({ mode: resolvedMode, variant: variant, size }), className)}
508
+ className={cn(fieldWrapperStyles({ mode: resolvedMode, variant: variant, width, size }), className)}
490
509
  data-field-mode={resolvedMode}
491
510
  aria-disabled={resolvedMode === 'disabled' ? true : undefined}
492
511
  {...(props as React.HTMLAttributes<HTMLDivElement>)}
@@ -494,7 +513,7 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
494
513
  <span className={cn('flex-1 min-w-0 truncate', resolvedMode === 'disabled' && 'text-fg-disabled')}>
495
514
  {value
496
515
  ? displayCommitted
497
- : <span className="text-fg-muted">{EMPTY_DISPLAY}</span>
516
+ : <span className={fieldEmptyColorClass(resolvedMode)}>{emptyDisplay}</span>
498
517
  }
499
518
  </span>
500
519
  {/* 2026-06-26 類型身份 indicator:edit 顯示 / readonly 不顯示(純值、不可開) / disabled 保留(fg-disabled,對齊原生 <select disabled>);
@@ -527,18 +546,22 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
527
546
  <PopoverTrigger asChild>
528
547
  <div
529
548
  ref={ref}
530
- id={idProp ?? fieldCtx?.id}
531
- role="combobox"
532
- tabIndex={disabled ? -1 : 0}
533
- aria-disabled={disabled || undefined}
534
- aria-label={accessibleName}
535
- aria-labelledby={ariaLabelledByProp ?? fieldCtx?.labelId}
536
- aria-invalid={error || undefined}
537
- aria-required={fieldCtx?.required || undefined}
538
- aria-describedby={ariaDescribedByProp ?? fieldCtx?.descriptionId}
539
- aria-errormessage={ariaErrorMessageProp ?? (error ? fieldCtx?.errorId : undefined)}
540
- aria-haspopup="dialog"
541
- aria-expanded={open}
549
+ // a11y(2026-07-14 dim-10 修):typeable 模式 combobox 語意(name / state / 鍵盤)
550
+ // 集中在內層 <input>(APG editable-combobox idiom)— 外層 div 移除 role / tabIndex
551
+ // / aria-*,否則形成「關掉鍵盤 handler 的假 combobox tab stop」+ 內層 input 變成
552
+ // 第二個未命名 tab stop(雙重焦點站)。非 typeable 維持原 div-as-combobox canonical。
553
+ id={typeable ? undefined : (idProp ?? fieldCtx?.id)}
554
+ role={typeable ? undefined : 'combobox'}
555
+ tabIndex={typeable ? undefined : (disabled ? -1 : 0)}
556
+ aria-disabled={typeable ? undefined : (disabled || undefined)}
557
+ aria-label={typeable ? undefined : accessibleName}
558
+ aria-labelledby={typeable ? undefined : (ariaLabelledByProp ?? fieldCtx?.labelId)}
559
+ aria-invalid={typeable ? undefined : (error || undefined)}
560
+ aria-required={typeable ? undefined : (fieldCtx?.required || undefined)}
561
+ aria-describedby={typeable ? undefined : (ariaDescribedByProp ?? fieldCtx?.descriptionId)}
562
+ aria-errormessage={typeable ? undefined : (ariaErrorMessageProp ?? (error ? fieldCtx?.errorId : undefined))}
563
+ aria-haspopup={typeable ? undefined : 'dialog'}
564
+ aria-expanded={typeable ? undefined : open}
542
565
  data-field-mode="edit"
543
566
  data-error={error ? '' : undefined}
544
567
  // Radix PopoverTrigger 只 compose onClick(onOpenToggle),`<div>` trigger 無
@@ -551,7 +574,7 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
551
574
  if (e.key === 'Escape') setOpen(false)
552
575
  }}
553
576
  className={cn(
554
- fieldWrapperStyles({ mode: 'edit', variant: variant, size, error }),
577
+ fieldWrapperStyles({ mode: 'edit', variant: variant, width, size, error }),
555
578
  'text-left cursor-pointer',
556
579
  'focus-visible:outline-none',
557
580
  className,
@@ -562,8 +585,21 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
562
585
  // Issue 10 typed input(2026-05-10):real `<input>` 接 user 鍵盤打字。
563
586
  // Click 在 input 上不 propagate 給外層 popover trigger(避免每次打字都開 popover)。
564
587
  // Calendar icon `<ItemSuffix>` 點才開 popover(Material/Ant typed-date idiom)。
588
+ // a11y(2026-07-14 dim-10 修):input 持完整 combobox 語意(id/name/state,APG
589
+ // editable-combobox)— 外層 div 已讓位(見上方 role/tabIndex 註解);ArrowDown
590
+ // 開 popover 補鍵盤開啟路徑(原僅 icon click 可開,鍵盤 user 無入口)。
565
591
  <input
566
592
  type="text"
593
+ id={idProp ?? fieldCtx?.id}
594
+ role="combobox"
595
+ aria-haspopup="dialog"
596
+ aria-expanded={open}
597
+ aria-label={accessibleName}
598
+ aria-labelledby={ariaLabelledByProp ?? fieldCtx?.labelId}
599
+ aria-required={fieldCtx?.required || undefined}
600
+ aria-describedby={ariaDescribedByProp ?? fieldCtx?.descriptionId}
601
+ aria-errormessage={ariaErrorMessageProp ?? ((inputInvalid || error) ? fieldCtx?.errorId : undefined)}
602
+ disabled={disabled}
567
603
  className={cn(bareInputStyles, 'truncate', !inputDraft && 'placeholder:text-fg-muted')}
568
604
  value={inputDraft}
569
605
  placeholder={resolvedPlaceholder}
@@ -575,6 +611,7 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
575
611
  if (composingRef.current) return
576
612
  if (e.key === 'Enter') { e.preventDefault(); handleInputCommit(inputDraft) }
577
613
  if (e.key === 'Escape') { setInputDraft(displayLive); setInputInvalid(false); e.preventDefault() }
614
+ if (e.key === 'ArrowDown' && !open) { e.preventDefault(); setOpen(true) }
578
615
  }}
579
616
  onBlur={() => { if (!composingRef.current) handleInputCommit(inputDraft) }}
580
617
  onClick={(e) => e.stopPropagation()}
@@ -607,12 +644,18 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
607
644
  </ItemSuffix>
608
645
  </div>
609
646
  </PopoverTrigger>
610
- <PopoverContent className="w-auto p-0" align="start">
611
- {/* role="dialog" 為 flex item of PopoverContent(flex flex-col overflow-hidden)。
612
- 2026-05-06 v9.1:加 `flex flex-col flex-1 min-h-0` 完成 M25 chain — viewport
647
+ <PopoverContent
648
+ className="w-auto p-0"
649
+ align="start"
650
+ aria-label="日期選擇" // i18n-allow: DS default dialog label
651
+ >
652
+ {/* a11y(2026-07-14 dim-10 修):Radix PopoverContent 自帶 role="dialog"(popover.tsx:58)
653
+ — 內層 div 原本重複 role="dialog" 形成雙層 nested unnamed dialog,改為純 layout div,
654
+ accessible name 收斂到外層 PopoverContent aria-label(單一 dialog 層)。
655
+ 2026-05-06 v9.1:`flex flex-col flex-1 min-h-0` 完成 M25 chain — viewport
613
656
  壓縮時 dialog 縮 + 內 calendar/footer 排序;原無 chain 致 calendar 末行被
614
657
  overflow-hidden 切掉、footer 推出 popover(user 報「位置改變就壞掉」根因)。 */}
615
- <div role="dialog" className="flex flex-col flex-1 min-h-0">
658
+ <div className="flex flex-col flex-1 min-h-0">
616
659
  {/* Calendar 區包 overflow-y-auto:viewport 壓縮時 calendar 內滾(Material / Carbon
617
660
  date picker idiom)。footer 永遠 in-view(SurfaceFooter shrink-0)。 */}
618
661
  <div className="flex-1 min-h-0 overflow-y-auto">
@@ -704,6 +747,9 @@ export interface DatePickerRangeProps
704
747
  mode?: FieldMode
705
748
  /** Field chrome variant. Default = context.variant ?? 'default'. Per-prop override. */
706
749
  variant?: FieldVariant
750
+ /** 寬度軸 — `fill` 填滿容器(default)/ `hug` 依內容收縮(value 寬 + slot 寬 + gap + 內 padding);
751
+ * chrome 與互動不變。SSOT → field-controls.spec.md「寬度軸(width: fill / hug)」。 */
752
+ width?: FieldWidth
707
753
  error?: boolean
708
754
  size?: 'sm' | 'md' | 'lg'
709
755
  /** 區間值:[start ISO, end ISO]。任一 null 代表尚未選。 */
@@ -728,6 +774,7 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
728
774
  {
729
775
  mode,
730
776
  variant: variantProp,
777
+ width,
731
778
  error: errorProp = false,
732
779
  size: sizeProp,
733
780
  value,
@@ -756,7 +803,8 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
756
803
  const disabled = useResolvedFieldDisabled(disabledProp)
757
804
  // 2026-06-08 SSOT:mode 經 useResolvedFieldMode;修 <Field mode="display"> 漏 cascade
758
805
  const resolvedMode = useResolvedFieldMode({ mode, disabled })
759
- const variant: FieldVariant = useResolvedFieldVariant(variantProp)
806
+ const emptyDisplay = useFieldEmptyDisplay()
807
+ const variant: FieldVariantInternal = useResolvedFieldVariant(variantProp)
760
808
  const isEditable = resolvedMode === 'edit'
761
809
  // 2026-05-18 改 import ICON_SIZE SSOT(per user『做完』approval,消除 M17 違反 7+ 重複 ternary)
762
810
  const iconSize = ICON_SIZE[size as 'sm' | 'md' | 'lg']
@@ -778,12 +826,15 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
778
826
  const endBtnRef = React.useRef<HTMLButtonElement>(null)
779
827
  const hasInteractedOutsideRef = React.useRef(false)
780
828
 
781
- // Sync draft from value ONLY on open false→true(canonical 2026-05-02 v3):
782
- // 之前用 `[value, open]` 雙 dep,popover 開啟期間 value 任何 reference 變更 useEffect
783
- // 觸發 → 直接 clobber user 的 draft 編輯。改成只在 open false→true 同步。
829
+ // Draft sync canonical(2026-07-14 dim-26 V4 修,升級 2026-05-02 v3):
830
+ // - open=false(關閉期間):controlled value 變更**必**同步 draft needConfirm 顯示層讀
831
+ // draft(startIso/endIso),不同步會讓 trigger 持續顯示 stale 舊區間(外部 controlled
832
+ // update 被凍結)。關閉期間無編輯進行,直接鏡射無 clobber 風險。
833
+ // - open=true(開啟期間):只在 false→true 轉換時 seed 一次;開啟中 value reference 變更
834
+ // 不覆寫,保護 user 尚未確認的 draft 編輯(原 v3 canonical 保留)。
784
835
  const lastOpenRef = React.useRef(open)
785
836
  React.useEffect(() => {
786
- if (!lastOpenRef.current && open) setDraft(value ?? [null, null])
837
+ if (!open || !lastOpenRef.current) setDraft(value ?? [null, null])
787
838
  lastOpenRef.current = open
788
839
  }, [open, value])
789
840
 
@@ -888,7 +939,7 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
888
939
  // mode='display'(Phase B2 2026-05-05):純內容輸出 — 無 Field wrapper / 無 Calendar icon。
889
940
  if (resolvedMode === 'display') {
890
941
  const hasAny = !!(startIso || endIso)
891
- if (!hasAny) return <span className={cn('text-fg-muted', className)}>{EMPTY_DISPLAY}</span>
942
+ if (!hasAny) return <span className={cn(fieldEmptyColorClass(resolvedMode), className)}>{emptyDisplay}</span>
892
943
  return (
893
944
  <span className={cn('inline-flex items-center min-w-0', nakedCellRowModeAlign, className)}>
894
945
  <span className={cn('truncate', !startIso && 'text-fg-muted')}>
@@ -907,7 +958,7 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
907
958
  return (
908
959
  <div
909
960
  ref={ref}
910
- className={cn(fieldWrapperStyles({ mode: resolvedMode, variant: variant, size }), className)}
961
+ className={cn(fieldWrapperStyles({ mode: resolvedMode, variant: variant, width, size }), className)}
911
962
  data-field-mode={resolvedMode}
912
963
  aria-disabled={resolvedMode === 'disabled' ? true : undefined}
913
964
  {...props}
@@ -943,7 +994,7 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
943
994
  data-error={error ? '' : undefined}
944
995
  data-state={open ? 'open' : 'closed'}
945
996
  className={cn(
946
- fieldWrapperStyles({ mode: 'edit', size, error }),
997
+ fieldWrapperStyles({ mode: 'edit', width, size, error }),
947
998
  'cursor-text',
948
999
  className,
949
1000
  )}
@@ -1002,6 +1053,7 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
1002
1053
  <PopoverContent
1003
1054
  className="w-auto p-0"
1004
1055
  align="start"
1056
+ aria-label="日期區間選擇" // i18n-allow: DS default dialog label
1005
1057
  // 2026-07-05 D4 focus 回復(機制詳 :758 comment):outside-click 標記不搶焦(鏡射
1006
1058
  // Radix non-modal 自家 hasInteractedOutside guard);其餘關閉路徑(Esc / 確定 /
1007
1059
  // 選完自動關)preventDefault 掉內建 triggerRef.focus()(Anchor-only 恆 null no-op)
@@ -1015,8 +1067,10 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
1015
1067
  hasInteractedOutsideRef.current = false
1016
1068
  }}
1017
1069
  >
1018
- {/* 2026-05-06 v9.1 M25 chain single DatePicker 修法,viewport 壓縮 calendar 內滾 + footer 永遠 in-view */}
1019
- <div role="dialog" aria-label="日期區間選擇" className="flex flex-col flex-1 min-h-0">
1070
+ {/* a11y(2026-07-14 dim-10 修):accessible name 收斂到外層 PopoverContent(Radix 自帶
1071
+ role="dialog")— 原內層第二個 role="dialog" 移除,避免 nested dialog 且外層 dialog 無名。
1072
+ 2026-05-06 v9.1 M25 chain — 同 single DatePicker 修法,viewport 壓縮 calendar 內滾 + footer 永遠 in-view */}
1073
+ <div className="flex flex-col flex-1 min-h-0">
1020
1074
  <div className="flex-1 min-h-0 overflow-y-auto">
1021
1075
  <CalendarTimeContainer
1022
1076
  showTime={showTime}
@@ -156,23 +156,23 @@ export const StateBehavior: Story = {
156
156
  render: () => (
157
157
  <div className="flex flex-col gap-10">
158
158
  <div>
159
- <H3>空值呈現 — 一律用 `—` 字元(em dash)</H3>
159
+ <H3>空值呈現 — 一律用半形 `-` 字元(hyphen)</H3>
160
160
  <Desc>
161
- DescriptionList 是唯讀資訊展示,空值不留空白(會讓使用者以為資料沒載入完)。一律用 em dash
162
- (`—`)明確表達「有查過,但這個欄位目前沒值」。對齊 Atlassian / Polaris / GitHub 的資訊卡慣例。
161
+ DescriptionList 是唯讀資訊展示,空值不留空白(會讓使用者以為資料沒載入完)。一律用半形連字號
162
+ (`-`,對齊 Field `EMPTY_DISPLAY`)明確表達「有查過,但這個欄位目前沒值」;色同 value `text-foreground`。對齊 Atlassian / Polaris / GitHub 的資訊卡慣例。
163
163
  </Desc>
164
164
  <div className="border border-dashed border-divider rounded-md p-4 max-w-md">
165
165
  <DescriptionList cols={2}>
166
166
  <DescriptionItem label="姓名">Ada Chen</DescriptionItem>
167
- <DescriptionItem label="職稱"><span className="text-fg-muted">—</span></DescriptionItem>
167
+ <DescriptionItem label="職稱"><span className="text-foreground">-</span></DescriptionItem>
168
168
  <DescriptionItem label="Email">user@example.com</DescriptionItem>
169
- <DescriptionItem label="電話"><span className="text-fg-muted">—</span></DescriptionItem>
169
+ <DescriptionItem label="電話"><span className="text-foreground">-</span></DescriptionItem>
170
170
  <DescriptionItem label="團隊">Engineering</DescriptionItem>
171
- <DescriptionItem label="直屬主管"><span className="text-fg-muted">—</span></DescriptionItem>
171
+ <DescriptionItem label="直屬主管"><span className="text-foreground">-</span></DescriptionItem>
172
172
  </DescriptionList>
173
173
  </div>
174
174
  <p className="text-footnote text-fg-muted mt-3">
175
- 空值不應該用「N/A」/「暫無」等字串——不同 consumer 會選不同字,破壞視覺一致。一律 em dash。
175
+ 空值不應該用「N/A」/「暫無」等字串——不同 consumer 會選不同字,破壞視覺一致。一律半形連字號 `-`。
176
176
  </p>
177
177
  </div>
178
178
 
@@ -180,14 +180,16 @@ export const StateBehavior: Story = {
180
180
  <H3>長 value — 自然換行,撐高該 grid cell</H3>
181
181
  <Desc>
182
182
  `value` 是自然流文字,超過欄寬自然換行(CSS grid 會讓該 row 的 cell 變高,其他 cell 保持 label
183
- top-aligned)。不使用 truncate——value 是被讀的內容,截斷會讓使用者漏資訊。
183
+ top-aligned)。不使用 truncate——value 是被讀的內容,截斷會讓使用者漏資訊。帶空白的文字(如職稱)
184
+ 自然斷行;無空白長字串(email / URL / token)需在該 item 加 `break-all` 才會斷(此範例 Email 欄已加;
185
+ vertical dd 預設不強制斷字,長字串由 consumer 自加 break-all)。
184
186
  </Desc>
185
187
  <div className="border border-dashed border-divider rounded-md p-4 max-w-md">
186
188
  <DescriptionList cols={2}>
187
189
  <DescriptionItem label="姓名">Ada Chen</DescriptionItem>
188
190
  <DescriptionItem label="職稱">Senior Staff Principal Engineer, Design Systems</DescriptionItem>
189
191
  <DescriptionItem label="辦公地點">Taipei, Taiwan</DescriptionItem>
190
- <DescriptionItem label="Email">very.long.email.address@subdomain.example.com</DescriptionItem>
192
+ <DescriptionItem label="Email" className="min-w-0 break-all">very.long.email.address@subdomain.example.com</DescriptionItem>
191
193
  </DescriptionList>
192
194
  </div>
193
195
  </div>
@@ -246,7 +248,7 @@ export const Accessibility = {
246
248
  render: () => (
247
249
  <div className="max-w-3xl text-body text-fg-secondary">
248
250
  <h3 className="text-h5 text-foreground mb-2">無障礙設計</h3>
249
- <p className="whitespace-pre-line">{"詳 `description-list.spec.md`「無障礙」段。摘要:\n\n- 語意 HTML:外層 <dl>,每組 <dt>(term)+ <dd>(description)— screen reader 讀「term X, description Y」配對敘事\n- DT/DD 配對:DescriptionItem 強制一組配對,不分開暴露 <dt>/<dd> primitive\n- 空值:consumer 占位(SR 讀出長破折號,比空 <dd> 明確)\n- 多欄 cols>1:視覺 grid、DOM 仍 item 順序,SR 依 DOM 敘事\n- 無互動:純唯讀呈現,無 keyboard / focus state(無 ARIA 補強需求,語意由原生 dl/dt/dd 承載)"}</p>
251
+ <p className="whitespace-pre-line">{"詳 `description-list.spec.md`「無障礙」段。摘要:\n\n- 語意 HTML:外層 <dl>,每組 <dt>(term)+ <dd>(description)— screen reader 讀「term X, description Y」配對敘事\n- DT/DD 配對:DescriptionItem 強制一組配對,不分開暴露 <dt>/<dd> primitive\n- 空值:consumer 傳半形 - 占位(裸 - SR 敘事弱,宜補 sr-only「無資料」,比空 <dd> 明確)\n- 多欄 cols>1:視覺 grid、DOM 仍 item 順序,SR 依 DOM 敘事\n- 無互動:純唯讀呈現,無 keyboard / focus state(無 ARIA 補強需求,語意由原生 dl/dt/dd 承載)"}</p>
250
252
  </div>
251
253
  ),
252
254
  }
@@ -185,7 +185,7 @@ export const LayoutRule: Story = {
185
185
  <DescriptionItem label="職稱">Senior Design Engineer</DescriptionItem>
186
186
  </DescriptionList>
187
187
  </Frame>
188
- <Label warn>↑ 窄容器配 cols=2 → email 與職稱都被壓到斷行,可讀性差</Label>
188
+ <Label warn>↑ 窄容器配 cols=2 → 職稱被迫斷行、email 擠壓貼邊,節奏亂、可讀性差</Label>
189
189
  </Rule>
190
190
  </div>
191
191
  ),
@@ -238,7 +238,7 @@ export const LabelAlignmentRule: Story = {
238
238
  </div>
239
239
  </Frame>
240
240
  <Label warn>
241
- ↑ 這是自訂 layout 模擬 key-right-value-left → 不是 DescriptionList,也無 dl/dt/dd 語義
241
+ ↑ 這是自訂 layout 模擬 label 左 / value 右(key-left-value-right)→ 不是 DescriptionList,也無 dl/dt/dd 語義
242
242
  </Label>
243
243
  </Rule>
244
244
  </div>
@@ -173,7 +173,7 @@ consumer 要在 DL 上方加 section heading(「基本資料」/「團隊資訊
173
173
 
174
174
  - **語意 HTML**:外層 `<dl>`,每組內 `<dt>` 為 term、`<dd>` 為 description——screen reader 會讀成「term X, description Y」對話,明確表達屬性-值關係
175
175
  - **DT / DD 配對**:每個 `<dt>` 必須有對應的 `<dd>`(不可孤立),否則 SR 敘事會中斷;元件內建一組 `DescriptionItem` 強制配對,不分開暴露 `<dt>` / `<dd>` primitive
176
- - **空值呈現**:value 空時由 **consumer 自行傳入** `<span className="text-fg-muted">—</span>` 占位(元件不自動 normalize——`<dd>` 直接 render `children`),`text-fg-muted` 降低視覺重量;SR 會讀出「長破折號」,比空 `<dd>` 更明確
176
+ - **空值呈現**:value 空時由 **consumer 自行傳入** `<span className="text-foreground">-</span>` 占位(半形 hyphen `-`,對齊 Field `EMPTY_DISPLAY` DS-wide 空值符號,2026-07-08 user 拍板「空值都用"-"⋯我從頭到尾哪裡有說要用全形的」;元件不自動 normalize——`<dd>` 直接 render `children`),`text-foreground`(同 value 色——「-」是不可編輯供檢視的值,非 placeholder 提示,2026-07-09 user 拍板)。**a11y known follow-up**:裸 `-` SR 敘事弱(半形連字號多被 SR 略過),宜補 `<span className="sr-only">無資料</span>` 或 `aria-label`,比空 `<dd>` 更明確
177
177
  - **多欄 `cols > 1`**:視覺為 grid 欄位,但 DOM 順序為 item 順序——SR 仍依 DOM 敘事(term1 → desc1 → term2 → desc2),不依視覺欄位;設計時確保 DOM 順序符合語意分組
178
178
  - **長值換行**:horizontal 模式的 value(`<dd>`)以 `break-all min-w-0` 處理,讓 URL / ID 等無空白長字串能斷行,避免撐破單列;vertical 模式 value 佔滿整欄寬,自然流文字依字詞換行(不強制單行 truncate,長內容保留可讀完整性)。若 vertical 模式需展示無空白長字串(連續英數 token),由 consumer 自行於該 value 加 `break-all`
179
179
  - **列表識別**:預設 `<dl>` 有部分瀏覽器 SR 不視為 list,若需明確 list 語意,DL 根容器可搭配 `role="list"` + `<div role="listitem">`(目前預設不加,保留標準 `<dl>` 語意,consumer 可自行加 role 覆蓋)
@@ -188,7 +188,7 @@ DescriptionList 是**唯讀 label / value 資料呈現**(非互動 / 非 variant
188
188
  - **無 ColorMatrix**:DL 固定 semantic token(label `text-fg-secondary` / value `text-foreground`),無自己的色彩變體,dark mode 由 semantic token 自動切換。加 color variant 不符語意(DL 是資訊展示,非狀態載體)。
189
189
  - **無 SizeMatrix**:DL 無 size prop——垂直間距隨 `layout-space` token 感知 density(見「間距」段),但 label / value typography 走 reading mode 固定 tier,不提供 sm / md / lg 變體。不同 density 由 token 自動處理,非 prop 切換。
190
190
 
191
- 對應 anatomy story(實際 5 個,對齊 6-canonical 結構;ColorMatrix / SizeMatrix N/A):`Overview`(anatomy + typography + 間距) + `Inspector`(Controls 即時切 `cols` / `direction` / `divided`) + `ColsMatrix`(元件特有 1 / 2 / 3 欄對照) + `StateBehavior`(空值 `—` / 長值 / 多行 / ReactNode value) + `Accessibility`(`dl/dt/dd` 語意 + 無互動說明)。
191
+ 對應 anatomy story(實際 5 個,對齊 6-canonical 結構;ColorMatrix / SizeMatrix N/A):`Overview`(anatomy + typography + 間距) + `Inspector`(Controls 即時切 `cols` / `direction` / `divided`) + `ColsMatrix`(元件特有 1 / 2 / 3 欄對照) + `StateBehavior`(空值 `-` / 長值 / 多行 / ReactNode value) + `Accessibility`(`dl/dt/dd` 語意 + 無互動說明)。
192
192
 
193
193
  ---
194
194
 
@@ -196,7 +196,7 @@ DescriptionList 是**唯讀 label / value 資料呈現**(非互動 / 非 variant
196
196
 
197
197
  - **Disabled(action cell)**:DescriptionList 主體為唯讀資料呈現,本身無 disabled state。**dd 內互動內容 canonical(2026-07-04 Q9 拍板,三處立場收斂)**:操作型互動(Button / Input)**禁止**(見「禁止事項」— 需要動作 → Field read-only / inline-edit / action row / 卡片 header action);展示 / 導覽型 ReactNode(Tag / Badge / **Link**)**允許**,Link 自行 own disabled,DL 不干預。對齊 Polaris(ReactNode 型別 + 純敘述範例)/ Ant(action 放 extra 不放 dd)/ Carbon(read-only default)三家共識。
198
198
  - **Loading**:DL 非 async surface,無 loading prop。若 page-level data 載入中,consumer 應在 DL 外層用 `<Skeleton>`(每組 dt/dd 對應一條 skeleton line)取代;DL 本體不渲染 loading state。
199
- - **Empty(no items / empty value)**:no items → consumer 應 conditional 渲 `<Empty>` 取代 DL,不渲空 `<dl>`(SR 會讀「empty list」造成混淆);individual value 空 → consumer 應自行傳入 `—`(em dash,包 `text-fg-muted`;元件不自動 normalize,已在「無障礙」段 codify)。
199
+ - **Empty(no items / empty value)**:no items → consumer 應 conditional 渲 `<Empty>` 取代 DL,不渲空 `<dl>`(SR 會讀「empty list」造成混淆);individual value 空 → consumer 應自行傳入半形 `-`(hyphen,對齊 Field `EMPTY_DISPLAY`,2026-07-08 user 拍板;包 `text-foreground`(色同 value,2026-07-09);元件不自動 normalize,已在「無障礙」段 codify)。
200
200
  - **長 label / 長值**:horizontal 模式 label(`dt`)`shrink-0` 不收縮、不截斷,value(`dd`)`break-all min-w-0` 斷行吸收擠壓;vertical 模式兩者佔滿欄寬自然換行。無空白長字串(URL / ID)詳「無障礙」段「長值換行」。
201
201
  - **Dark mode**:走 semantic token(`text-fg-secondary` / `text-foreground`)自動 adapt。
202
202
  - **Density**:垂直 gap 隨 `layout-space` token density-aware(見「間距」段),typography fixed reading mode tier 不變。
@@ -21,7 +21,7 @@ type Story = StoryObj<typeof DescriptionList>
21
21
  export const UserProfile: Story = {
22
22
  name: '使用者個資',
23
23
  render: () => (
24
- <div className="border border-border rounded-lg p-4 max-w-md">
24
+ <div className="border border-border rounded-lg p-[var(--layout-space-loose)] max-w-md">
25
25
  <DescriptionList cols={1}>
26
26
  <DescriptionItem label="姓名">Ada Chen</DescriptionItem>
27
27
  <DescriptionItem label="Email">ada.chen@example.com</DescriptionItem>
@@ -37,7 +37,7 @@ export const UserProfile: Story = {
37
37
  export const ProductSpec: Story = {
38
38
  name: '產品規格',
39
39
  render: () => (
40
- <div className="border border-border rounded-lg p-4 max-w-2xl">
40
+ <div className="border border-border rounded-lg p-[var(--layout-space-loose)] max-w-2xl">
41
41
  <DescriptionList cols={2}>
42
42
  <DescriptionItem label="螢幕尺寸">6.7 吋 Super Retina XDR</DescriptionItem>
43
43
  <DescriptionItem label="處理器">A18 Pro</DescriptionItem>
@@ -54,8 +54,9 @@ export const ProductSpec: Story = {
54
54
  export const OrderSummary: Story = {
55
55
  name: '訂單明細',
56
56
  render: () => (
57
- <div className="border border-border rounded-lg p-4 max-w-md">
58
- <div className="text-body font-medium mb-3">訂單摘要</div>
57
+ <div className="border border-border rounded-lg p-[var(--layout-space-loose)] max-w-md">
58
+ {/* title 到第一個 item 的間距 = item 之間間距(Gestalt proximity canonical,見 spec;對齊 Horizontal story)*/}
59
+ <div className="text-body font-medium mb-[var(--layout-space-tight)]">訂單摘要</div>
59
60
  <DescriptionList cols={1}>
60
61
  <DescriptionItem label="訂單編號">#20260418-A241</DescriptionItem>
61
62
  <DescriptionItem label="商品">Pro 年費方案 × 5 人</DescriptionItem>
@@ -75,7 +76,7 @@ export const OrderSummary: Story = {
75
76
  export const DetailPanel: Story = {
76
77
  name: '詳情面板',
77
78
  render: () => (
78
- <div className="border border-border rounded-lg p-4 max-w-3xl">
79
+ <div className="border border-border rounded-lg p-[var(--layout-space-loose)] max-w-3xl">
79
80
  <DescriptionList cols={3}>
80
81
  <DescriptionItem label="訂單狀態">已出貨</DescriptionItem>
81
82
  <DescriptionItem label="建立時間">2026-04-18 10:35</DescriptionItem>
@@ -92,7 +93,7 @@ export const DetailPanel: Story = {
92
93
  export const Horizontal: Story = {
93
94
  name: '水平佈局',
94
95
  render: () => (
95
- <div className="border border-border rounded-lg p-4 max-w-md">
96
+ <div className="border border-border rounded-lg p-[var(--layout-space-loose)] max-w-md">
96
97
  {/* title 到第一個 item 的間距 = item 之間間距(Gestalt proximity canonical,見 spec) */}
97
98
  <div className="text-body font-medium mb-[var(--layout-space-tight)]">檔案資訊</div>
98
99
  <DescriptionList direction="horizontal">
@@ -83,6 +83,7 @@ export const Overview: Story = {
83
83
  {[
84
84
  ['autoHeight', 'boolean', 'false', 'true=隨內容 / false=填滿 viewport(body 捲動)'],
85
85
  ['maxWidth', 'string | number', "'512px'", 'Content 最大寬度(傳 number 視為 px,亦可傳 CSS 值如 32rem),受 viewport inset 限制'],
86
+ ['actions(DialogHeader)', 'ReactNode', '—', 'Header 級操作 cluster(prev/next/⋮);DS 自動在 actions 與 Close X 間放 ButtonDivider(關閉誤觸保護,action-bar.spec.md:281)'],
86
87
  ].map(([p, t, d, desc]) => (
87
88
  <tr key={p}><Td mono>{p}</Td><Td mono>{t}</Td><Td mono>{d}</Td><Td>{desc}</Td></tr>
88
89
  ))}
@@ -105,6 +105,15 @@ Modal 與 viewport 四邊保持 `--layout-space-bottom`(48px)最小間距。
105
105
 
106
106
  **Canonical 來源**:Dialog 是 overlay chrome,corner close X 屬 action group region,必用 Button(非 Inline Action / 非自刻 button)。詳見 `patterns/element-anatomy/inline-action.spec.md`「Dismiss canonical — X close only」+ `patterns/overlay-surface/overlay-surface.spec.md`「Chrome dismiss size canonical」。
107
107
 
108
+ ### Header actions slot(2026-07-08)
109
+
110
+ Header 級操作(記錄 prev / next 導覽、header 級溢出選單 ⋮ 等「作用於整個 dialog 內容」的操作)走 `<DialogHeader actions={…}>` slot,**不**塞 children 自刻右側 cluster。
111
+
112
+ - **何時用**:操作對象是 dialog 承載的記錄本身(切換上下筆、複製連結、更多選單)。欄位級操作仍歸 body;confirm / cancel 歸 footer。
113
+ - **分隔線由 DS 自動放**:actions 與內建 Close X 之間 DS 渲 `<ButtonDivider>` — `action-bar.spec.md:281`「最右側為關閉 / 解除按鈕 → 分隔線必須(誤觸保護)」;幾何 = ButtonDivider `mx-1` 於 `gap-2` cluster → 兩側 12px 對稱(同 spec「分隔線幾何」段)。
114
+ - **按鈕形態**:`<Button variant="text" iconOnly …>`(text variant 自動 `data-unbounded`,不撐高 chrome header;對齊 action-bar「溢出按鈕一律最低視覺重量」)。
115
+ - ❌ **禁**:consumer 在 children 內自刻 cluster + divider(分隔線落點歸 DS,自刻 = 漏分隔線 / 幾何 drift 根因 — 2026-07-08 WM 詳情 header 錨例)。
116
+
108
117
  ## Title
109
118
 
110
119
  `text-body-lg font-medium truncate`——單行截斷,不換行。