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

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 (492) hide show
  1. package/AGENTS.md +210 -0
  2. package/CLAUDE.md +17 -191
  3. package/cli-init.mjs +30 -2
  4. package/dist/components/Accordion/accordion.d.ts +2 -2
  5. package/dist/components/Accordion/accordion.d.ts.map +1 -1
  6. package/dist/components/Accordion/accordion.js.map +1 -1
  7. package/dist/components/Avatar/avatar.js +1 -1
  8. package/dist/components/Avatar/avatar.js.map +1 -1
  9. package/dist/components/BulkActionBar/bulk-action-bar.d.ts +1 -1
  10. package/dist/components/BulkActionBar/bulk-action-bar.d.ts.map +1 -1
  11. package/dist/components/BulkActionBar/bulk-action-bar.js +3 -3
  12. package/dist/components/BulkActionBar/bulk-action-bar.js.map +1 -1
  13. package/dist/components/Button/button-group.d.ts +2 -2
  14. package/dist/components/Button/button-group.d.ts.map +1 -1
  15. package/dist/components/Button/button-group.js +2 -2
  16. package/dist/components/Button/button-group.js.map +1 -1
  17. package/dist/components/Button/button.d.ts +2 -1
  18. package/dist/components/Button/button.d.ts.map +1 -1
  19. package/dist/components/Button/button.js +1 -1
  20. package/dist/components/Button/button.js.map +1 -1
  21. package/dist/components/Carousel/carousel.d.ts +14 -8
  22. package/dist/components/Carousel/carousel.d.ts.map +1 -1
  23. package/dist/components/Carousel/carousel.js +64 -37
  24. package/dist/components/Carousel/carousel.js.map +1 -1
  25. package/dist/components/Checkbox/checkbox-group.d.ts.map +1 -1
  26. package/dist/components/Checkbox/checkbox-group.js +21 -14
  27. package/dist/components/Checkbox/checkbox-group.js.map +1 -1
  28. package/dist/components/Checkbox/checkbox.d.ts +2 -2
  29. package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
  30. package/dist/components/Checkbox/checkbox.js +49 -10
  31. package/dist/components/Checkbox/checkbox.js.map +1 -1
  32. package/dist/components/Combobox/combobox.d.ts +15 -6
  33. package/dist/components/Combobox/combobox.d.ts.map +1 -1
  34. package/dist/components/Combobox/combobox.js +13 -7
  35. package/dist/components/Combobox/combobox.js.map +1 -1
  36. package/dist/components/Command/command.d.ts.map +1 -1
  37. package/dist/components/Command/command.js +11 -2
  38. package/dist/components/Command/command.js.map +1 -1
  39. package/dist/components/DataTable/cell-registry.d.ts +5 -5
  40. package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
  41. package/dist/components/DataTable/cell-registry.js +41 -38
  42. package/dist/components/DataTable/cell-registry.js.map +1 -1
  43. package/dist/components/DataTable/column-types.d.ts +1 -17
  44. package/dist/components/DataTable/column-types.d.ts.map +1 -1
  45. package/dist/components/DataTable/column-types.js.map +1 -1
  46. package/dist/components/DataTable/data-table-column-visibility-panel.d.ts.map +1 -1
  47. package/dist/components/DataTable/data-table-column-visibility-panel.js +71 -64
  48. package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -1
  49. package/dist/components/DataTable/data-table-filter-group.d.ts +47 -0
  50. package/dist/components/DataTable/data-table-filter-group.d.ts.map +1 -0
  51. package/dist/components/DataTable/data-table-filter-group.js +154 -0
  52. package/dist/components/DataTable/data-table-filter-group.js.map +1 -0
  53. package/dist/components/DataTable/data-table-filter-panel.d.ts +0 -2
  54. package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
  55. package/dist/components/DataTable/data-table-filter-panel.js +5 -328
  56. package/dist/components/DataTable/data-table-filter-panel.js.map +1 -1
  57. package/dist/components/DataTable/data-table-filter-value-picker.d.ts +29 -0
  58. package/dist/components/DataTable/data-table-filter-value-picker.d.ts.map +1 -0
  59. package/dist/components/DataTable/data-table-filter-value-picker.js +187 -0
  60. package/dist/components/DataTable/data-table-filter-value-picker.js.map +1 -0
  61. package/dist/components/DataTable/data-table-interaction-layer.d.ts +2 -2
  62. package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
  63. package/dist/components/DataTable/data-table-sort-manager.js +2 -2
  64. package/dist/components/DataTable/data-table-sort-manager.js.map +1 -1
  65. package/dist/components/DataTable/data-table.d.ts +1 -1
  66. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  67. package/dist/components/DataTable/data-table.js +44 -32
  68. package/dist/components/DataTable/data-table.js.map +1 -1
  69. package/dist/components/DatePicker/date-picker.d.ts +3 -3
  70. package/dist/components/DatePicker/date-picker.js +4 -4
  71. package/dist/components/DatePicker/date-picker.js.map +1 -1
  72. package/dist/components/DescriptionList/description-list.d.ts +3 -3
  73. package/dist/components/DescriptionList/description-list.d.ts.map +1 -1
  74. package/dist/components/DescriptionList/description-list.js +6 -6
  75. package/dist/components/DescriptionList/description-list.js.map +1 -1
  76. package/dist/components/Dialog/dialog.d.ts +2 -2
  77. package/dist/components/Dialog/dialog.d.ts.map +1 -1
  78. package/dist/components/Dialog/dialog.js.map +1 -1
  79. package/dist/components/DropdownMenu/dropdown-menu.d.ts +8 -3
  80. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  81. package/dist/components/DropdownMenu/dropdown-menu.js +7 -7
  82. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  83. package/dist/components/Field/field-context.d.ts +16 -10
  84. package/dist/components/Field/field-context.d.ts.map +1 -1
  85. package/dist/components/Field/field-context.js.map +1 -1
  86. package/dist/components/Field/field-types.d.ts +2 -2
  87. package/dist/components/Field/field-types.d.ts.map +1 -1
  88. package/dist/components/Field/field-types.js.map +1 -1
  89. package/dist/components/Field/field-wrapper.d.ts +20 -4
  90. package/dist/components/Field/field-wrapper.d.ts.map +1 -1
  91. package/dist/components/Field/field-wrapper.js +30 -31
  92. package/dist/components/Field/field-wrapper.js.map +1 -1
  93. package/dist/components/Field/field.d.ts +1 -1
  94. package/dist/components/Field/field.d.ts.map +1 -1
  95. package/dist/components/Field/field.js +25 -3
  96. package/dist/components/Field/field.js.map +1 -1
  97. package/dist/components/Field/index.d.ts +1 -0
  98. package/dist/components/Field/index.d.ts.map +1 -1
  99. package/dist/components/Field/index.js +2 -0
  100. package/dist/components/Field/index.js.map +1 -1
  101. package/dist/components/Field/use-form-validation.d.ts +1 -1
  102. package/dist/components/Field/use-form-validation.js.map +1 -1
  103. package/dist/components/FileItem/file-item.d.ts.map +1 -1
  104. package/dist/components/FileItem/file-item.js +2 -5
  105. package/dist/components/FileItem/file-item.js.map +1 -1
  106. package/dist/components/FileUpload/file-upload.d.ts.map +1 -1
  107. package/dist/components/FileUpload/file-upload.js +5 -1
  108. package/dist/components/FileUpload/file-upload.js.map +1 -1
  109. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  110. package/dist/components/FileViewer/file-viewer.js +2 -1
  111. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  112. package/dist/components/HoverCard/hover-card.d.ts +2 -2
  113. package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
  114. package/dist/components/HoverCard/hover-card.js +4 -2
  115. package/dist/components/HoverCard/hover-card.js.map +1 -1
  116. package/dist/components/InlineEdit/inline-edit.d.ts +23 -16
  117. package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -1
  118. package/dist/components/InlineEdit/inline-edit.js +104 -62
  119. package/dist/components/InlineEdit/inline-edit.js.map +1 -1
  120. package/dist/components/Input/input.d.ts +1 -1
  121. package/dist/components/Input/input.d.ts.map +1 -1
  122. package/dist/components/Input/input.js +6 -6
  123. package/dist/components/Input/input.js.map +1 -1
  124. package/dist/components/LinkInput/link-input.d.ts +5 -5
  125. package/dist/components/LinkInput/link-input.d.ts.map +1 -1
  126. package/dist/components/LinkInput/link-input.js +3 -3
  127. package/dist/components/LinkInput/link-input.js.map +1 -1
  128. package/dist/components/Notice/notice.d.ts +17 -1
  129. package/dist/components/Notice/notice.d.ts.map +1 -1
  130. package/dist/components/Notice/notice.js +7 -1
  131. package/dist/components/Notice/notice.js.map +1 -1
  132. package/dist/components/NumberInput/number-input.d.ts +1 -1
  133. package/dist/components/NumberInput/number-input.d.ts.map +1 -1
  134. package/dist/components/NumberInput/number-input.js +12 -1
  135. package/dist/components/NumberInput/number-input.js.map +1 -1
  136. package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts +1 -1
  137. package/dist/components/PeoplePicker/avatar-stack-overflow.js.map +1 -1
  138. package/dist/components/PeoplePicker/people-picker.d.ts +5 -5
  139. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  140. package/dist/components/PeoplePicker/people-picker.js +7 -5
  141. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  142. package/dist/components/PeoplePicker/person-display.d.ts +1 -1
  143. package/dist/components/PeoplePicker/person-display.js.map +1 -1
  144. package/dist/components/ProfileCard/profile-card.d.ts +1 -1
  145. package/dist/components/ProfileCard/profile-card.js.map +1 -1
  146. package/dist/components/RadioGroup/radio-group.d.ts +3 -3
  147. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  148. package/dist/components/RadioGroup/radio-group.js +1 -1
  149. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  150. package/dist/components/Rating/rating.d.ts.map +1 -1
  151. package/dist/components/Rating/rating.js +4 -0
  152. package/dist/components/Rating/rating.js.map +1 -1
  153. package/dist/components/ScrollArea/scroll-area.d.ts +3 -2
  154. package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
  155. package/dist/components/ScrollArea/scroll-area.js.map +1 -1
  156. package/dist/components/SegmentedControl/segmented-control.d.ts +4 -3
  157. package/dist/components/SegmentedControl/segmented-control.d.ts.map +1 -1
  158. package/dist/components/SegmentedControl/segmented-control.js.map +1 -1
  159. package/dist/components/Select/select.d.ts +16 -6
  160. package/dist/components/Select/select.d.ts.map +1 -1
  161. package/dist/components/Select/select.js +17 -5
  162. package/dist/components/Select/select.js.map +1 -1
  163. package/dist/components/SelectMenu/select-menu.d.ts +17 -1
  164. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  165. package/dist/components/SelectMenu/select-menu.js +17 -3
  166. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  167. package/dist/components/SelectionControl/boolean-value.d.ts +1 -1
  168. package/dist/components/SelectionControl/boolean-value.js.map +1 -1
  169. package/dist/components/Sheet/sheet.d.ts +2 -2
  170. package/dist/components/Sheet/sheet.d.ts.map +1 -1
  171. package/dist/components/Sheet/sheet.js.map +1 -1
  172. package/dist/components/Sidebar/sidebar.d.ts +1 -1
  173. package/dist/components/Sidebar/sidebar.js +2 -2
  174. package/dist/components/Sidebar/sidebar.js.map +1 -1
  175. package/dist/components/Slider/slider.d.ts.map +1 -1
  176. package/dist/components/Slider/slider.js +6 -3
  177. package/dist/components/Slider/slider.js.map +1 -1
  178. package/dist/components/Steps/steps.d.ts +6 -4
  179. package/dist/components/Steps/steps.d.ts.map +1 -1
  180. package/dist/components/Steps/steps.js +19 -5
  181. package/dist/components/Steps/steps.js.map +1 -1
  182. package/dist/components/Switch/switch.d.ts +4 -4
  183. package/dist/components/Switch/switch.d.ts.map +1 -1
  184. package/dist/components/Switch/switch.js +3 -1
  185. package/dist/components/Switch/switch.js.map +1 -1
  186. package/dist/components/Tabs/tabs.d.ts +1 -1
  187. package/dist/components/Tabs/tabs.d.ts.map +1 -1
  188. package/dist/components/Tabs/tabs.js +73 -23
  189. package/dist/components/Tabs/tabs.js.map +1 -1
  190. package/dist/components/Tag/tag.d.ts +3 -1
  191. package/dist/components/Tag/tag.d.ts.map +1 -1
  192. package/dist/components/Tag/tag.js +2 -2
  193. package/dist/components/Tag/tag.js.map +1 -1
  194. package/dist/components/Textarea/textarea.d.ts +4 -4
  195. package/dist/components/Textarea/textarea.d.ts.map +1 -1
  196. package/dist/components/Textarea/textarea.js +15 -15
  197. package/dist/components/Textarea/textarea.js.map +1 -1
  198. package/dist/components/TimePicker/time-picker.d.ts +4 -4
  199. package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
  200. package/dist/components/TimePicker/time-picker.js +8 -5
  201. package/dist/components/TimePicker/time-picker.js.map +1 -1
  202. package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
  203. package/dist/components/Tooltip/tooltip.js +27 -23
  204. package/dist/components/Tooltip/tooltip.js.map +1 -1
  205. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  206. package/dist/components/TreeView/tree-view.js +16 -0
  207. package/dist/components/TreeView/tree-view.js.map +1 -1
  208. package/dist/index.d.ts +7 -7
  209. package/dist/index.d.ts.map +1 -1
  210. package/dist/index.js +6 -11
  211. package/dist/lib/drag-visual.d.ts +2 -2
  212. package/dist/lib/drag-visual.js.map +1 -1
  213. package/dist/lib/utils.d.ts +1 -0
  214. package/dist/lib/utils.d.ts.map +1 -1
  215. package/dist/lib/utils.js +21 -1
  216. package/dist/lib/utils.js.map +1 -1
  217. package/dist/patterns/element-anatomy/item-anatomy.d.ts +2 -0
  218. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
  219. package/dist/patterns/element-anatomy/item-anatomy.js +2 -2
  220. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  221. package/dist/tokens/categorical-color.d.ts +3 -3
  222. package/dist/tokens/categorical-color.d.ts.map +1 -1
  223. package/dist/tokens/categorical-color.js +2 -2
  224. package/dist/tokens/categorical-color.js.map +1 -1
  225. package/ds-canonical/fork/AGENTS.md +213 -0
  226. package/ds-canonical/fork/codex/agents/skills/independent-review/SKILL.md +33 -0
  227. package/ds-canonical/fork/codex/hooks.json +16 -0
  228. package/ds-canonical/fork/governance.lock +22 -7
  229. package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +22 -1
  230. package/ds-canonical/fork/hooks/inject_deploy_url_after_push.sh +14 -2
  231. package/ds-canonical/fork/manifest.json +10 -1
  232. package/ds-canonical/fork/preamble.md +3 -2
  233. package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +7 -7
  234. package/ds-canonical/fork/skills/ux-audit/SKILL.md +1 -1
  235. package/ds-canonical/fork/skills/visual-audit/SKILL.md +0 -1
  236. package/ds-canonical/hooks/check_codex_brief_invariants.sh +9 -3
  237. package/ds-canonical/hooks/check_datatable_invariants.sh +6 -3
  238. package/ds-canonical/hooks/check_ds_anchor_preflight.sh +22 -1
  239. package/ds-canonical/hooks/check_overlay_open_focus_escape_probe.sh +11 -2
  240. package/ds-canonical/hooks/check_plugin_fork_health.sh +17 -1
  241. package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +21 -4
  242. package/ds-canonical/hooks/inject_deploy_url_after_push.sh +14 -2
  243. package/ds-canonical/hooks/session_start_governance_check.sh +10 -2
  244. package/ds-canonical/references/certified-surfaces.md +20 -0
  245. package/ds-canonical/references/preflight-gate-baseline.json +5 -0
  246. package/ds-canonical/references/principle-dim-map.json +20 -2
  247. package/ds-canonical/references/props-naming.md +2 -1
  248. package/ds-canonical/references/ssot-index.md +2 -2
  249. package/ds-canonical/references/story-baseline-registry.json +2 -2
  250. package/ds-canonical/rules/story-rules.md +1 -1
  251. package/ds-canonical/rules/ui-development.md +2 -1
  252. package/ds-canonical/skills/codex-collab/SKILL.md +7 -7
  253. package/ds-canonical/skills/codex-collab/references/brief-template.md +5 -1
  254. package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
  255. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +5 -5
  256. package/ds-canonical/skills/design-system-audit/SKILL.md +5 -5
  257. package/ds-canonical/skills/product-ui-audit/SKILL.md +7 -7
  258. package/ds-canonical/skills/ux-audit/SKILL.md +1 -1
  259. package/ds-canonical/skills/visual-audit/SKILL.md +0 -1
  260. package/ds-story-manifest.json +21 -21
  261. package/llms-full.txt +3 -3
  262. package/llms.txt +1 -1
  263. package/package.json +2 -1
  264. package/src/components/Accordion/accordion.anatomy.stories.tsx +11 -11
  265. package/src/components/Accordion/accordion.principles.stories.tsx +21 -6
  266. package/src/components/Accordion/accordion.spec.md +10 -1
  267. package/src/components/Accordion/accordion.stories.tsx +10 -5
  268. package/src/components/Accordion/accordion.tsx +7 -2
  269. package/src/components/Alert/alert.principles.stories.tsx +2 -8
  270. package/src/components/AppShell/app-shell.anatomy.stories.tsx +19 -13
  271. package/src/components/AppShell/app-shell.principles.stories.tsx +21 -21
  272. package/src/components/AppShell/app-shell.spec.md +4 -0
  273. package/src/components/AppShell/app-shell.stories.tsx +4 -5
  274. package/src/components/Avatar/avatar.tsx +1 -1
  275. package/src/components/Badge/badge.spec.md +2 -2
  276. package/src/components/Breadcrumb/breadcrumb.anatomy.stories.tsx +7 -3
  277. package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +4 -1
  278. package/src/components/Breadcrumb/breadcrumb.stories.tsx +1 -1
  279. package/src/components/BulkActionBar/bulk-action-bar.anatomy.stories.tsx +6 -6
  280. package/src/components/BulkActionBar/bulk-action-bar.principles.stories.tsx +18 -6
  281. package/src/components/BulkActionBar/bulk-action-bar.spec.md +15 -5
  282. package/src/components/BulkActionBar/bulk-action-bar.stories.tsx +8 -24
  283. package/src/components/BulkActionBar/bulk-action-bar.tsx +4 -4
  284. package/src/components/Button/button-group.tsx +4 -4
  285. package/src/components/Button/button.anatomy.stories.tsx +26 -7
  286. package/src/components/Button/button.principles.stories.tsx +1 -1
  287. package/src/components/Button/button.spec.md +2 -2
  288. package/src/components/Button/button.stories.tsx +22 -28
  289. package/src/components/Button/button.tsx +2 -1
  290. package/src/components/Calendar/calendar.anatomy.stories.tsx +1 -1
  291. package/src/components/Calendar/calendar.spec.md +1 -1
  292. package/src/components/Carousel/carousel.spec.md +17 -1
  293. package/src/components/Carousel/carousel.tsx +93 -42
  294. package/src/components/Checkbox/checkbox-group.tsx +26 -15
  295. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +3 -3
  296. package/src/components/Checkbox/checkbox.spec.md +14 -3
  297. package/src/components/Checkbox/checkbox.stories.tsx +4 -4
  298. package/src/components/Checkbox/checkbox.tsx +79 -19
  299. package/src/components/Coachmark/coachmark.anatomy.stories.tsx +5 -5
  300. package/src/components/Coachmark/coachmark.principles.stories.tsx +1 -1
  301. package/src/components/Combobox/combobox.anatomy.stories.tsx +11 -4
  302. package/src/components/Combobox/combobox.principles.stories.tsx +10 -11
  303. package/src/components/Combobox/combobox.spec.md +6 -2
  304. package/src/components/Combobox/combobox.stories.tsx +9 -36
  305. package/src/components/Combobox/combobox.tsx +42 -27
  306. package/src/components/Command/command.spec.md +3 -3
  307. package/src/components/Command/command.tsx +9 -2
  308. package/src/components/DataTable/cell-registry.tsx +75 -76
  309. package/src/components/DataTable/column-types.ts +4 -17
  310. package/src/components/DataTable/data-table-column-visibility-panel.tsx +20 -7
  311. package/src/components/DataTable/data-table-filter-group.tsx +231 -0
  312. package/src/components/DataTable/data-table-filter-panel.tsx +19 -436
  313. package/src/components/DataTable/data-table-filter-value-picker.tsx +237 -0
  314. package/src/components/DataTable/data-table-interaction-layer.tsx +3 -3
  315. package/src/components/DataTable/data-table-sort-manager.tsx +2 -2
  316. package/src/components/DataTable/data-table.anatomy.stories.tsx +25 -24
  317. package/src/components/DataTable/data-table.css +2 -3
  318. package/src/components/DataTable/data-table.principles.stories.tsx +17 -11
  319. package/src/components/DataTable/data-table.spec.md +8 -8
  320. package/src/components/DataTable/data-table.stories.tsx +39 -29
  321. package/src/components/DataTable/data-table.tsx +94 -68
  322. package/src/components/DataTable/filter-operators.spec.md +5 -3
  323. package/src/components/DateGrid/date-grid.spec.md +1 -1
  324. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +9 -9
  325. package/src/components/DatePicker/date-picker.principles.stories.tsx +4 -4
  326. package/src/components/DatePicker/date-picker.spec.md +9 -9
  327. package/src/components/DatePicker/date-picker.stories.tsx +9 -9
  328. package/src/components/DatePicker/date-picker.tsx +13 -13
  329. package/src/components/DescriptionList/description-list.anatomy.stories.tsx +5 -5
  330. package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
  331. package/src/components/DescriptionList/description-list.spec.md +12 -12
  332. package/src/components/DescriptionList/description-list.stories.tsx +3 -3
  333. package/src/components/DescriptionList/description-list.tsx +10 -10
  334. package/src/components/Dialog/dialog.tsx +4 -1
  335. package/src/components/DropdownMenu/dropdown-menu.tsx +27 -14
  336. package/src/components/Field/field-context.ts +17 -11
  337. package/src/components/Field/field-controls.spec.md +44 -37
  338. package/src/components/Field/field-types.ts +14 -12
  339. package/src/components/Field/field-wrapper.tsx +59 -43
  340. package/src/components/Field/field.anatomy.stories.tsx +6 -6
  341. package/src/components/Field/field.principles.stories.tsx +5 -28
  342. package/src/components/Field/field.spec.md +4 -4
  343. package/src/components/Field/field.stories.tsx +103 -72
  344. package/src/components/Field/field.tsx +36 -4
  345. package/src/components/Field/form-validation.spec.md +2 -0
  346. package/src/components/Field/index.ts +1 -0
  347. package/src/components/Field/use-form-validation.ts +1 -1
  348. package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +3 -3
  349. package/src/components/FieldControlGroup/field-control-group.spec.md +3 -3
  350. package/src/components/FileItem/file-item.tsx +10 -8
  351. package/src/components/FileUpload/file-upload.principles.stories.tsx +7 -7
  352. package/src/components/FileUpload/file-upload.spec.md +3 -2
  353. package/src/components/FileUpload/file-upload.tsx +5 -1
  354. package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +1 -1
  355. package/src/components/FileViewer/file-viewer.principles.stories.tsx +1 -1
  356. package/src/components/FileViewer/file-viewer.spec.md +1 -1
  357. package/src/components/FileViewer/file-viewer.stories.tsx +1 -1
  358. package/src/components/FileViewer/file-viewer.tsx +3 -2
  359. package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -4
  360. package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -1
  361. package/src/components/HoverCard/hover-card.spec.md +2 -2
  362. package/src/components/HoverCard/hover-card.tsx +4 -2
  363. package/src/components/InlineEdit/inline-edit.anatomy.stories.tsx +184 -0
  364. package/src/components/InlineEdit/inline-edit.principles.stories.tsx +142 -0
  365. package/src/components/InlineEdit/inline-edit.spec.md +71 -46
  366. package/src/components/InlineEdit/inline-edit.stories.tsx +20 -19
  367. package/src/components/InlineEdit/inline-edit.tsx +211 -125
  368. package/src/components/Input/input.anatomy.stories.tsx +15 -15
  369. package/src/components/Input/input.principles.stories.tsx +3 -3
  370. package/src/components/Input/input.spec.md +4 -4
  371. package/src/components/Input/input.stories.tsx +3 -3
  372. package/src/components/Input/input.tsx +13 -13
  373. package/src/components/LinkInput/link-input.anatomy.stories.tsx +2 -2
  374. package/src/components/LinkInput/link-input.principles.stories.tsx +1 -1
  375. package/src/components/LinkInput/link-input.spec.md +6 -2
  376. package/src/components/LinkInput/link-input.stories.tsx +8 -8
  377. package/src/components/LinkInput/link-input.tsx +21 -19
  378. package/src/components/Notice/notice.principles.stories.tsx +1 -1
  379. package/src/components/Notice/notice.tsx +8 -2
  380. package/src/components/NumberInput/number-input.anatomy.stories.tsx +6 -6
  381. package/src/components/NumberInput/number-input.principles.stories.tsx +4 -4
  382. package/src/components/NumberInput/number-input.spec.md +6 -6
  383. package/src/components/NumberInput/number-input.stories.tsx +4 -4
  384. package/src/components/NumberInput/number-input.tsx +17 -5
  385. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +8 -4
  386. package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +6 -7
  387. package/src/components/OverflowIndicator/overflow-indicator.spec.md +1 -1
  388. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +6 -30
  389. package/src/components/PeoplePicker/avatar-stack-overflow.ts +1 -1
  390. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +13 -10
  391. package/src/components/PeoplePicker/people-picker.principles.stories.tsx +5 -1
  392. package/src/components/PeoplePicker/people-picker.stories.tsx +5 -5
  393. package/src/components/PeoplePicker/people-picker.tsx +39 -20
  394. package/src/components/PeoplePicker/person-display.tsx +3 -3
  395. package/src/components/Popover/popover.anatomy.stories.tsx +10 -7
  396. package/src/components/Popover/popover.principles.stories.tsx +49 -28
  397. package/src/components/Popover/popover.spec.md +4 -2
  398. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +1 -1
  399. package/src/components/ProfileCard/profile-card.tsx +1 -1
  400. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +14 -13
  401. package/src/components/ProgressBar/progress-bar.principles.stories.tsx +8 -23
  402. package/src/components/ProgressBar/progress-bar.stories.tsx +8 -2
  403. package/src/components/README.md +1 -0
  404. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +8 -3
  405. package/src/components/RadioGroup/radio-group.stories.tsx +3 -3
  406. package/src/components/RadioGroup/radio-group.tsx +19 -14
  407. package/src/components/Rating/rating.anatomy.stories.tsx +1 -1
  408. package/src/components/Rating/rating.principles.stories.tsx +3 -3
  409. package/src/components/Rating/rating.spec.md +2 -2
  410. package/src/components/Rating/rating.stories.tsx +4 -18
  411. package/src/components/Rating/rating.tsx +5 -1
  412. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
  413. package/src/components/ScrollArea/scroll-area.spec.md +1 -1
  414. package/src/components/ScrollArea/scroll-area.tsx +5 -2
  415. package/src/components/SegmentedControl/segmented-control.principles.stories.tsx +4 -1
  416. package/src/components/SegmentedControl/segmented-control.spec.md +5 -10
  417. package/src/components/SegmentedControl/segmented-control.tsx +6 -3
  418. package/src/components/Select/select.anatomy.stories.tsx +13 -7
  419. package/src/components/Select/select.principles.stories.tsx +3 -3
  420. package/src/components/Select/select.spec.md +11 -1
  421. package/src/components/Select/select.stories.tsx +41 -27
  422. package/src/components/Select/select.tsx +44 -26
  423. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +44 -26
  424. package/src/components/SelectMenu/select-menu.principles.stories.tsx +0 -1
  425. package/src/components/SelectMenu/select-menu.stories.tsx +7 -19
  426. package/src/components/SelectMenu/select-menu.tsx +38 -5
  427. package/src/components/SelectionControl/boolean-value.tsx +2 -2
  428. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +1 -1
  429. package/src/components/SelectionControl/selection-item.principles.stories.tsx +4 -4
  430. package/src/components/Separator/separator.principles.stories.tsx +1 -1
  431. package/src/components/Sheet/sheet.principles.stories.tsx +5 -3
  432. package/src/components/Sheet/sheet.tsx +4 -1
  433. package/src/components/Sidebar/sidebar.tsx +1 -1
  434. package/src/components/Slider/slider.anatomy.stories.tsx +5 -4
  435. package/src/components/Slider/slider.principles.stories.tsx +6 -6
  436. package/src/components/Slider/slider.spec.md +13 -1
  437. package/src/components/Slider/slider.stories.tsx +44 -32
  438. package/src/components/Slider/slider.tsx +13 -4
  439. package/src/components/Steps/steps.anatomy.stories.tsx +7 -7
  440. package/src/components/Steps/steps.principles.stories.tsx +1 -1
  441. package/src/components/Steps/steps.spec.md +4 -2
  442. package/src/components/Steps/steps.stories.tsx +4 -56
  443. package/src/components/Steps/steps.tsx +31 -7
  444. package/src/components/Switch/switch.anatomy.stories.tsx +3 -3
  445. package/src/components/Switch/switch.principles.stories.tsx +1 -1
  446. package/src/components/Switch/switch.spec.md +4 -4
  447. package/src/components/Switch/switch.stories.tsx +3 -3
  448. package/src/components/Switch/switch.tsx +16 -10
  449. package/src/components/Tabs/tabs.anatomy.stories.tsx +6 -0
  450. package/src/components/Tabs/tabs.principles.stories.tsx +10 -2
  451. package/src/components/Tabs/tabs.spec.md +5 -2
  452. package/src/components/Tabs/tabs.stories.tsx +36 -44
  453. package/src/components/Tabs/tabs.tsx +101 -36
  454. package/src/components/Tag/tag.anatomy.stories.tsx +2 -2
  455. package/src/components/Tag/tag.principles.stories.tsx +4 -4
  456. package/src/components/Tag/tag.spec.md +3 -1
  457. package/src/components/Tag/tag.tsx +5 -3
  458. package/src/components/Textarea/textarea.anatomy.stories.tsx +6 -6
  459. package/src/components/Textarea/textarea.spec.md +5 -5
  460. package/src/components/Textarea/textarea.tsx +24 -24
  461. package/src/components/TimePicker/time-picker.anatomy.stories.tsx +12 -11
  462. package/src/components/TimePicker/time-picker.principles.stories.tsx +37 -44
  463. package/src/components/TimePicker/time-picker.spec.md +6 -5
  464. package/src/components/TimePicker/time-picker.stories.tsx +3 -3
  465. package/src/components/TimePicker/time-picker.tsx +24 -14
  466. package/src/components/Toast/toast.principles.stories.tsx +1 -1
  467. package/src/components/Toast/toast.stories.tsx +1 -1
  468. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +15 -6
  469. package/src/components/Tooltip/tooltip.principles.stories.tsx +4 -4
  470. package/src/components/Tooltip/tooltip.spec.md +9 -3
  471. package/src/components/Tooltip/tooltip.stories.tsx +1 -1
  472. package/src/components/Tooltip/tooltip.tsx +12 -2
  473. package/src/components/TreeView/tree-view.anatomy.stories.tsx +16 -14
  474. package/src/components/TreeView/tree-view.principles.stories.tsx +44 -11
  475. package/src/components/TreeView/tree-view.spec.md +8 -6
  476. package/src/components/TreeView/tree-view.stories.tsx +9 -43
  477. package/src/components/TreeView/tree-view.tsx +36 -0
  478. package/src/index.ts +16 -9
  479. package/src/lib/drag-visual.ts +2 -2
  480. package/src/lib/utils.ts +19 -0
  481. package/src/patterns/element-anatomy/inline-action.spec.md +1 -1
  482. package/src/patterns/element-anatomy/item-anatomy.tsx +4 -2
  483. package/src/patterns/header-canonical/header-canonical.spec.md +9 -0
  484. package/src/patterns/header-canonical/header-canonical.stories.tsx +31 -5
  485. package/src/tokens/categorical-color.ts +5 -5
  486. package/src/tokens/color/color.spec.md +5 -5
  487. package/src/tokens/color/primitives.css +9 -2
  488. package/src/tokens/opacity/opacity.spec.md +1 -1
  489. package/src/tokens/orphan-tokens.spec.md +1 -1
  490. package/src/tokens/typography/typography.spec.md +2 -0
  491. package/src/tokens/uiSize/uiSize.css +6 -1
  492. package/src/tokens/uiSize/uiSize.spec.md +1 -1
@@ -1,6 +1,6 @@
1
1
  # Advanced Filter 設計原則(Operator × ColumnType × ValueShape SSOT,v3)
2
2
 
3
- > **狀態**:已落地 — registry 寫成 `filter-operators.ts`,`filter-tree.ts` + `data-table-filter-panel.tsx` 消費(原 draft 兩個升級條件皆已達成,2026-06-11 對齊)。
3
+ > **狀態**:已落地 — registry 寫成 `filter-operators.ts`,`filter-tree.ts` + filter panel 家族消費(`data-table-filter-panel.tsx`;row/picker 直接消費點在 2026-07-14 拆檔子模組 `data-table-filter-group.tsx` / `data-table-filter-value-picker.tsx`)(原 draft 兩個升級條件皆已達成,2026-06-11 對齊)。
4
4
  > **M8 benchmark**:對照 ClickUp(CU)/ Airtable(AT)/ Notion(NT)三家。**v3 加 datetime / includeTime + 砍 number.between(2/3 業界共識)**。
5
5
  > **設計路線**:**ClickUp 為 baseline**,合理 + 不衝突 + 真實用的擴充採納。
6
6
  > **檔位**:暫放 DataTable/,若決定抽 `patterns/advanced-filter/` 再搬。
@@ -133,7 +133,7 @@
133
133
  | 1-to-1 比對 | ✓ `is` / `is_not`(picker 多選 OR-語意) | ✗ 不適用(陣列比單值 ambiguous) |
134
134
  | 集合運算 | ✗ 不適用 | ✓ `has_any_of` / `has_all_of` / `has_none_of` |
135
135
 
136
- 差異**根源於 cell 資料形狀**,不是 picker 不同。Value picker 兩者都共用 `<Combobox>` DS 既有元件(code 真值 `data-table-filter-panel.tsx` select_multi case)。
136
+ 差異**根源於 cell 資料形狀**,不是 picker 不同。Value picker 兩者都共用 `<Combobox>` DS 既有元件(code 真值 `data-table-filter-value-picker.tsx` select_multi case;2026-07-14 拆檔自 panel)。
137
137
 
138
138
  ### `person`(4 ops — 跟 select 同邏輯)
139
139
  | op key | 中 | en | valueShape | CU | AT | NT |
@@ -238,13 +238,15 @@
238
238
 
239
239
  **技術坑(信心 85%,Phase B spec.md 詳)**:TanStack `ColumnFiltersState` per-column 一筆 filter value,N 條同 column 會 AND-chain 不能 OR。**業界標準解法**:棄用 `columnFilters`,改自管 FilterTree state + 用 `globalFilter` + 自訂 `globalFilterFn` 走樹求 boolean。
240
240
 
241
- ## 8. 邊界案例(code 真值 — `filter-tree.ts` / `data-table-filter-panel.tsx`)
241
+ ## 8. 邊界案例(code 真值 — `filter-tree.ts` / filter panel 家族:`data-table-filter-panel.tsx` + `data-table-filter-group.tsx`)
242
242
 
243
243
  - **Condition 值空 / 未選 field**:視為 incomplete,求值 **pass-through**(不過濾任何 row);空值 ≠ `is_not_set`(後者是顯式 op)— `isConditionComplete` 守門
244
244
  - **群組刪光 condition**:空群組保留並 pass-through(true),panel 顯示「移除空群組」按鈕由 user 顯式刪除,不自動消失
245
245
  - **巢狀深度**:1-level cap 由 TypeScript 型別鎖死(`FilterGroup.children: FilterCondition[]`),無 runtime guard;繞過型別塞入的非 condition 物件缺 `field`/`op` → incomplete → pass-through,不 crash
246
246
  - **relative 區間邊界**:全部 local time、雙端 inclusive(`startOfDay`–`endOfDay`);`past_7_days` = 7 天前 00:00 起**含今天整天**;week 以週一起算(`weekStartsOn: 1`)
247
247
 
248
+ **A11y / Loading(明文 N/A)**:本 spec 是 Operator × ColumnType × ValueShape 資料模型 SSOT(非 UI 元件)——filter panel 的互動 a11y / loading 狀態屬 UI 層 owner(`data-table.spec.md` + filter panel 家族元件)與各 Field 控件 spec。
249
+
248
250
  ## 9. Phase B 進度
249
251
 
250
252
  - [x] ValueShape × DS 元件對照 — 完成,coverage 8/12 直接消費 + 4 預留;datetime 走 `<DatePicker showTime>` / `<DatePickerRange showTime>` prop variant(M21,非新元件)
@@ -58,7 +58,7 @@ DateGrid 是 internal primitive(見「定位」),一般 consumer 經 `DatePicker
58
58
  | 場景 | 改用 | 原因 |
59
59
  |------|------|------|
60
60
  | 日期輸入欄位 | `DatePicker` | DateGrid 是 inline,欄位需要 trigger + popup 結構 |
61
- | 純顯示單日期 | `<DatePicker mode="display">` / `Intl.DateTimeFormat` | 不需 interactive 月曆 |
61
+ | 純顯示單日期 | `<DatePicker mode="view">` / `Intl.DateTimeFormat` | 不需 interactive 月曆 |
62
62
  | 時間選擇(時分) | `TimePicker`(見 `../TimePicker/time-picker.spec.md`)| DateGrid 只處理日期層級 |
63
63
  | 事件行事曆(日程本) | 專用行事曆元件 | DateGrid 是日期選擇;事件日誌需要 event overlay / drag / week/month view 切換 |
64
64
 
@@ -248,7 +248,7 @@ export const Overview = {
248
248
  <thead><tr><Th>Prop</Th><Th>Type</Th><Th>Default</Th><Th>說明</Th></tr></thead>
249
249
  <tbody>
250
250
  {[
251
- ['mode', "'edit' | 'display' | 'readonly' | 'disabled'", "'edit'", "顯示模式;display 為純內容輸出(DataTable cell 用)。優先序:顯式 mode prop 永遠最優先,未傳 mode 時 disabled 才升 disabled(useResolvedFieldMode);disabled 以 aria-disabled 表達(trigger 為 div role=combobox,非原生 disabled 屬性)"],
251
+ ['mode', "'edit' | 'view' | 'readonly' | 'disabled'", "'edit'", "顯示模式;view 為純內容輸出(DataTable cell 用)。優先序:顯式 mode prop 永遠最優先,未傳 mode 時 disabled 才升 disabled(useResolvedFieldMode);disabled 以 aria-disabled 表達(trigger 為 div role=combobox,非原生 disabled 屬性)"],
252
252
  ['error', 'boolean', 'false', '紅色邊框 + aria-invalid,僅 edit 模式生效'],
253
253
  ['size', "'sm' | 'md' | 'lg'", "'md'", '高度與字體,與 Button 共用 field-height token'],
254
254
  ['value', 'string | null', '—', 'ISO date string(YYYY-MM-DD)'],
@@ -708,12 +708,12 @@ export const StateBehavior = {
708
708
  <span className="text-caption font-medium text-fg-secondary">格式化 — 預設 YYYY/MM/DD 直接組;傳 formatOptions / locale 走 Intl.DateTimeFormat</span>
709
709
  <div className="overflow-x-auto">
710
710
  <table className="border-collapse text-caption">
711
- <thead><tr><Th>設定</Th><Th>readonly 預覽</Th><Th>Display 預覽</Th></tr></thead>
711
+ <thead><tr><Th>設定</Th><Th>readonly 預覽</Th><Th>view 預覽</Th></tr></thead>
712
712
  <tbody>
713
713
  <tr>
714
714
  <Td>預設(YYYY/MM/DD)</Td>
715
715
  <td className="p-2 border-b border-divider"><DatePicker mode="readonly" value="2026-04-02" /></td>
716
- <td className="p-2 border-b border-divider"><DatePicker mode="display" value="2026-04-02" /></td>
716
+ <td className="p-2 border-b border-divider"><DatePicker mode="view" value="2026-04-02" /></td>
717
717
  </tr>
718
718
  <tr>
719
719
  <Td mono>month: 'short'</Td>
@@ -721,7 +721,7 @@ export const StateBehavior = {
721
721
  <DatePicker mode="readonly" value="2026-04-02" formatOptions={{ year: 'numeric', month: 'short', day: 'numeric' }} />
722
722
  </td>
723
723
  <td className="p-2 border-b border-divider">
724
- <DatePicker mode="display" value="2026-04-02" formatOptions={{ year: 'numeric', month: 'short', day: 'numeric' }} />
724
+ <DatePicker mode="view" value="2026-04-02" formatOptions={{ year: 'numeric', month: 'short', day: 'numeric' }} />
725
725
  </td>
726
726
  </tr>
727
727
  <tr>
@@ -730,7 +730,7 @@ export const StateBehavior = {
730
730
  <DatePicker mode="readonly" value="2026-04-02" formatOptions={{ year: 'numeric', month: 'long', day: 'numeric' }} />
731
731
  </td>
732
732
  <td className="p-2 border-b border-divider">
733
- <DatePicker mode="display" value="2026-04-02" formatOptions={{ year: 'numeric', month: 'long', day: 'numeric' }} />
733
+ <DatePicker mode="view" value="2026-04-02" formatOptions={{ year: 'numeric', month: 'long', day: 'numeric' }} />
734
734
  </td>
735
735
  </tr>
736
736
  <tr>
@@ -739,13 +739,13 @@ export const StateBehavior = {
739
739
  <DatePicker mode="readonly" value="2026-04-02" locale="zh-TW" formatOptions={{ year: 'numeric', month: 'long', day: 'numeric' }} />
740
740
  </td>
741
741
  <td className="p-2 border-b border-divider">
742
- <DatePicker mode="display" value="2026-04-02" locale="zh-TW" formatOptions={{ year: 'numeric', month: 'long', day: 'numeric' }} />
742
+ <DatePicker mode="view" value="2026-04-02" locale="zh-TW" formatOptions={{ year: 'numeric', month: 'long', day: 'numeric' }} />
743
743
  </td>
744
744
  </tr>
745
745
  </tbody>
746
746
  </table>
747
747
  </div>
748
- <span className="text-[11px] text-fg-muted">edit trigger 顯示文字與 Display 都用 Intl.DateTimeFormat 格式化(formatOptions / locale prop 對兩者皆生效,跨模式一致)。</span>
748
+ <span className="text-[11px] text-fg-muted">edit trigger 顯示文字與 view 都用 Intl.DateTimeFormat 格式化(formatOptions / locale prop 對兩者皆生效,跨模式一致)。</span>
749
749
  </div>
750
750
 
751
751
  {/* Empty value display */}
@@ -761,8 +761,8 @@ export const StateBehavior = {
761
761
  <DatePicker mode="disabled" value={null} className="w-48" />
762
762
  </div>
763
763
  <div className="flex items-center gap-3">
764
- <span className="text-[11px] text-fg-muted w-20 shrink-0">Display</span>
765
- <DatePicker mode="display" value={null} />
764
+ <span className="text-[11px] text-fg-muted w-20 shrink-0">view</span>
765
+ <DatePicker mode="view" value={null} />
766
766
  </div>
767
767
  </div>
768
768
  </div>
@@ -51,7 +51,7 @@ export const UsageGuidance: Story = {
51
51
  <li><LinkTo kind="Design System/Components/DatePicker/展示" name="可清除"><span className="text-primary hover:text-primary-hover font-medium cursor-pointer">篩選器的選填截止日,填錯一鍵清空(可清除)</span></LinkTo></li>
52
52
  <li><LinkTo kind="Design System/Components/DatePicker/展示" name="尺寸"><span className="text-primary hover:text-primary-hover font-medium cursor-pointer">緊湊工具列與標準表單的尺寸對應(尺寸)</span></LinkTo></li>
53
53
  <li><LinkTo kind="Design System/Components/DatePicker/展示" name="範圍模式:訂房 / 訂機票情境"><span className="text-primary hover:text-primary-hover font-medium cursor-pointer">Range:訂房 / 訂機票情境</span></LinkTo></li>
54
- <li><LinkTo kind="Design System/Components/DatePicker/展示" name="展示樣式"><span className="text-primary hover:text-primary-hover font-medium cursor-pointer">審批詳情頁唯讀展示申請日期(展示樣式)</span></LinkTo></li>
54
+ <li><LinkTo kind="Design System/Components/DatePicker/展示" name="檢視樣式"><span className="text-primary hover:text-primary-hover font-medium cursor-pointer">審批詳情頁唯讀展示申請日期(展示樣式)</span></LinkTo></li>
55
55
  </ul>
56
56
  <p className="text-fg-muted mt-3">判斷不確定時:對照 spec.md「何時用 / 何時不用」段;若仍不符,改用近親元件(見下方 vs 近親 段)。</p>
57
57
  </div>
@@ -139,7 +139,7 @@ export const FormattingRule: Story = {
139
139
  <div>
140
140
  <Rule
141
141
  title="格式化跨模式一致 — 預設 YYYY/MM/DD,傳 formatOptions / locale 走 Intl.DateTimeFormat"
142
- note="未傳格式 prop 時預設直接組 YYYY/MM/DD(locale-independent);傳 formatOptions + locale 才啟用 Intl.DateTimeFormat,同時控制 readonly / disabled Display 文字與 edit trigger 顯示文字。跨模式一致、跨頁面可預期。Calendar popup 的月份語言由 Calendar 內部 locale 處理"
142
+ note="未傳格式 prop 時預設直接組 YYYY/MM/DD(locale-independent);傳 formatOptions + locale 才啟用 Intl.DateTimeFormat,同時控制 view / readonly / disabled 的格式化文字與 edit trigger 顯示文字。跨模式一致、跨頁面可預期。Calendar popup 的月份語言由 Calendar 內部 locale 處理"
143
143
  >
144
144
  <DatePicker
145
145
  mode="readonly"
@@ -157,7 +157,7 @@ export const FormattingRule: Story = {
157
157
 
158
158
  <Rule
159
159
  title="Edit trigger 文字也受 formatOptions / locale 控制"
160
- note={'原本原生 <input type="date"> 的 trigger 格式受瀏覽器 locale 控制無法干預;改自建後,edit trigger 顯示的已選日期也走 Intl.DateTimeFormat——跟 Display 模式完全一致'}
160
+ note={'原本原生 <input type="date"> 的 trigger 格式受瀏覽器 locale 控制無法干預;改自建後,edit trigger 顯示的已選日期也走 Intl.DateTimeFormat——跟 view 模式完全一致'}
161
161
  >
162
162
  <DatePicker
163
163
  value="2026-05-15"
@@ -170,7 +170,7 @@ export const FormattingRule: Story = {
170
170
 
171
171
  <Rule
172
172
  title="null 值統一顯示半形連字號"
173
- note="Display 模式 null / undefined 顯示半形 -(foreground,同 readonly value 色),與其他 Field 元件一致"
173
+ note="view 模式 null / undefined 顯示半形 -(foreground,同 readonly value 色),與其他 Field 元件一致"
174
174
  >
175
175
  <DatePicker mode="readonly" value={null} />
176
176
  </Rule>
@@ -68,7 +68,7 @@ open 軸同樣只開最小 API — **uncontrolled-only**:`defaultOpen`(初始開
68
68
  |------|------|------|
69
69
  | 日期範圍(from → to) | **`<DatePicker.Range>`**(本檔下「DatePicker.Range」段,2026-04-21 新增) | 仿 Ant `DatePicker.RangePicker` 架構:雙 input + 箭頭 + 共用 calendar icon,Popover 展開兩月份並列 |
70
70
  | 日期 + 時間(含時分) | **本元件加 `showTime` prop**(canonical 2026-05-02,Ant idiom) | DatePicker `showTime` / DatePickerRange `showTime` 內建 TimeColumns + 此刻/確定 footer;value 變 ISO datetime |
71
- | 相對時間(「3 天前」「昨天」)| 自訂 Display 元件 | DatePicker 的 Display 是絕對日期;相對時間需要計算 + locale 格式化 |
71
+ | 相對時間(「3 天前」「昨天」)| 自訂展示元件 | DatePicker 的 view 態是絕對日期;相對時間需要計算 + locale 格式化 |
72
72
  | 純文字 YYYY-MM-DD(不需要 picker)| `Input` | 如 API debug 介面、不需互動的純記錄 |
73
73
  | 生日等「只有月日、不需要年」的欄位 | 目前用 DatePicker 忍受年份 | 多數情境可接受;要極致可自訂 MonthDayPicker |
74
74
  | Notion / Google 式 event calendar 檢視 | **`<Calendar>`** 元件(見 `../Calendar/calendar.spec.md`,月/週/日 event view);**非本元件語義** | DatePicker 是「選日期」的 form control;Calendar 是「看事件」的頁面 canvas,兩者雖名字都有 calendar 但是不同 DS 元件 |
@@ -232,7 +232,7 @@ DateGrid cell 有 5 種語意視覺,每種用不同形狀/色彩語言避免混
232
232
  - **needConfirm 獨立於 showTime**(2026-07-05 D4 codify):date-only `<DatePicker needConfirm>` 亦成立,footer 渲染 gate = `showTime || needConfirm`(single 與 Range 一致)——needConfirm 時「確定」是唯一 commit 路徑,漏渲 footer = draft 永遠無法 commit 的死路(2026-07-05 修 single 漏 `|| needConfirm`)
233
233
  - showSeconds=false(default)→ TimeColumns 只顯示 H/M(對齊 Ant 預設)
234
234
  - Range cell disable(對齊 Ant `useRangeDisabledDate`):activeEnd='start' + end 已選 → date > end disabled;activeEnd='end' + start 已選 → date < start disabled
235
- - Range stadium pattern(canonical 2026-05-03 v8):rangeStart/End cell pseudo `before:rounded-l-full / rounded-r-full` 跟 button 圓的左/右半弧 EXACTLY OVERLAY → 無「凸出」(對齊 Ant `cell-range-start::before { border-radius: 9999px 0 0 9999px }`)
235
+ - Range stadium pattern(canonical 2026-05-03 v8):SSOT `../DateGrid/date-grid.spec.md`(`range_start` / `range_end` 半圓 stadium 規則;class 細節見 `date-grid.tsx`)
236
236
 
237
237
  ### 為什麼用 prop 而非分離 `<DateTimePicker>` 元件
238
238
 
@@ -258,7 +258,7 @@ DateGrid cell 有 5 種語意視覺,每種用不同形狀/色彩語言避免混
258
258
  | `formatOptions` | `Intl.DateTimeFormatOptions` | `{ year: 'numeric', month: 'short', day: 'numeric' }` |
259
259
  | `locale` | BCP 47 locale | `'zh-TW'`、`'en-US'` |
260
260
 
261
- 預設(未傳 `formatOptions` / `locale`)直接組 `YYYY/MM/DD`(locale-independent,對齊 Ant year-first;見 date-picker.tsx `formatDate` 註解);傳 `formatOptions` / `locale` 才走 `Intl.DateTimeFormat`。Display 模式(readonly / disabled / DataTable cell)與 Edit 模式 trigger 文字同一條格式化路徑,兩者一致。
261
+ 預設(未傳 `formatOptions` / `locale`)直接組 `YYYY/MM/DD`(locale-independent,對齊 Ant year-first;見 date-picker.tsx `formatDate` 註解);傳 `formatOptions` / `locale` 才走 `Intl.DateTimeFormat`。View / readonly / disabled 模式(含 DataTable cell)與 Edit 模式 trigger 文字同一條格式化路徑,兩者一致。
262
262
 
263
263
  ---
264
264
 
@@ -267,7 +267,7 @@ DateGrid cell 有 5 種語意視覺,每種用不同形狀/色彩語言避免混
267
267
  `clearable` prop 在有值時顯示 clear 按鈕(endAction)。
268
268
 
269
269
  - 只在 edit 模式顯示
270
- - 清除後 value 變為 `null`(Display 顯示半形 -,text-foreground)
270
+ - 清除後 `onChange?.('')`(空字串 = 空值;view 態顯示半形 -,text-foreground)
271
271
  - **Dual-state sync canonical**(2026-05-03 v10):X 點擊必同時 `onChange?.('')` + `setDraft(null)`(Range 同),否則 `needConfirm=true`(showTime 預設)且 popover 開著時 `displayValue=draft` 仍顯示舊值,trigger 看起來「沒清」。X 在 trigger 上是 standard clear affordance,不走 needConfirm「等確定」語義 — 立刻 commit + 同步 draft
272
272
 
273
273
  ---
@@ -284,16 +284,16 @@ DateGrid cell 有 5 種語意視覺,每種用不同形狀/色彩語言避免混
284
284
 
285
285
  DatePicker 套 `React.forwardRef` + `displayName`;`DatePickerProps` extends `Omit<React.HTMLAttributes<HTMLDivElement>, 'value' | 'onChange' | 'placeholder' | 'defaultValue'>`,剩餘 DOM attrs `...props` spread 到**當前 mode 的 root wrapper**(edit trigger `<div role="combobox">` / readonly · disabled wrapper div / Range wrapper div)。
286
286
 
287
- **例外**:`mode="display"` 預設(未 opt-in `showDisplayEndIcon`)輸出裸 `<span>`,**不** spread `...props`——consumer 傳 DOM attrs(`data-testid` / `onFocus` 等)時注意 display 模式不生效;`className` 各 mode 皆顯式接收(套在該 mode 的 root 元素)。
287
+ **例外**:`mode="view"` 預設(未 opt-in `showDisplayEndIcon`)輸出裸 `<span>`,**不** spread `...props`——consumer 傳 DOM attrs(`data-testid` / `onFocus` 等)時注意 view 模式不生效;`className` 各 mode 皆顯式接收(套在該 mode 的 root 元素)。
288
288
 
289
- **`asChild` 不支援**:trigger 是 compound(display 裸 span / edit `div role="combobox"` 不同 render tree),無單一 Slot 目標。consumer 若要自訂 trigger 視覺,改用 `<DatePicker mode="display">` + 自家 Button composition。
289
+ **`asChild` 不支援**:trigger 是 compound(view 裸 span / edit `div role="combobox"` 不同 render tree),無單一 Slot 目標。consumer 若要自訂 trigger 視覺,改用 `<DatePicker mode="view">` + 自家 Button composition。
290
290
 
291
291
  ---
292
292
 
293
293
  ## A11y 預設
294
294
 
295
295
  - Trigger:`role="combobox"` + `aria-haspopup="dialog"` + `aria-expanded={open}` + 必含 accessible name(`aria-label` / 或外層 `<label>` / 或 fieldCtx label)
296
- - Popover content:`role="dialog"`;單一日期 popover 不重覆 `aria-label`(由 trigger 的 `role="combobox"` accessible name 標示),Range popover 加 `aria-label="日期區間選擇"`
296
+ - Popover content:`role="dialog"`;單一日期 popover PopoverContent 帶 `aria-label="日期選擇"`(date-picker.tsx:650,DS default dialog label),Range popover 加 `aria-label="日期區間選擇"`
297
297
  - DateGrid 鍵盤:Arrow keys 切日 / PageUp/Down 切月 / Home/End 行首尾(react-day-picker v9 內建)
298
298
  - Trigger 鍵盤(Space / Enter open;Esc close + 回焦):單一 DatePicker 的 `<div role="combobox">` 無 native Enter/Space→click,由元件**自建 `onKeyDown`** 開 popover(Radix PopoverTrigger 只 compose onClick;date-picker.tsx:554),Esc 關閉後靠 PopoverTrigger 的 Radix **內建** `triggerRef.focus()` 回焦;Range 用 native `<button>` onClick 開、只掛 PopoverAnchor(triggerRef 恆 null → 內建回焦 no-op),改由**自建 `onCloseAutoFocus`** 手動回焦 active 端 button(date-picker.tsx:1020-1026,守 WCAG 2.4.3)
299
299
  - Range 雙 trigger:`activeEnd` state 指向當前編輯端,`aria-expanded` 對應只當該 trigger active 時 true
@@ -311,11 +311,11 @@ DatePicker 套 `React.forwardRef` + `displayName`;`DatePickerProps` extends `Omi
311
311
 
312
312
  ## 邊界案例
313
313
 
314
- - **Disabled**:Field SSOT own;resolvedMode='disabled' 走 readonly / disabled 純 wrapper 分支(無 Popover trigger、`aria-disabled`、不開 picker),文字與 Calendar icon 切 `text-fg-disabled`。readonly 不顯示 Calendar icon(類型身份 indicator 規則,SSOT field-controls.spec.md L227);disabled 保留並切 `fg-disabled`。顯式 `mode="display"` 永遠最優先(useResolvedFieldMode step 1,見 field-context.ts):display + disabled 同傳走 display 分支不套 disabled token;要 disabled chrome 傳 `disabled` 或 `mode="disabled"`。
314
+ - **Disabled**:Field SSOT own;resolvedMode='disabled' 走 readonly / disabled 純 wrapper 分支(無 Popover trigger、`aria-disabled`、不開 picker),文字與 Calendar icon 切 `text-fg-disabled`。readonly 不顯示 Calendar icon(類型身份 indicator 規則,SSOT field-controls.spec.md「下拉箭頭與類型身份 indicator」段 L266-276);disabled 保留並切 `fg-disabled`。顯式 `mode="view"` 永遠最優先(useResolvedFieldMode step 1,見 field-context.ts):view + disabled 同傳走 view 分支不套 disabled token;要 disabled chrome 傳 `disabled` 或 `mode="disabled"`。
315
315
  - **Loading(server-rendered grid)**:DatePicker 為 sync UI 不獨立 own loading。若 consumer 場景需 async date constraint fetch(如後端 disabled-dates list),consumer 應先 disable trigger 直到 fetch 完成,或在 popover 開啟後 body 切 `<Empty icon={<CircularProgress/>}/>`(對齊 panel-body loading SSOT)。本 spec scope 內不渲 loading state。
316
316
  - **Empty(no value)**:`value=null` → trigger 顯 placeholder(預設 `YYYY/MM/DD`,showTime 時 `YYYY/MM/DD HH:MM`;consumer 可傳 `placeholder` 覆寫)。無導覽目標時鍵盤焦點停留(react-day-picker v9 內建)。
317
317
  - **Invalid date input**:Field validation 處理 `aria-invalid="true"` + error border + 下方 error message;DatePicker 本身不 own validation 規則。
318
- - **極長格式化日期**:trigger 文字單行 `truncate`(ellipsis),不換行不撐高(Display / Edit / typeable / Range 雙 input 皆同)。
318
+ - **極長格式化日期**:trigger 文字單行 `truncate`(ellipsis),不換行不撐高(View / Edit / typeable / Range 雙 input 皆同)。
319
319
  - **RTL**:未實作方向鏡像(trigger / Range 雙 input / DateGrid 皆以 LTR physical 方向設計);RTL 屬 DS-wide 決策,未定(與 Chip / Breadcrumb 同口徑)。
320
320
  - **Dark mode / density**:走 Field + Popover SSOT 自動 adapt;DateGrid 內 cell 尺寸 density-aware(消費 `--field-height-sm`:md=28×28 / lg=32×32,對齊 L128 + `date-grid.spec.md:120`),隨 density 縮放而非固定。
321
321
 
@@ -76,8 +76,8 @@ export const Modes: Story = {
76
76
  </div>
77
77
  {/* @story-trait-rationale: pre-existing trait gaps tracked separately */}
78
78
  <div>
79
- <h3 className="text-body font-bold text-foreground mb-2">display</h3>
80
- <DatePicker mode="display" value="2026-04-02" />
79
+ <h3 className="text-body font-bold text-foreground mb-2">view</h3>
80
+ <DatePicker mode="view" value="2026-04-02" />
81
81
  </div>
82
82
  <div>
83
83
  <h3 className="text-body font-bold text-foreground mb-2">readonly</h3>
@@ -315,26 +315,26 @@ export const ShowTimeRange: Story = {
315
315
  },
316
316
  }
317
317
 
318
- /* ── Display(DataTable cell 用)── */
319
- export const Display: Story = {
320
- name: '展示樣式',
318
+ /* ── View(DataTable cell 用)── */
319
+ export const View: Story = {
320
+ name: '檢視樣式',
321
321
  render: () => (
322
322
  <div className="flex flex-col gap-3">
323
323
  <div className="flex items-center gap-3">
324
324
  <span className="text-caption text-fg-muted w-20">預設</span>
325
- <DatePicker mode="display" value="2026-04-02" />
325
+ <DatePicker mode="view" value="2026-04-02" />
326
326
  </div>
327
327
  <div className="flex items-center gap-3">
328
328
  <span className="text-caption text-fg-muted w-20">完整月份</span>
329
- <DatePicker mode="display" value="2026-04-02" formatOptions={{ year: 'numeric', month: 'long', day: 'numeric' }} />
329
+ <DatePicker mode="view" value="2026-04-02" formatOptions={{ year: 'numeric', month: 'long', day: 'numeric' }} />
330
330
  </div>
331
331
  <div className="flex items-center gap-3">
332
332
  <span className="text-caption text-fg-muted w-20">zh-TW</span>
333
- <DatePicker mode="display" value="2026-04-02" locale="zh-TW" formatOptions={{ year: 'numeric', month: 'long', day: 'numeric' }} />
333
+ <DatePicker mode="view" value="2026-04-02" locale="zh-TW" formatOptions={{ year: 'numeric', month: 'long', day: 'numeric' }} />
334
334
  </div>
335
335
  <div className="flex items-center gap-3">
336
336
  <span className="text-caption text-fg-muted w-20">null</span>
337
- <DatePicker mode="display" value={null} />
337
+ <DatePicker mode="view" value={null} />
338
338
  </div>
339
339
  </div>
340
340
  ),
@@ -328,9 +328,9 @@ export interface DatePickerProps
328
328
  */
329
329
  needConfirm?: boolean
330
330
  /**
331
- * Display 是否渲 Calendar icon + Field naked wrapper(D-path opt-in,2026-05-08)
332
- * — DataTable cell display↔edit 像素級對齊用。預設 false(裸 span,backward compat)。
333
- * 設 true 時 display 走 fieldWrapperStyles(naked variant)+ ItemSuffix CalendarIcon,
331
+ * View 態是否渲 Calendar icon + Field naked wrapper(D-path opt-in,2026-05-08)
332
+ * — DataTable cell view↔edit 像素級對齊用。預設 false(裸 span,backward compat)。
333
+ * 設 true 時 view 走 fieldWrapperStyles(naked variant)+ ItemSuffix CalendarIcon,
334
334
  * 與 edit 同 DOM 結構,消除 Layer-B padding mismatch。
335
335
  */
336
336
  showDisplayEndIcon?: boolean
@@ -409,7 +409,7 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
409
409
  const size = useResolvedFieldSize(sizeProp) // B 組 cascade fix:<Field size>/cell surface-size 對 DatePicker 生效
410
410
  const error = useResolvedFieldInvalid(errorProp)
411
411
  const disabled = useResolvedFieldDisabled(disabledProp)
412
- // 2026-06-08 SSOT:mode 經 useResolvedFieldMode;修 <Field mode="display"> 漏 cascade
412
+ // 2026-06-08 SSOT:mode 經 useResolvedFieldMode;修 <Field mode="view"> 漏 cascade
413
413
  const resolvedMode = useResolvedFieldMode({ mode, disabled })
414
414
  const emptyDisplay = useFieldEmptyDisplay()
415
415
  const variant: FieldVariantInternal = useResolvedFieldVariant(variantProp)
@@ -475,21 +475,21 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
475
475
  }
476
476
  }, [onChange, showTime])
477
477
 
478
- // mode='display'(Phase B2 2026-05-05):純內容輸出 — 對齊原 DatePickerDisplay sub-component(retired)。
478
+ // mode='view'(Phase B2 2026-05-05):純內容輸出 — 對齊原 DatePickerDisplay sub-component(retired)。
479
479
  // Default(showDisplayEndIcon=false):無 Field wrapper / 無 Calendar icon — backward compat 裸 span。
480
480
  // Opt-in(showDisplayEndIcon=true,2026-05-08 D-path):Field naked wrapper + ItemSuffix Calendar,
481
- // 與 edit 同結構消除 cell display↔edit 像素偏移(Layer-B padding mismatch)。
482
- if (resolvedMode === 'display') {
481
+ // 與 edit 同結構消除 cell view↔edit 像素偏移(Layer-B padding mismatch)。
482
+ if (resolvedMode === 'view') {
483
483
  if (!showDisplayEndIcon) {
484
- // 2026-05-14 I2 fix(spec contract (e) display typography canonical):bare span 套
484
+ // 2026-05-14 I2 fix(spec contract (e) view typography canonical):bare span 套
485
485
  // `fieldDisplayTextClass(size)`(sm/md→text-body,lg→text-body-lg)— 對齊 Field family 統一。
486
486
  if (!value) return <span className={cn(fieldDisplayTextClass(size), fieldEmptyColorClass(resolvedMode), className)}>{emptyDisplay}</span>
487
487
  return <span className={cn(fieldDisplayTextClass(size), 'truncate', className)}>{displayCommitted}</span>
488
488
  }
489
489
  return (
490
490
  <div
491
- className={cn(fieldWrapperStyles({ mode: 'display', variant, width, size }), className)}
492
- data-field-mode="display"
491
+ className={cn(fieldWrapperStyles({ mode: 'view', variant, width, size }), className)}
492
+ data-field-mode="view"
493
493
  >
494
494
  <span className={cn(bareInputStyles, 'flex-1 min-w-0 truncate', !value && fieldEmptyColorClass(resolvedMode))}>
495
495
  {value ? displayCommitted : emptyDisplay}
@@ -801,7 +801,7 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
801
801
  const size = useResolvedFieldSize(sizeProp) // B 組 cascade fix:<Field size>/cell surface-size 對 DatePicker 生效
802
802
  const error = useResolvedFieldInvalid(errorProp)
803
803
  const disabled = useResolvedFieldDisabled(disabledProp)
804
- // 2026-06-08 SSOT:mode 經 useResolvedFieldMode;修 <Field mode="display"> 漏 cascade
804
+ // 2026-06-08 SSOT:mode 經 useResolvedFieldMode;修 <Field mode="view"> 漏 cascade
805
805
  const resolvedMode = useResolvedFieldMode({ mode, disabled })
806
806
  const emptyDisplay = useFieldEmptyDisplay()
807
807
  const variant: FieldVariantInternal = useResolvedFieldVariant(variantProp)
@@ -936,8 +936,8 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
936
936
  return false
937
937
  }, [activeEnd, startDate, endDate])
938
938
 
939
- // mode='display'(Phase B2 2026-05-05):純內容輸出 — 無 Field wrapper / 無 Calendar icon。
940
- if (resolvedMode === 'display') {
939
+ // mode='view'(Phase B2 2026-05-05):純內容輸出 — 無 Field wrapper / 無 Calendar icon。
940
+ if (resolvedMode === 'view') {
941
941
  const hasAny = !!(startIso || endIso)
942
942
  if (!hasAny) return <span className={cn(fieldEmptyColorClass(resolvedMode), className)}>{emptyDisplay}</span>
943
943
  return (
@@ -5,7 +5,7 @@
5
5
  // foreground(value),無 variant × state 色彩矩陣。色彩 token 已於
6
6
  // Overview「Typography(閱讀模式)」段列出。
7
7
  // SizeMatrix N/A — 不提供 size prop;大小固定 text-body(14px reading mode),
8
- // 由 layout(cols / direction / divided)而非 size 決定差異。ColsMatrix 已
8
+ // 由 layout(cols / orientation / divided)而非 size 決定差異。ColsMatrix 已
9
9
  // 涵蓋 layout 變化。
10
10
  import type { Meta, StoryObj } from '@storybook/react'
11
11
  import { DescriptionList, DescriptionItem } from './description-list'
@@ -54,7 +54,7 @@ export const Overview: Story = {
54
54
  <Desc>items 之間垂直間距走 `--layout-space-tight` token(density-aware)——切 density 自動適配,避免硬寫 px / py-N 脫鉤 token;label → value(同 item 內)走 `--item-gap-label-desc-reading`(2px,見下表 row 1)。</Desc>
55
55
  <div className="overflow-x-auto">
56
56
  <table className="text-caption border-collapse">
57
- <thead><tr><Th>Direction</Th><Th>位置</Th><Th>Value</Th><Th>Rationale</Th></tr></thead>
57
+ <thead><tr><Th>Orientation</Th><Th>位置</Th><Th>Value</Th><Th>Rationale</Th></tr></thead>
58
58
  <tbody>
59
59
  <tr><Td mono>vertical</Td><Td>label → value(同 item 內)</Td><Td mono>--item-gap-label-desc-reading(2px)</Td><Td>極小間距,視覺上 label 與 value 緊密配對(dt body + dd body → reading token)</Td></tr>
60
60
  <tr><Td mono>vertical</Td><Td>items 之間垂直 gap</Td><Td mono>gap-y-[var(--layout-space-tight)]</Td><Td>density-aware;Gestalt proximity 群組</Td></tr>
@@ -73,16 +73,16 @@ export const Overview: Story = {
73
73
  export const Inspector: Story = {
74
74
  name: '元件檢閱器',
75
75
  parameters: {
76
- docs: { description: { story: '右側 Controls 切 props 即時 render,取代 Figma inspect。調整 `cols` / `direction` / `divided` 看 CSS grid 配置變化。' } },
76
+ docs: { description: { story: '右側 Controls 切 props 即時 render,取代 Figma inspect。調整 `cols` / `orientation` / `divided` 看 CSS grid 配置變化。' } },
77
77
  },
78
78
  args: {
79
79
  cols: 2,
80
- direction: 'vertical',
80
+ orientation: 'vertical',
81
81
  divided: false,
82
82
  },
83
83
  argTypes: {
84
84
  cols: { control: 'radio', options: [1, 2, 3] },
85
- direction: { control: 'radio', options: ['vertical', 'horizontal'] },
85
+ orientation: { control: 'radio', options: ['vertical', 'horizontal'] },
86
86
  divided: { control: 'boolean', description: 'horizontal 模式下,每個 item 下加 border-b 對齊 rows(長列表建議開)' },
87
87
  },
88
88
  render: (args) => (
@@ -197,7 +197,7 @@ export const LabelAlignmentRule: Story = {
197
197
  <div>
198
198
  <Rule
199
199
  title="本系統採 stacked(label 在上、value 在下)— label 左對齊"
200
- note="對齊 Atlassian / Shopify Polaris / Stripe 慣例——label 與 value 垂直堆疊,兩者都左對齊。閱讀節奏由上往下、由左往右,不需視線左右跳動。這是 vertical(預設)模式的結構;label 左 / value 右的 metadata 列改用既有 `direction=&quot;horizontal&quot;` prop(見 spec「Direction」段)"
200
+ note="對齊 Atlassian / Shopify Polaris / Stripe 慣例——label 與 value 垂直堆疊,兩者都左對齊。閱讀節奏由上往下、由左往右,不需視線左右跳動。這是 vertical(預設)模式的結構;label 左 / value 右的 metadata 列改用既有 `orientation=&quot;horizontal&quot;` prop(見 spec「Orientation」段)"
201
201
  >
202
202
  <Frame className="max-w-md">
203
203
  <DescriptionList cols={2}>
@@ -225,7 +225,7 @@ export const LabelAlignmentRule: Story = {
225
225
 
226
226
  <Rule
227
227
  title="❌ 不要自己用 flex 改 horizontal layout"
228
- note="手刻 flex 模擬 label 左 / value 右 → 失去 dl/dt/dd 語意,且多欄配置下 grid 對齊錯亂。有此需求 → 用既有 `direction=&quot;horizontal&quot;` prop(dl/dt/dd 語意完整保留,見 showcase「水平佈局」story),不要自組 layout"
228
+ note="手刻 flex 模擬 label 左 / value 右 → 失去 dl/dt/dd 語意,且多欄配置下 grid 對齊錯亂。有此需求 → 用既有 `orientation=&quot;horizontal&quot;` prop(dl/dt/dd 語意完整保留,見 showcase「水平佈局」story),不要自組 layout"
229
229
  >
230
230
  <Frame className="max-w-md">
231
231
  <div className="flex justify-between py-1">
@@ -44,11 +44,11 @@ benchmark:
44
44
  ## 結構
45
45
 
46
46
  - `DescriptionList`:外層 `dl`,vertical 模式為 CSS grid、horizontal 模式為 flex column
47
- - `DescriptionItem`:一組 `dt`(label)+ `dd`(value),透過 context 知道當前 direction 自動切 layout
47
+ - `DescriptionItem`:一組 `dt`(label)+ `dd`(value),透過 context 知道當前 orientation 自動切 layout
48
48
 
49
- ## Direction(2026-04-20 新增)
49
+ ## Orientation(2026-04-20 新增)
50
50
 
51
- | direction | Layout | 典型情境 | 世界級對照 |
51
+ | orientation | Layout | 典型情境 | 世界級對照 |
52
52
  |-----------|--------|---------|-----------|
53
53
  | `vertical`(預設)| label 在上 / value 在下 | ProfileCard detail、sidebar 長 value(地址、bio) | Atlassian DescriptionList、Polaris DescriptionList |
54
54
  | `horizontal` | label 左 / value 右對齊 | **file info panel / 訂單詳情 / settings summary**(短 value 的 metadata 列) | Google Drive file info、Notion file panel、iOS Settings | <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
@@ -63,13 +63,13 @@ benchmark:
63
63
 
64
64
  ```tsx
65
65
  // 短 metadata 列,無需 divider
66
- <DescriptionList direction="horizontal">
66
+ <DescriptionList orientation="horizontal">
67
67
  <DescriptionItem label="建立">2026-04-20</DescriptionItem>
68
68
  <DescriptionItem label="修改">2026-04-20</DescriptionItem>
69
69
  </DescriptionList>
70
70
 
71
71
  // 檔案資訊 — 多 row + key 長度不一 → divided 對齊格線
72
- <DescriptionList direction="horizontal" divided>
72
+ <DescriptionList orientation="horizontal" divided>
73
73
  <DescriptionItem label="檔名">Q1 財報分析.xlsx</DescriptionItem>
74
74
  <DescriptionItem label="類型">application/vnd.xlsx</DescriptionItem>
75
75
  <DescriptionItem label="大小">1.2 MB</DescriptionItem>
@@ -86,18 +86,18 @@ benchmark:
86
86
 
87
87
  ## 間距
88
88
 
89
- ### Vertical direction
89
+ ### Vertical orientation
90
90
 
91
91
  - **label → value**(同 item 內):`--item-gap-label-desc-reading` token(2px)——極小間距,視覺上 label 與 value 緊密配對
92
92
  - **items 之間垂直 gap**:`gap-y-[var(--layout-space-tight)]`——density-aware,跟隨系統密度設定
93
93
  - **columns 之間水平 gap**:`gap-x-4`(16px)
94
94
 
95
- ### Horizontal direction(divided=false)
95
+ ### Horizontal orientation(divided=false)
96
96
 
97
97
  - **items 之間垂直 gap**:`mb-[var(--layout-space-tight)]` per item(last:mb-0)——density-aware,等同 vertical 的 items gap
98
98
  - label ↔ value 水平距離:`justify-between` + `gap-4`(最小 16px,content 之間拉開)
99
99
 
100
- ### Horizontal direction(divided=true)
100
+ ### Horizontal orientation(divided=true)
101
101
 
102
102
  - 每個 item `py-[var(--layout-space-tight)]`(density-aware,形成 cell-like row 高度)
103
103
  - 每個 item 底部 `border-b border-divider`,`last:border-b-0`——row 之間視覺格線,key 長度不一時易於對齊掃描
@@ -106,9 +106,9 @@ benchmark:
106
106
 
107
107
  ## Props
108
108
 
109
- ### `direction`:vertical / horizontal
109
+ ### `orientation`:vertical / horizontal
110
110
 
111
- 見上「Direction」段。
111
+ 見上「Orientation」段。
112
112
 
113
113
  ### `divided`:horizontal 專用 row divider
114
114
 
@@ -184,11 +184,11 @@ consumer 要在 DL 上方加 section heading(「基本資料」/「團隊資訊
184
184
 
185
185
  DescriptionList 是**唯讀 label / value 資料呈現**(非互動 / 非 variant 驅動):
186
186
 
187
- - **有 Inspector**:DL 雖唯讀,但有 layout prop 可即時切換——`Inspector` story 暴露 `cols`(1 / 2 / 3)/ `direction`(vertical / horizontal)/ `divided` 三個 prop 的 Controls,取代 Figma inspect。`direction` 與 `divided` 是 `ColsMatrix`(只示範 cols)沒涵蓋的維度。
187
+ - **有 Inspector**:DL 雖唯讀,但有 layout prop 可即時切換——`Inspector` story 暴露 `cols`(1 / 2 / 3)/ `orientation`(vertical / horizontal)/ `divided` 三個 prop 的 Controls,取代 Figma inspect。`orientation` 與 `divided` 是 `ColsMatrix`(只示範 cols)沒涵蓋的維度。
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` / `orientation` / `divided`) + `ColsMatrix`(元件特有 1 / 2 / 3 欄對照) + `StateBehavior`(空值 `-` / 長值 / 多行 / ReactNode value) + `Accessibility`(`dl/dt/dd` 語意 + 無互動說明)。
192
192
 
193
193
  ---
194
194
 
@@ -89,14 +89,14 @@ export const DetailPanel: Story = {
89
89
  ),
90
90
  }
91
91
 
92
- /* ── Horizontal direction(label 左 / value 右,divided=false)──────── */
92
+ /* ── Horizontal orientation(label 左 / value 右,divided=false)──────── */
93
93
  export const Horizontal: Story = {
94
94
  name: '水平佈局',
95
95
  render: () => (
96
96
  <div className="border border-border rounded-lg p-[var(--layout-space-loose)] max-w-md">
97
97
  {/* title 到第一個 item 的間距 = item 之間間距(Gestalt proximity canonical,見 spec) */}
98
98
  <div className="text-body font-medium mb-[var(--layout-space-tight)]">檔案資訊</div>
99
- <DescriptionList direction="horizontal">
99
+ <DescriptionList orientation="horizontal">
100
100
  <DescriptionItem label="檔名">Q1-roadmap.pdf</DescriptionItem>
101
101
  <DescriptionItem label="類型">application/pdf</DescriptionItem>
102
102
  <DescriptionItem label="大小">2.4 MB</DescriptionItem>
@@ -107,7 +107,7 @@ export const Horizontal: Story = {
107
107
  }
108
108
 
109
109
  // @story-trait-rationale: HorizontalDivided retired 2026-05-17 per audit Dim 24/25 strict re-run —
110
- // 違 story-rules.md L42「同 affordance 內 prop variations 用 Controls 不另開」。Horizontal direction
110
+ // 違 story-rules.md L42「同 affordance 內 prop variations 用 Controls 不另開」。Horizontal orientation
111
111
  // 已展示;divided 是單一 prop toggle,anatomy Inspector 已 expose Controls (L85-86)。
112
112
  // 原本內容 archive 於 git history(若要看 divided 視覺,進 anatomy Inspector 開 divided=true)。
113
113
  // 2026-06-12:刪除 zombie export _RETIRED_HorizontalDivided,對齊 DS-wide comment-only 退役慣例(deep-audit dim25)。
@@ -12,7 +12,7 @@ import { cn } from '@/lib/utils'
12
12
  * value (dd): text-body (14px) text-foreground (neutral-9)
13
13
  * 兩者都是 14px × 1.5 行高——層級靠色彩區分,不靠字體大小。
14
14
  *
15
- * ── direction(2026-04-20 新增)──
15
+ * ── orientation(2026-04-20 新增)──
16
16
  * vertical(預設):label 在上 / value 在下,適合長 value(地址、bio、說明段落)、
17
17
  * form-like 資訊展示
18
18
  * horizontal :label 左 / value 右對齊,適合短 value 的 metadata 列
@@ -30,15 +30,15 @@ import { cn } from '@/lib/utils'
30
30
  * divided horizontal 模式:每 item py-[var(--layout-space-tight)](cell-like row 高度)
31
31
  */
32
32
 
33
- export type DescriptionDirection = 'vertical' | 'horizontal'
33
+ export type DescriptionListOrientation = 'vertical' | 'horizontal'
34
34
 
35
35
  interface DescriptionContextValue {
36
- direction: DescriptionDirection
36
+ orientation: DescriptionListOrientation
37
37
  divided: boolean
38
38
  }
39
39
 
40
40
  const DescriptionContext = React.createContext<DescriptionContextValue>({
41
- direction: 'vertical',
41
+ orientation: 'vertical',
42
42
  divided: false,
43
43
  })
44
44
 
@@ -46,7 +46,7 @@ export interface DescriptionListProps extends React.HTMLAttributes<HTMLDListElem
46
46
  /** grid 欄數(vertical 才生效;horizontal 永遠單欄),預設 1 */
47
47
  cols?: 1 | 2 | 3
48
48
  /** 項目排列方向,預設 vertical(label 在上 / value 在下) */
49
- direction?: DescriptionDirection
49
+ orientation?: DescriptionListOrientation
50
50
  /**
51
51
  * horizontal 模式下每個 item 下方加分隔線以對齊 rows。預設 false。
52
52
  * 短列表(< 4 rows)不需要;檔案 metadata 等長列表、key 長度不一時建議開。
@@ -61,10 +61,10 @@ const colsClass: Record<number, string> = {
61
61
  }
62
62
 
63
63
  const DescriptionList = React.forwardRef<HTMLDListElement, DescriptionListProps>(
64
- ({ cols = 1, direction = 'vertical', divided = false, className, ...props }, ref) => {
65
- const isHorizontal = direction === 'horizontal'
64
+ ({ cols = 1, orientation = 'vertical', divided = false, className, ...props }, ref) => {
65
+ const isHorizontal = orientation === 'horizontal'
66
66
  // Memoize provider value(2026-04-22 D3 perf audit):避免每 render 重建 2-field object
67
- const ctxValue = React.useMemo(() => ({ direction, divided }), [direction, divided])
67
+ const ctxValue = React.useMemo(() => ({ orientation, divided }), [orientation, divided])
68
68
  return (
69
69
  <DescriptionContext.Provider value={ctxValue}>
70
70
  <dl
@@ -90,8 +90,8 @@ export interface DescriptionItemProps extends React.HTMLAttributes<HTMLDivElemen
90
90
 
91
91
  const DescriptionItem = React.forwardRef<HTMLDivElement, DescriptionItemProps>(
92
92
  ({ label, children, className, ...props }, ref) => {
93
- const { direction, divided } = React.useContext(DescriptionContext)
94
- if (direction === 'horizontal') {
93
+ const { orientation, divided } = React.useContext(DescriptionContext)
94
+ if (orientation === 'horizontal') {
95
95
  return (
96
96
  <div
97
97
  ref={ref}
@@ -52,7 +52,10 @@ const DialogOverlay = React.forwardRef<
52
52
  ))
53
53
  DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
54
54
 
55
- interface DialogContentProps extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> {
55
+ // asChild Omit(2026-07-18 決策2):DialogContent 是固定 surface chrome(overlay + 定位 +
56
+ // bg/rounded/shadow + onOpenAutoFocus),恆渲染 {children}(consumer body,通常 Header+Body+Footer
57
+ // 多節點)→ <Content asChild> Radix Slot React.Children.only crash。children 保留(consumer body)。
58
+ interface DialogContentProps extends Omit<React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>, 'asChild'> {
56
59
  /** 最大寬度。預設 512px。傳 number 視為 px。 */
57
60
  maxWidth?: string | number
58
61
  /**