@qijenchen/design-system 0.1.0-beta.145 → 0.1.0-beta.147

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 (576) hide show
  1. package/dist/components/Accordion/accordion.d.ts +1 -1
  2. package/dist/components/Accordion/accordion.d.ts.map +1 -1
  3. package/dist/components/Accordion/accordion.js +8 -3
  4. package/dist/components/Accordion/accordion.js.map +1 -1
  5. package/dist/components/AccountMenu/account-menu.d.ts.map +1 -1
  6. package/dist/components/AccountMenu/account-menu.js.map +1 -1
  7. package/dist/components/AgentPanel/agent-panel-fab.d.ts +7 -1
  8. package/dist/components/AgentPanel/agent-panel-fab.d.ts.map +1 -1
  9. package/dist/components/AgentPanel/agent-panel-fab.js +36 -14
  10. package/dist/components/AgentPanel/agent-panel-fab.js.map +1 -1
  11. package/dist/components/AgentPanel/agent-panel-logo.d.ts +3 -3
  12. package/dist/components/AgentPanel/agent-panel-logo.js.map +1 -1
  13. package/dist/components/AgentPanel/agent-panel.d.ts +1 -1
  14. package/dist/components/AgentPanel/agent-panel.d.ts.map +1 -1
  15. package/dist/components/AgentPanel/agent-panel.js +28 -22
  16. package/dist/components/AgentPanel/agent-panel.js.map +1 -1
  17. package/dist/components/AppShell/app-shell.d.ts +1 -1
  18. package/dist/components/AppShell/app-shell.js +1 -1
  19. package/dist/components/AppShell/app-shell.js.map +1 -1
  20. package/dist/components/Avatar/avatar.d.ts +95 -1
  21. package/dist/components/Avatar/avatar.d.ts.map +1 -1
  22. package/dist/components/Avatar/avatar.js +106 -15
  23. package/dist/components/Avatar/avatar.js.map +1 -1
  24. package/dist/components/Avatar/index.js +14 -2
  25. package/dist/components/Breadcrumb/breadcrumb.d.ts +4 -2
  26. package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -1
  27. package/dist/components/Breadcrumb/breadcrumb.js +2 -2
  28. package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
  29. package/dist/components/BulkActionBar/bulk-action-bar.d.ts.map +1 -1
  30. package/dist/components/BulkActionBar/bulk-action-bar.js +27 -2
  31. package/dist/components/BulkActionBar/bulk-action-bar.js.map +1 -1
  32. package/dist/components/Button/button.d.ts +2 -2
  33. package/dist/components/Button/button.d.ts.map +1 -1
  34. package/dist/components/Button/button.js +118 -22
  35. package/dist/components/Button/button.js.map +1 -1
  36. package/dist/components/Calendar/calendar.d.ts +34 -10
  37. package/dist/components/Calendar/calendar.d.ts.map +1 -1
  38. package/dist/components/Calendar/calendar.js +210 -36
  39. package/dist/components/Calendar/calendar.js.map +1 -1
  40. package/dist/components/Carousel/carousel.d.ts +1 -1
  41. package/dist/components/Carousel/carousel.d.ts.map +1 -1
  42. package/dist/components/Carousel/carousel.js +3 -2
  43. package/dist/components/Carousel/carousel.js.map +1 -1
  44. package/dist/components/Chart/chart.d.ts +1 -0
  45. package/dist/components/Chart/chart.d.ts.map +1 -1
  46. package/dist/components/Chart/chart.js +8 -0
  47. package/dist/components/Chart/chart.js.map +1 -1
  48. package/dist/components/Checkbox/checkbox.d.ts +1 -1
  49. package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
  50. package/dist/components/Checkbox/checkbox.js +10 -2
  51. package/dist/components/Checkbox/checkbox.js.map +1 -1
  52. package/dist/components/Chip/chip.d.ts +1 -1
  53. package/dist/components/Chip/chip.d.ts.map +1 -1
  54. package/dist/components/Chip/chip.js +4 -2
  55. package/dist/components/Chip/chip.js.map +1 -1
  56. package/dist/components/Combobox/combobox.d.ts +1 -1
  57. package/dist/components/Combobox/combobox.d.ts.map +1 -1
  58. package/dist/components/Combobox/combobox.js +37 -11
  59. package/dist/components/Combobox/combobox.js.map +1 -1
  60. package/dist/components/Command/command.d.ts +1 -1
  61. package/dist/components/Command/command.d.ts.map +1 -1
  62. package/dist/components/Command/command.js +106 -8
  63. package/dist/components/Command/command.js.map +1 -1
  64. package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
  65. package/dist/components/DataTable/cell-registry.js +3 -2
  66. package/dist/components/DataTable/cell-registry.js.map +1 -1
  67. package/dist/components/DataTable/data-table-column-visibility-panel.d.ts.map +1 -1
  68. package/dist/components/DataTable/data-table-column-visibility-panel.js +24 -24
  69. package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -1
  70. package/dist/components/DataTable/data-table-interaction-layer.d.ts +2 -1
  71. package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
  72. package/dist/components/DataTable/data-table-interaction-layer.js +3 -4
  73. package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
  74. package/dist/components/DataTable/data-table-sort-manager.d.ts.map +1 -1
  75. package/dist/components/DataTable/data-table-sort-manager.js +20 -20
  76. package/dist/components/DataTable/data-table-sort-manager.js.map +1 -1
  77. package/dist/components/DataTable/data-table.d.ts +8 -5
  78. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  79. package/dist/components/DataTable/data-table.js +197 -71
  80. package/dist/components/DataTable/data-table.js.map +1 -1
  81. package/dist/components/DateGrid/date-grid.d.ts +1 -1
  82. package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
  83. package/dist/components/DateGrid/date-grid.js +358 -225
  84. package/dist/components/DateGrid/date-grid.js.map +1 -1
  85. package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
  86. package/dist/components/DatePicker/date-picker.js +16 -1
  87. package/dist/components/DatePicker/date-picker.js.map +1 -1
  88. package/dist/components/Dialog/dialog.d.ts.map +1 -1
  89. package/dist/components/Dialog/dialog.js +55 -43
  90. package/dist/components/Dialog/dialog.js.map +1 -1
  91. package/dist/components/DropdownMenu/dropdown-menu-keyboard.d.ts +86 -0
  92. package/dist/components/DropdownMenu/dropdown-menu-keyboard.d.ts.map +1 -0
  93. package/dist/components/DropdownMenu/dropdown-menu-keyboard.js +172 -0
  94. package/dist/components/DropdownMenu/dropdown-menu-keyboard.js.map +1 -0
  95. package/dist/components/DropdownMenu/dropdown-menu.d.ts +6 -1
  96. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  97. package/dist/components/DropdownMenu/dropdown-menu.js +50 -39
  98. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  99. package/dist/components/Field/field-context.d.ts +4 -0
  100. package/dist/components/Field/field-context.d.ts.map +1 -1
  101. package/dist/components/Field/field-context.js +1 -2
  102. package/dist/components/Field/field-context.js.map +1 -1
  103. package/dist/components/Field/field-edit-keys.d.ts +8 -0
  104. package/dist/components/Field/field-edit-keys.d.ts.map +1 -1
  105. package/dist/components/Field/field-edit-keys.js +3 -0
  106. package/dist/components/Field/field-edit-keys.js.map +1 -1
  107. package/dist/components/Field/field-wrapper.d.ts +18 -1
  108. package/dist/components/Field/field-wrapper.d.ts.map +1 -1
  109. package/dist/components/Field/field-wrapper.js +39 -10
  110. package/dist/components/Field/field-wrapper.js.map +1 -1
  111. package/dist/components/Field/field.d.ts +3 -2
  112. package/dist/components/Field/field.d.ts.map +1 -1
  113. package/dist/components/Field/field.js +2 -1
  114. package/dist/components/Field/field.js.map +1 -1
  115. package/dist/components/FileItem/file-item.d.ts +26 -2
  116. package/dist/components/FileItem/file-item.d.ts.map +1 -1
  117. package/dist/components/FileItem/file-item.js +82 -25
  118. package/dist/components/FileItem/file-item.js.map +1 -1
  119. package/dist/components/FileItem/index.js +4 -2
  120. package/dist/components/FileUpload/file-upload.d.ts +1 -1
  121. package/dist/components/FileUpload/file-upload.d.ts.map +1 -1
  122. package/dist/components/FileUpload/file-upload.js +132 -55
  123. package/dist/components/FileUpload/file-upload.js.map +1 -1
  124. package/dist/components/FileViewer/file-viewer.d.ts +1 -1
  125. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  126. package/dist/components/FileViewer/file-viewer.js +9 -4
  127. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  128. package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -1
  129. package/dist/components/InlineEdit/inline-edit.js +1 -1
  130. package/dist/components/InlineEdit/inline-edit.js.map +1 -1
  131. package/dist/components/Input/input.d.ts.map +1 -1
  132. package/dist/components/Input/input.js +6 -1
  133. package/dist/components/Input/input.js.map +1 -1
  134. package/dist/components/LinkInput/link-input.d.ts.map +1 -1
  135. package/dist/components/LinkInput/link-input.js +20 -4
  136. package/dist/components/LinkInput/link-input.js.map +1 -1
  137. package/dist/components/Notice/notice.js +1 -1
  138. package/dist/components/Notice/notice.js.map +1 -1
  139. package/dist/components/NumberInput/number-input.d.ts.map +1 -1
  140. package/dist/components/NumberInput/number-input.js +6 -1
  141. package/dist/components/NumberInput/number-input.js.map +1 -1
  142. package/dist/components/OverflowIndicator/index.js +2 -1
  143. package/dist/components/OverflowIndicator/overflow-indicator.d.ts +19 -1
  144. package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
  145. package/dist/components/OverflowIndicator/overflow-indicator.js +47 -27
  146. package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
  147. package/dist/components/Pagination/pagination.d.ts +1 -1
  148. package/dist/components/Pagination/pagination.js +1 -1
  149. package/dist/components/Pagination/pagination.js.map +1 -1
  150. package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts +7 -6
  151. package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts.map +1 -1
  152. package/dist/components/PeoplePicker/avatar-stack-overflow.js +6 -7
  153. package/dist/components/PeoplePicker/avatar-stack-overflow.js.map +1 -1
  154. package/dist/components/PeoplePicker/people-picker-helpers.d.ts.map +1 -1
  155. package/dist/components/PeoplePicker/people-picker-helpers.js +1 -1
  156. package/dist/components/PeoplePicker/people-picker-helpers.js.map +1 -1
  157. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  158. package/dist/components/PeoplePicker/people-picker.js +2 -2
  159. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  160. package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
  161. package/dist/components/PeoplePicker/person-display.js +26 -28
  162. package/dist/components/PeoplePicker/person-display.js.map +1 -1
  163. package/dist/components/ProfileCard/profile-card.d.ts.map +1 -1
  164. package/dist/components/ProfileCard/profile-card.js.map +1 -1
  165. package/dist/components/RadioGroup/radio-group.d.ts +1 -1
  166. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  167. package/dist/components/RadioGroup/radio-group.js +10 -4
  168. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  169. package/dist/components/Rating/rating.d.ts +28 -6
  170. package/dist/components/Rating/rating.d.ts.map +1 -1
  171. package/dist/components/Rating/rating.js +97 -80
  172. package/dist/components/Rating/rating.js.map +1 -1
  173. package/dist/components/ScrollArea/scroll-area.d.ts +1 -1
  174. package/dist/components/ScrollArea/scroll-area.js +1 -1
  175. package/dist/components/ScrollArea/scroll-area.js.map +1 -1
  176. package/dist/components/SegmentedControl/segmented-control.d.ts +1 -1
  177. package/dist/components/SegmentedControl/segmented-control.d.ts.map +1 -1
  178. package/dist/components/SegmentedControl/segmented-control.js +3 -2
  179. package/dist/components/SegmentedControl/segmented-control.js.map +1 -1
  180. package/dist/components/Select/select.d.ts.map +1 -1
  181. package/dist/components/Select/select.js +15 -8
  182. package/dist/components/Select/select.js.map +1 -1
  183. package/dist/components/SelectMenu/index.js +2 -1
  184. package/dist/components/SelectMenu/index.js.map +1 -1
  185. package/dist/components/SelectMenu/select-menu-keyboard.d.ts +59 -0
  186. package/dist/components/SelectMenu/select-menu-keyboard.d.ts.map +1 -0
  187. package/dist/components/SelectMenu/select-menu-keyboard.js +107 -0
  188. package/dist/components/SelectMenu/select-menu-keyboard.js.map +1 -0
  189. package/dist/components/SelectMenu/select-menu.d.ts +1 -22
  190. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  191. package/dist/components/SelectMenu/select-menu.js +18 -34
  192. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  193. package/dist/components/SelectionControl/selection-item.d.ts.map +1 -1
  194. package/dist/components/SelectionControl/selection-item.js +1 -0
  195. package/dist/components/SelectionControl/selection-item.js.map +1 -1
  196. package/dist/components/Sidebar/sidebar.d.ts +7 -9
  197. package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
  198. package/dist/components/Sidebar/sidebar.js +171 -50
  199. package/dist/components/Sidebar/sidebar.js.map +1 -1
  200. package/dist/components/Slider/slider.d.ts +1 -1
  201. package/dist/components/Slider/slider.d.ts.map +1 -1
  202. package/dist/components/Slider/slider.js +9 -4
  203. package/dist/components/Slider/slider.js.map +1 -1
  204. package/dist/components/Steps/steps.d.ts.map +1 -1
  205. package/dist/components/Steps/steps.js +54 -26
  206. package/dist/components/Steps/steps.js.map +1 -1
  207. package/dist/components/Switch/switch.d.ts +1 -1
  208. package/dist/components/Switch/switch.d.ts.map +1 -1
  209. package/dist/components/Switch/switch.js +7 -2
  210. package/dist/components/Switch/switch.js.map +1 -1
  211. package/dist/components/Tabs/tabs.d.ts +1 -1
  212. package/dist/components/Tabs/tabs.d.ts.map +1 -1
  213. package/dist/components/Tabs/tabs.js +39 -4
  214. package/dist/components/Tabs/tabs.js.map +1 -1
  215. package/dist/components/Tag/tag.d.ts +1 -1
  216. package/dist/components/Tag/tag.d.ts.map +1 -1
  217. package/dist/components/Tag/tag.js +3 -2
  218. package/dist/components/Tag/tag.js.map +1 -1
  219. package/dist/components/Textarea/textarea.d.ts.map +1 -1
  220. package/dist/components/Textarea/textarea.js +8 -2
  221. package/dist/components/Textarea/textarea.js.map +1 -1
  222. package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
  223. package/dist/components/TimePicker/time-columns.js +8 -4
  224. package/dist/components/TimePicker/time-columns.js.map +1 -1
  225. package/dist/components/TimePicker/time-picker.d.ts +1 -1
  226. package/dist/components/TimePicker/time-picker.js +1 -1
  227. package/dist/components/TimePicker/time-picker.js.map +1 -1
  228. package/dist/components/TreeView/tree-view.d.ts +9 -5
  229. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  230. package/dist/components/TreeView/tree-view.js +266 -214
  231. package/dist/components/TreeView/tree-view.js.map +1 -1
  232. package/dist/hooks/use-input-modality.d.ts +12 -17
  233. package/dist/hooks/use-input-modality.d.ts.map +1 -1
  234. package/dist/hooks/use-input-modality.js +4 -34
  235. package/dist/hooks/use-input-modality.js.map +1 -1
  236. package/dist/hooks/use-overflow-items.d.ts.map +1 -1
  237. package/dist/hooks/use-overflow-items.js +2 -0
  238. package/dist/hooks/use-overflow-items.js.map +1 -1
  239. package/dist/hooks/use-truncated.d.ts.map +1 -1
  240. package/dist/hooks/use-truncated.js.map +1 -1
  241. package/dist/index.d.ts +3 -0
  242. package/dist/index.d.ts.map +1 -1
  243. package/dist/index.js +23 -3
  244. package/dist/index.js.map +1 -1
  245. package/dist/lib/drag-announcements.d.ts +32 -0
  246. package/dist/lib/drag-announcements.d.ts.map +1 -1
  247. package/dist/lib/drag-announcements.js +39 -1
  248. package/dist/lib/drag-announcements.js.map +1 -1
  249. package/dist/lib/focus-after-trigger.d.ts +45 -0
  250. package/dist/lib/focus-after-trigger.d.ts.map +1 -0
  251. package/dist/lib/focus-after-trigger.js +66 -0
  252. package/dist/lib/focus-after-trigger.js.map +1 -0
  253. package/dist/lib/overlay-coexistence.js +1 -1
  254. package/dist/lib/roving-list-keyboard.d.ts +208 -0
  255. package/dist/lib/roving-list-keyboard.d.ts.map +1 -0
  256. package/dist/lib/roving-list-keyboard.js +174 -0
  257. package/dist/lib/roving-list-keyboard.js.map +1 -0
  258. package/dist/lib/utils.d.ts.map +1 -1
  259. package/dist/lib/utils.js +6 -1
  260. package/dist/lib/utils.js.map +1 -1
  261. package/dist/patterns/element-anatomy/item-anatomy.d.ts +4 -4
  262. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
  263. package/dist/patterns/element-anatomy/item-anatomy.js +14 -4
  264. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  265. package/dist/patterns/horizontal-overflow/horizontal-overflow.d.ts.map +1 -1
  266. package/dist/patterns/horizontal-overflow/horizontal-overflow.js +25 -0
  267. package/dist/patterns/horizontal-overflow/horizontal-overflow.js.map +1 -1
  268. package/dist/patterns/overlay-surface/overlay-surface.d.ts.map +1 -1
  269. package/dist/patterns/overlay-surface/overlay-surface.js.map +1 -1
  270. package/dist/tokens/categorical-color.d.ts +6 -1
  271. package/dist/tokens/categorical-color.d.ts.map +1 -1
  272. package/dist/tokens/categorical-color.js.map +1 -1
  273. package/dist/tokens/uiSize/icon-size.d.ts +1 -1
  274. package/dist/tokens/uiSize/stack-gap.d.ts +18 -0
  275. package/dist/tokens/uiSize/stack-gap.d.ts.map +1 -0
  276. package/dist/tokens/uiSize/stack-gap.js +5 -0
  277. package/dist/tokens/uiSize/stack-gap.js.map +1 -0
  278. package/ds-canonical/fork/codex/agents/skills/performance-audit/SKILL.md +1 -1
  279. package/ds-canonical/fork/codex/hooks.json +1 -1
  280. package/ds-canonical/fork/consumer/lock.json +17 -14
  281. package/ds-canonical/fork/consumer/managed-files/423729840acdd43c812f17c245b871716c6b60f76e4d3e94864d0e34a815bf8d.blob +9 -0
  282. package/ds-canonical/fork/consumer/managed-files/46f10bc55cdfdf834d0749eebff42ea0bb8576f361b36d2b6ba1851354c50150.blob +47 -9
  283. package/ds-canonical/fork/consumer/managed-files/5a0d134a2645114c8caac20458070b00a7f0fd55b3e8805b7325cb4cf52fa15e.blob +110 -0
  284. package/ds-canonical/fork/consumer/managed-files/5af0a46760af338d51fd0f7950675f8e97f7d2f09386b8818fcd7a58e6654e75.blob +790 -0
  285. package/ds-canonical/fork/consumer/managed-files/68bfcddff9c4a16388c248cd34fb66163e9e64b3d809a48ef3984f6ae4ff6d12.blob +211 -0
  286. package/ds-canonical/fork/consumer/managed-files/7eb6cc60abfdabaf6617c336058fad1454ccde08889295767bfd9b7fd153cc6e.blob +45 -6
  287. package/ds-canonical/fork/consumer/managed-files/92e4828cdcb96ff0d01daa16f6885f24045a8e72820665650f2a1890dc3a446c.blob +42 -2
  288. package/ds-canonical/fork/consumer/managed-files/ab072e7f2eca51f0e18a5e18c4b333260ee5d219a12cc6df5bb2d683f0b2734d.blob +27 -1
  289. package/ds-canonical/fork/consumer/managed-files/e71c65f45c6af7ce12b6b3c0d8028f185da5b719e2050c9b2a6b243d41ae4878.blob +62 -14
  290. package/ds-canonical/fork/governance.lock +41 -17
  291. package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +16 -4
  292. package/ds-canonical/fork/hooks/check_consumer_code_quality.sh +3 -1
  293. package/ds-canonical/fork/hooks/check_pattern_invariants.sh +13 -9
  294. package/ds-canonical/fork/launchers/settings-hooks.json +1 -1
  295. package/ds-canonical/fork/manifest.json +17 -11
  296. package/ds-canonical/fork/providers/claude/skills/performance-audit/SKILL.md +1 -1
  297. package/ds-canonical/fork/providers/codex/hook-config.json +1 -1
  298. package/ds-canonical/fork/providers/codex/skills/performance-audit/SKILL.md +1 -1
  299. package/ds-canonical/fork/skills/performance-audit/SKILL.md +1 -1
  300. package/ds-canonical/hooks/check_consumer_app_invariants.sh +16 -4
  301. package/ds-canonical/hooks/check_consumer_code_quality.sh +3 -1
  302. package/ds-canonical/hooks/check_datatable_invariants.sh +4 -1
  303. package/ds-canonical/hooks/check_pattern_invariants.sh +13 -9
  304. package/ds-canonical/hooks/check_plugin_fork_health.sh +8 -1
  305. package/ds-canonical/hooks/check_propose_discipline.sh +8 -1
  306. package/ds-canonical/hooks/check_storybook_addon_packaging.sh +8 -1
  307. package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +64 -2
  308. package/ds-canonical/hooks/lib/_overlay_handcraft.sh +5 -2
  309. package/ds-canonical/hooks/registrations.json +12 -7
  310. package/ds-canonical/hooks/session_start_governance_check.sh +16 -0
  311. package/ds-canonical/hooks/tests/test_check_consumer_app_invariants.sh +25 -0
  312. package/ds-canonical/hooks/tests/test_check_consumer_code_quality.sh +4 -0
  313. package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +14 -0
  314. package/ds-canonical/hooks/tests/test_check_datatable_invariants.sh +24 -0
  315. package/ds-canonical/hooks/tests/test_check_overlay_handcraft.sh +32 -0
  316. package/ds-canonical/hooks/tests/test_check_pattern_invariants.sh +59 -0
  317. package/ds-canonical/hooks/tests/test_check_plugin_fork_health.sh +32 -1
  318. package/ds-canonical/hooks/tests/test_check_propose_discipline.sh +21 -0
  319. package/ds-canonical/hooks/tests/test_check_storybook_addon_packaging.sh +21 -0
  320. package/ds-canonical/hooks/tests/test_check_substantive_edit_approval_preflight.sh +97 -0
  321. package/ds-canonical/hooks/tests/test_session_start_governance_check.sh +49 -0
  322. package/ds-canonical/references/README.md +12 -6
  323. package/ds-canonical/references/drag-canonical.md +3 -1
  324. package/ds-canonical/references/focus-canonical.md +26 -13
  325. package/ds-canonical/references/governance-audit-coverage.md +1 -1
  326. package/ds-canonical/references/hit-area-canonical.md +361 -0
  327. package/ds-canonical/references/item-anatomy-recipe.md +4 -2
  328. package/ds-canonical/references/keyboard-model-canonical.md +559 -0
  329. package/ds-canonical/rules/meta-patterns.md +4 -4
  330. package/ds-canonical/rules/self-verify.md +4 -4
  331. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +1 -1
  332. package/ds-canonical/skills/design-system-audit/references/historical-bugs.md +96 -0
  333. package/ds-canonical/skills/knowledge-prune/SKILL.md +4 -1
  334. package/ds-canonical/skills/performance-audit/SKILL.md +1 -1
  335. package/ds-story-manifest.json +19 -7
  336. package/llms-full.txt +2 -2
  337. package/llms.txt +2 -2
  338. package/package.json +3 -1
  339. package/src/components/Accordion/accordion.anatomy.stories.tsx +3 -3
  340. package/src/components/Accordion/accordion.spec.md +1 -1
  341. package/src/components/Accordion/accordion.tsx +8 -3
  342. package/src/components/AccountMenu/account-menu.spec.md +2 -3
  343. package/src/components/AccountMenu/account-menu.tsx +0 -1
  344. package/src/components/AgentPanel/agent-decision-card.spec.md +88 -0
  345. package/src/components/AgentPanel/agent-panel-fab.spec.md +151 -0
  346. package/src/components/AgentPanel/agent-panel-fab.tsx +67 -24
  347. package/src/components/AgentPanel/agent-panel-logo.spec.md +87 -0
  348. package/src/components/AgentPanel/agent-panel-logo.tsx +3 -3
  349. package/src/components/AgentPanel/agent-panel.anatomy.stories.tsx +1 -1
  350. package/src/components/AgentPanel/agent-panel.principles.stories.tsx +1 -1
  351. package/src/components/AgentPanel/agent-panel.spec.md +30 -275
  352. package/src/components/AgentPanel/agent-panel.stories.tsx +113 -8
  353. package/src/components/AgentPanel/agent-panel.tsx +59 -22
  354. package/src/components/Alert/alert.anatomy.stories.tsx +1 -1
  355. package/src/components/AppShell/app-shell.tsx +1 -1
  356. package/src/components/AspectRatio/aspect-ratio.anatomy.stories.tsx +10 -15
  357. package/src/components/Avatar/avatar.anatomy.stories.tsx +23 -26
  358. package/src/components/Avatar/avatar.principles.stories.tsx +10 -10
  359. package/src/components/Avatar/avatar.spec.md +45 -6
  360. package/src/components/Avatar/avatar.stories.tsx +8 -8
  361. package/src/components/Avatar/avatar.tsx +227 -21
  362. package/src/components/Badge/badge.anatomy.stories.tsx +16 -21
  363. package/src/components/Breadcrumb/breadcrumb.anatomy.stories.tsx +3 -3
  364. package/src/components/Breadcrumb/breadcrumb.spec.md +3 -3
  365. package/src/components/Breadcrumb/breadcrumb.tsx +5 -3
  366. package/src/components/BulkActionBar/bulk-action-bar.anatomy.stories.tsx +1 -1
  367. package/src/components/BulkActionBar/bulk-action-bar.principles.stories.tsx +1 -1
  368. package/src/components/BulkActionBar/bulk-action-bar.spec.md +1 -0
  369. package/src/components/BulkActionBar/bulk-action-bar.stories.tsx +57 -2
  370. package/src/components/BulkActionBar/bulk-action-bar.tsx +32 -2
  371. package/src/components/Button/button.anatomy.stories.tsx +174 -33
  372. package/src/components/Button/button.spec.md +23 -8
  373. package/src/components/Button/button.tsx +116 -21
  374. package/src/components/Calendar/calendar.anatomy.stories.tsx +34 -11
  375. package/src/components/Calendar/calendar.principles.stories.tsx +44 -1
  376. package/src/components/Calendar/calendar.spec.md +97 -20
  377. package/src/components/Calendar/calendar.stories.tsx +101 -4
  378. package/src/components/Calendar/calendar.tsx +379 -74
  379. package/src/components/Carousel/carousel.anatomy.stories.tsx +16 -17
  380. package/src/components/Carousel/carousel.spec.md +48 -2
  381. package/src/components/Carousel/carousel.tsx +9 -3
  382. package/src/components/Chart/chart.anatomy.stories.tsx +7 -5
  383. package/src/components/Chart/chart.spec.md +32 -7
  384. package/src/components/Chart/chart.tsx +9 -0
  385. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +21 -28
  386. package/src/components/Checkbox/checkbox.spec.md +4 -2
  387. package/src/components/Checkbox/checkbox.tsx +10 -2
  388. package/src/components/Chip/chip.anatomy.stories.tsx +1 -1
  389. package/src/components/Chip/chip.spec.md +2 -1
  390. package/src/components/Chip/chip.tsx +4 -2
  391. package/src/components/Combobox/combobox.anatomy.stories.tsx +30 -37
  392. package/src/components/Combobox/combobox.spec.md +11 -3
  393. package/src/components/Combobox/combobox.tsx +43 -12
  394. package/src/components/Command/command.spec.md +11 -0
  395. package/src/components/Command/command.tsx +143 -10
  396. package/src/components/DataTable/cell-registry.tsx +5 -1
  397. package/src/components/DataTable/data-table-column-visibility-panel.tsx +5 -6
  398. package/src/components/DataTable/data-table-interaction-layer.tsx +27 -14
  399. package/src/components/DataTable/data-table-known-defects.spec.md +72 -0
  400. package/src/components/DataTable/data-table-scroll-performance.spec.md +295 -0
  401. package/src/components/DataTable/data-table-sort-manager.tsx +5 -6
  402. package/src/components/DataTable/data-table.anatomy.stories.tsx +1 -1
  403. package/src/components/DataTable/data-table.css +64 -0
  404. package/src/components/DataTable/data-table.spec.md +70 -346
  405. package/src/components/DataTable/data-table.stories.tsx +56 -9
  406. package/src/components/DataTable/data-table.tsx +392 -103
  407. package/src/components/DateGrid/date-grid.anatomy.stories.tsx +2 -2
  408. package/src/components/DateGrid/date-grid.spec.md +163 -1
  409. package/src/components/DateGrid/date-grid.tsx +270 -7
  410. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +18 -27
  411. package/src/components/DatePicker/date-picker.spec.md +6 -2
  412. package/src/components/DatePicker/date-picker.tsx +20 -1
  413. package/src/components/Dialog/dialog.spec.md +6 -2
  414. package/src/components/Dialog/dialog.stories.tsx +18 -9
  415. package/src/components/Dialog/dialog.tsx +83 -48
  416. package/src/components/DropdownMenu/dropdown-menu-keyboard.ts +255 -0
  417. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +32 -33
  418. package/src/components/DropdownMenu/dropdown-menu.spec.md +18 -5
  419. package/src/components/DropdownMenu/dropdown-menu.stories.tsx +58 -1
  420. package/src/components/DropdownMenu/dropdown-menu.tsx +70 -33
  421. package/src/components/Empty/empty.spec.md +1 -2
  422. package/src/components/Field/field-context.ts +9 -4
  423. package/src/components/Field/field-controls.spec.md +5 -2
  424. package/src/components/Field/field-edit-keys.ts +12 -0
  425. package/src/components/Field/field-wrapper.tsx +76 -10
  426. package/src/components/Field/field.anatomy.stories.tsx +1 -1
  427. package/src/components/Field/field.spec.md +11 -6
  428. package/src/components/Field/field.stories.tsx +24 -1
  429. package/src/components/Field/field.tsx +10 -4
  430. package/src/components/FileItem/file-item.anatomy.stories.tsx +20 -10
  431. package/src/components/FileItem/file-item.principles.stories.tsx +14 -7
  432. package/src/components/FileItem/file-item.spec.md +50 -48
  433. package/src/components/FileItem/file-item.stories.tsx +41 -28
  434. package/src/components/FileItem/file-item.tsx +184 -50
  435. package/src/components/FileUpload/file-upload.anatomy.stories.tsx +11 -15
  436. package/src/components/FileUpload/file-upload.spec.md +27 -1
  437. package/src/components/FileUpload/file-upload.stories.tsx +33 -0
  438. package/src/components/FileUpload/file-upload.tsx +173 -43
  439. package/src/components/FileViewer/file-viewer.tsx +9 -4
  440. package/src/components/HoverCard/hover-card.stories.tsx +2 -2
  441. package/src/components/InlineEdit/inline-edit.spec.md +2 -0
  442. package/src/components/InlineEdit/inline-edit.tsx +8 -3
  443. package/src/components/Input/input.anatomy.stories.tsx +23 -31
  444. package/src/components/Input/input.spec.md +11 -0
  445. package/src/components/Input/input.tsx +6 -1
  446. package/src/components/LinkInput/link-input.anatomy.stories.tsx +18 -21
  447. package/src/components/LinkInput/link-input.principles.stories.tsx +4 -4
  448. package/src/components/LinkInput/link-input.spec.md +12 -1
  449. package/src/components/LinkInput/link-input.tsx +37 -4
  450. package/src/components/Menu/menu-item.anatomy.stories.tsx +50 -56
  451. package/src/components/Menu/menu-item.spec.md +1 -1
  452. package/src/components/Menu/menu-item.stories.tsx +48 -42
  453. package/src/components/Notice/notice.anatomy.stories.tsx +8 -16
  454. package/src/components/Notice/notice.spec.md +1 -1
  455. package/src/components/Notice/notice.tsx +1 -1
  456. package/src/components/NumberInput/number-input.anatomy.stories.tsx +21 -28
  457. package/src/components/NumberInput/number-input.spec.md +2 -0
  458. package/src/components/NumberInput/number-input.tsx +8 -1
  459. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +28 -48
  460. package/src/components/OverflowIndicator/overflow-indicator.spec.md +13 -1
  461. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +12 -9
  462. package/src/components/OverflowIndicator/overflow-indicator.tsx +32 -12
  463. package/src/components/Pagination/pagination.spec.md +1 -0
  464. package/src/components/Pagination/pagination.tsx +1 -1
  465. package/src/components/PeoplePicker/avatar-stack-overflow.ts +14 -13
  466. package/src/components/PeoplePicker/people-picker-helpers.ts +5 -2
  467. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +1 -1
  468. package/src/components/PeoplePicker/people-picker.spec.md +4 -2
  469. package/src/components/PeoplePicker/people-picker.tsx +1 -4
  470. package/src/components/PeoplePicker/person-display.tsx +45 -28
  471. package/src/components/Popover/popover.anatomy.stories.tsx +1 -1
  472. package/src/components/Popover/popover.principles.stories.tsx +3 -12
  473. package/src/components/Popover/popover.spec.md +7 -3
  474. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +1 -1
  475. package/src/components/ProfileCard/profile-card.spec.md +1 -1
  476. package/src/components/ProfileCard/profile-card.tsx +0 -3
  477. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +11 -21
  478. package/src/components/ProgressBar/progress-bar.spec.md +1 -1
  479. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +17 -24
  480. package/src/components/RadioGroup/radio-group.spec.md +1 -1
  481. package/src/components/RadioGroup/radio-group.tsx +22 -4
  482. package/src/components/Rating/rating.anatomy.stories.tsx +131 -124
  483. package/src/components/Rating/rating.principles.stories.tsx +69 -43
  484. package/src/components/Rating/rating.spec.md +142 -63
  485. package/src/components/Rating/rating.stories.tsx +11 -15
  486. package/src/components/Rating/rating.tsx +131 -117
  487. package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
  488. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +6 -3
  489. package/src/components/ScrollArea/scroll-area.spec.md +3 -1
  490. package/src/components/ScrollArea/scroll-area.stories.tsx +5 -2
  491. package/src/components/ScrollArea/scroll-area.tsx +1 -1
  492. package/src/components/SegmentedControl/segmented-control.anatomy.stories.tsx +1 -1
  493. package/src/components/SegmentedControl/segmented-control.spec.md +2 -2
  494. package/src/components/SegmentedControl/segmented-control.tsx +3 -2
  495. package/src/components/Select/select.anatomy.stories.tsx +26 -35
  496. package/src/components/Select/select.spec.md +4 -3
  497. package/src/components/Select/select.tsx +11 -4
  498. package/src/components/SelectMenu/select-menu-keyboard.ts +218 -0
  499. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +6 -17
  500. package/src/components/SelectMenu/select-menu.spec.md +12 -4
  501. package/src/components/SelectMenu/select-menu.tsx +21 -56
  502. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +9 -33
  503. package/src/components/SelectionControl/selection-item.spec.md +2 -2
  504. package/src/components/SelectionControl/selection-item.tsx +3 -1
  505. package/src/components/Separator/separator.stories.tsx +4 -4
  506. package/src/components/Sheet/sheet.principles.stories.tsx +31 -13
  507. package/src/components/Sidebar/sidebar.anatomy.stories.tsx +1 -1
  508. package/src/components/Sidebar/sidebar.spec.md +73 -6
  509. package/src/components/Sidebar/sidebar.stories.tsx +82 -4
  510. package/src/components/Sidebar/sidebar.tsx +281 -64
  511. package/src/components/Skeleton/skeleton.spec.md +1 -1
  512. package/src/components/Slider/slider.anatomy.stories.tsx +1 -1
  513. package/src/components/Slider/slider.spec.md +6 -5
  514. package/src/components/Slider/slider.tsx +13 -8
  515. package/src/components/Steps/steps-state-visuals.spec.md +157 -0
  516. package/src/components/Steps/steps.anatomy.stories.tsx +1 -0
  517. package/src/components/Steps/steps.spec.md +59 -142
  518. package/src/components/Steps/steps.stories.tsx +1 -1
  519. package/src/components/Steps/steps.tsx +125 -33
  520. package/src/components/Switch/switch.spec.md +3 -3
  521. package/src/components/Switch/switch.tsx +6 -1
  522. package/src/components/Tabs/tabs.spec.md +5 -1
  523. package/src/components/Tabs/tabs.tsx +42 -3
  524. package/src/components/Tag/tag.anatomy.stories.tsx +24 -28
  525. package/src/components/Tag/tag.spec.md +10 -11
  526. package/src/components/Tag/tag.tsx +3 -3
  527. package/src/components/Textarea/textarea.tsx +7 -1
  528. package/src/components/TimePicker/time-columns.tsx +9 -4
  529. package/src/components/TimePicker/time-picker.spec.md +4 -1
  530. package/src/components/TimePicker/time-picker.tsx +1 -1
  531. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +6 -15
  532. package/src/components/Tooltip/tooltip.principles.stories.tsx +4 -16
  533. package/src/components/Tooltip/tooltip.spec.md +2 -1
  534. package/src/components/TreeView/tree-view.anatomy.stories.tsx +35 -13
  535. package/src/components/TreeView/tree-view.spec.md +67 -38
  536. package/src/components/TreeView/tree-view.stories.tsx +221 -12
  537. package/src/components/TreeView/tree-view.tsx +463 -356
  538. package/src/hooks/use-input-modality.ts +17 -46
  539. package/src/hooks/use-overflow-items.ts +4 -0
  540. package/src/hooks/use-truncated.ts +3 -2
  541. package/src/index.ts +17 -0
  542. package/src/lib/README.md +2 -0
  543. package/src/lib/drag-announcements.ts +78 -0
  544. package/src/lib/focus-after-trigger.ts +102 -0
  545. package/src/lib/roving-list-keyboard.ts +400 -0
  546. package/src/lib/utils.ts +5 -0
  547. package/src/patterns/action-bar/action-bar.spec.md +2 -0
  548. package/src/patterns/element-anatomy/inline-action.spec.md +16 -12
  549. package/src/patterns/element-anatomy/item-anatomy.spec.md +98 -6
  550. package/src/patterns/element-anatomy/item-anatomy.stories.tsx +75 -70
  551. package/src/patterns/element-anatomy/item-anatomy.tsx +17 -6
  552. package/src/patterns/element-anatomy/truncated-text.spec.md +1 -0
  553. package/src/patterns/header-canonical/header-canonical.spec.md +3 -2
  554. package/src/patterns/horizontal-overflow/horizontal-overflow.spec.md +2 -0
  555. package/src/patterns/horizontal-overflow/horizontal-overflow.stories.tsx +36 -0
  556. package/src/patterns/horizontal-overflow/horizontal-overflow.tsx +28 -0
  557. package/src/patterns/overlay-surface/overlay-chrome-sizing.spec.md +180 -0
  558. package/src/patterns/overlay-surface/overlay-surface.spec.md +8 -162
  559. package/src/patterns/overlay-surface/overlay-surface.tsx +5 -3
  560. package/src/patterns/resize-handle/resize-handle.spec.md +3 -3
  561. package/src/styles/base.css +1 -1
  562. package/src/tokens/categorical-color.ts +6 -1
  563. package/src/tokens/color/color.spec.md +91 -24
  564. package/src/tokens/color/color.stories.tsx +50 -2
  565. package/src/tokens/color/primitives.css +41 -38
  566. package/src/tokens/color/semantic.css +105 -36
  567. package/src/tokens/layoutSpace/layoutSpace.spec.md +2 -0
  568. package/src/tokens/motion/motion.spec.md +31 -8
  569. package/src/tokens/orphan-tokens.spec.md +1 -1
  570. package/src/tokens/uiSize/icon-size.ts +1 -1
  571. package/src/tokens/uiSize/stack-gap.ts +17 -0
  572. package/src/tokens/uiSize/uiSize.css +12 -0
  573. package/src/tokens/uiSize/uiSize.spec.md +17 -16
  574. package/src/tokens/uiSize/uiSize.stories.tsx +1 -1
  575. package/dist/node_modules/aria-hidden/dist/es2015/index.js +0 -147
  576. package/dist/node_modules/aria-hidden/dist/es2015/index.js.map +0 -1
@@ -0,0 +1,180 @@
1
+ ---
2
+ internal: true
3
+ # 同 overlay-surface.spec.md:DS-internal pattern 的分節,不是另一個 pattern;sub-spec 不另立 family(Dim 16 豁免)
4
+ ---
5
+
6
+ <!-- @benchmark-cited: D5 retrofit 2026-05-18 — body claims marked per-claim @benchmark-unverified inline; canonical source URLs in frontmatter benchmark list.(2026-09-27 自 overlay-surface.spec.md 抽出,標記沿用) -->
7
+
8
+ # Overlay chrome 分級尺寸設計原則(overlay-surface 的分節;獨立 SSOT)
9
+
10
+ > **本 spec 是 overlay chrome 分級尺寸的獨立 SSOT**(2026-09-27 從 `overlay-surface.spec.md` 整段抽出「Overlay title typography canonical」「為什麼 SurfaceHeader 是 padding-based」「Size canonical」「Chrome dismiss size canonical」四節,避免單一 spec 過長(595 行 > 500 硬上限,待辦總帳 N19);內容零改動,只加本檔頭、檔尾指標,與 N23 的四處來源標註(見「為什麼用負 margin」與「震盪歷史備忘」))。SurfaceHeader / SurfaceBody / SurfaceFooter 結構、List-as-region、footer 對齊、Viewport-aware scroll chain、A11y 仍住 `./overlay-surface.spec.md`;程式碼對應 `overlay-surface.tsx`(`CHROME_UNBOUNDED_SLOT` / `COMPACT_HEADER_SLOT`)與 `../../components/Button/button.tsx`(`data-unbounded`)。
11
+ >
12
+ > **Layout Family**:同 `overlay-surface.spec.md`(非 Family 1–4 — structural container primitive 的分區尺寸);本檔不另立 family。
13
+
14
+ ## Overlay title typography canonical(modal vs non-modal 分級,2026-04-22)
15
+
16
+ Overlay family 的 header title typography 依「modal vs non-modal」分級,**跟 chrome padding / dismiss behavior 同 rationale(modal 重量級 vs non-modal 輕量)**:
17
+
18
+ | 家族 | Title typography | 套用元件 |
19
+ |------|------------------|---------|
20
+ | **Modal**(阻斷互動)| `text-body-lg font-medium truncate`(**16px**)| `Dialog` / `Sheet` |
21
+ | **Non-modal**(可忽略)| `text-body font-medium truncate`(**14px**)| `Popover` / `Coachmark` |
22
+
23
+ **Rationale**:
24
+ - **Modal**:title 是決策 anchor,user 必須 process → 需視覺重量(16px + 重字重)
25
+ - **Non-modal**:title 是輔助標籤,user 可忽略 → 輕量字級(14px)不搶 body content
26
+
27
+ **世界級對照**(7 家 DS 同 split): <!-- @benchmark-unverified -->
28
+ | DS | Modal title | Non-modal popover title |
29
+ |----|-------------|------------------------|
30
+ | Material M3 | Headline 24 / body 16 | Smaller 14-16 |
31
+ | Polaris | Modal 大 | Popover 較小 |
32
+ | Atlassian | Modal 大 | InlineDialog 小 |
33
+ | Notion | 16+ | 14 |
34
+ | Linear | 16 | 14 |
35
+ | Figma | 16 | 13-14 |
36
+ | GitHub Primer | 16 | 14 |
37
+
38
+ **跟「density 鎖 md」同源**:Popover / Coachmark 把「輕量」貫穿 chrome:density 鎖 md + chrome button 透過 v5 unbounded trick 縮 layout + **title 小一級**。三件一起構成「輕量浮層」視覺語言,跟 Modal heavy 形成明確分化。
39
+
40
+ **禁止**:consumer 自刻 `<h2 className="text-body-lg">` 繞 `PopoverTitle` — 若需要大 title 代表該用 Dialog 而非 Popover(選錯元件)。
41
+
42
+ **SSOT**:
43
+ - `components/Popover/popover.spec.md`「Title typography canonical(non-modal 特化)」(Popover 專用細節)
44
+ - `components/Dialog/dialog.spec.md`「Title」(Modal 專用細節)
45
+
46
+ ---
47
+
48
+ ## 為什麼 SurfaceHeader 是 padding-based(而非 fixed-h)(2026-04-22 設計原則)
49
+
50
+ **SurfaceHeader 永遠 padding-based**(`py-tight`,不鎖固定高度)。Header 高度 = `max(title line-height, button slot)+ 2×py`,**slot 設計為 ≤ title line-height** 讓 title 主導 → header 高度 = title 決定(slot 縮位 / CSS var 參數化等實作細節詳下方「Chrome dismiss size canonical」)。SurfaceFooter **不**套 unbounded slot trick(僅 padding + `border-t`,慣例放 bounded action buttons)。**語義宣告**:
51
+
52
+ **Padding-based 宣告**:「本 chrome **可以成長** — title 可換行、可附 subtitle / description」。適用 overlay family(Dialog / Sheet / Popover / Coachmark),這些都是 modal/semi-modal 情境,title 有可能長(例如「確認要永久刪除 Marketing Q4 Campaign 這個專案嗎?」兩行 title),或有 subtitle(「這個操作無法復原」補充說明)。
53
+
54
+ **Fixed-height 宣告**:「本 chrome **永遠單行固定結構** — 不會長高」。適用 chrome 類如 Sidebar / FileViewer toolbar / app top bar,這些 chrome 的內容是 logo / icons / 短固定 label,不會 grow。
55
+
56
+ **兩者視覺上在單行 content 時都是 48/56,但是不同的設計宣告**:
57
+ - 若 Dialog 用 fixed-h,未來塞兩行 title / subtitle 會被剪掉 → 違反 modal 作為「完整決策 context」的職責
58
+ - 若 Sidebar 用 padding-based,chrome 可能在長 label 時變動 → 違反 sidebar chrome「剛性佈局」的職責
59
+
60
+ **判斷 tree**:問「這個 chrome 的 title 有可能多行 / 有 subtitle / 有 description 嗎?」
61
+ - **會** → padding-based(SurfaceHeader 或自刻 py-tight)
62
+ - **不會** → fixed-h(`h-[var(--chrome-header-height)]`)
63
+
64
+ **完整 canonical + 世界級對照**:`tokens/uiSize/uiSize.spec.md`「Chrome header 選型 canonical」節(含「2 種 pattern 對照」)
65
+
66
+ ---
67
+
68
+ ## Size canonical(per-overlay default size SSOT,2026-05-04)
69
+
70
+ > **背景**:Popover / HoverCard 是「輕量浮層」(chrome 45 / slot 21 / title 小一級 / density 鎖 md);Dialog / Sheet 是「heavy commitment chrome」(chrome 48 / slot 24)。Per-surface body+footer button/field default size 跟「輕量 vs heavy」分化對應。
71
+ >
72
+ > **依據**:Linear / Notion / Airtable / Carbon / Material Menu / Atlassian Popup popover bodies 共識用 sm-density;Material AlertDialog / Carbon Modal / shadcn Dialog 共識用 md。world-class 雙派分明依「浮層密度」分。 <!-- @benchmark-unverified -->
73
+
74
+ | Overlay | Header chrome | Body field controls | Body inline action(drag handle / trash / +CTA)| Footer action Buttons |
75
+ |--|--|--|--|--|
76
+ | **Popover** | unbounded sm → 21 slot(輕)| **sm**(輕量 dense info)| inline-action sm/md = **16+18** | **sm** |
77
+ | **HoverCard** | (同 Popover)| **sm** | 同 | **sm** |
78
+ | **Dialog** | unbounded sm → 24 slot | **md** | inline-action sm/md = 16+18 | **md** |
79
+ | **Sheet** | (同 Dialog)| **md** | 同 | **md** |
80
+ | **BulkActionBar** | N/A | N/A | N/A | **md**(default footer placement);未來 top-toolbar variant → sm |
81
+
82
+ **核心 invariant**:overlay surface 內 **body field controls + footer Buttons 同一 size**(per-surface 一致)。違反 = 視覺重量割裂。
83
+
84
+ **為什麼 Popover all-sm 而非 mix**:Popover 整體已是「輕量浮層」設計語言(chrome 短、title 小、density 鎖 md)。如果 body 用 md fields(32 高)+ footer sm Buttons(28 高),視覺重量割裂破壞「輕量」一致性。**all-sm 是內部一致性**(body 28 / footer 28 同高,延伸 chrome 輕一級的密度)。
85
+
86
+ **為什麼 Dialog all-md 而非 mix**:Dialog 是 heavy commitment chrome,body 操作往往 form-heavy,md (32) 是 Field family default(`--field-height-md` SSOT),footer Buttons 同 md commit 視覺重量配得上 modal 結論性。
87
+
88
+ **Drag handle / inline-action sizing**(對齊 `patterns/element-anatomy/inline-action.spec.md`):
89
+ - Field sm/md 同 row → inline action **16 icon / 18 hover bg**
90
+ - Field lg 同 row → inline action **20 icon / 22 hover bg**
91
+
92
+ 亦即:在 Popover(field=sm)或 Dialog(field=md)body 內,inline action 都同樣 16+18,差別只在 lg-density 場景。
93
+
94
+ ---
95
+
96
+ ## Chrome dismiss size canonical
97
+
98
+ **設計 insight(本檔既有記載;2026-09-27 查無對話原文可引,依 M36(a) 標為來源不明,不得當 user 拍板引用)**:header 的 padding-based sizing 在 **unbounded button**(text variant / dismiss,無 bg/border)場景視覺 padding 過大;在 **bounded button** 則剛好。解法 = **保持 button native size 不變(命中區 / 視覺 render 都是 sm 原尺寸),但 layout 佔位縮到 title line-box(24,衍生自 --font-body-lg-size×1.5)** via 負 margin。
99
+
100
+ **Canonical**:button native size **保留 sm**(命中區 / 視覺 render 不動);**unbounded 的靠 CSS 負 my 把 layout 佔位縮到 `--chrome-slot-h`** ≤ title line-height,讓 title 主導 chrome 高度。
101
+
102
+ | Button 類型 | 判定(button.tsx L426-427)| Trick 套用 | Layout 佔位 | Dialog/Sheet header (slot 24)| Popover header (slot 21)|
103
+ |--|--|--|--|--|--|
104
+ | **Unbounded** | `variant === 'text'` OR `dismiss` → `data-unbounded="true"` | ✓ 套負 my | = `var(--chrome-slot-h)` | max(24, 24) + py-tight = **48** | max(21, 21) + py-tight = **45** |
105
+ | **Bounded** | `primary` / `tertiary` / `outline` 等(有 bg/border) | ✗ 不套 | = native sm (28 md / 32 lg) | max(24, 28) + py-tight = **52**(自然長)| max(21, 28) + py-tight = **52**(自然長)|
106
+
107
+ **為什麼差別**:Unbounded 沒視覺邊界 → native 28 是純 hit-target padding,縮 layout 不損視覺;Bounded 的 bg/border 就是內容,縮會切掉 → 必須讓 chrome 自然長高,**這是設計宣告「此 chrome 有重要 action,視覺重量該配得上」**。
108
+
109
+ **實作**:
110
+
111
+ ```tsx
112
+ // button.tsx ── 自動標記 data-unbounded
113
+ const unboundedAttr = resolvedVariant === 'text' || dismiss ? { 'data-unbounded': 'true' } : {}
114
+
115
+ // overlay-surface.tsx ── slot 透過 CSS var 參數化(2026-05-04 v3;2026-06-16 default 改衍生)
116
+ const CHROME_UNBOUNDED_SLOT =
117
+ '[&_[data-unbounded]]:my-[calc((var(--chrome-slot-h,calc(var(--font-body-lg-size)*1.5))-var(--field-height-sm))/2)]'
118
+
119
+ // SurfaceHeader default → slot 衍生自 title typography = calc(--font-body-lg-size × 1.5) = 24
120
+ // (2026-06-16:從寫死 field-height-xs 改衍生 → title 字級改了 slot 自動跟、不靠巧合;M17 SSOT;
121
+ // 1.5 = typography.spec body 行高常數,非 token 故 inline,body 行高改須同步)
122
+ // Popover-tier override → COMPACT_HEADER_SLOT(= calc(--font-body-size × 1.5) = 21,衍生自 text-body title)
123
+ // 公式 = (slot - native) / 2 ── Dialog md: (24-28)/2 = -2px / Popover md: (21-28)/2 = -3.5px
124
+ ```
125
+
126
+ **覆蓋範圍**:
127
+ - Dismiss X(`<Button dismiss />`)→ data-unbounded ✓
128
+ - Text variant action(`<Button variant="text" />` 如 Share / Refresh / Settings)→ data-unbounded ✓
129
+ - 所有無視覺邊界的 button,不限 dismiss
130
+
131
+ **為什麼用負 margin 而非 fixed wrapper / size="xs"**:
132
+ - `size="xs"` 會縮小 button 本身,**命中區也跟著縮到 24**,與 overlay chrome 的比例不協調(chrome 的 dismiss 是 `sm` = 28),也違反此處記載的意圖「touch 仍 sm」(**AI 推導、引不出 user 原話**;2026-09-27 依待辦總帳 N23 拿掉「user 意圖」的歸屬,引號內原字不動,來源說明見下一行)。**問題在比例,不在 a11y** —— 24 正好等於 `tokens/uiSize/uiSize.spec.md`「元件高度地板」(:169)訂的最小值,沒有低於任何我們採用的門檻;先前這裡寫的「違反 a11y 最小 24+ hit target」既與 :169 自相矛盾、也查無出處,2026-09-24 更正(同 `uiSize.spec.md:350`)
133
+ - ⚠️ **引號內為本檔既有記載,本輪查無對話出處,依 M36(a) 標為來源不明,不得再當成 user 拍板引用。** 2026-09-24 這一行一度被改寫成「按鈕本身仍 sm」並直接覆蓋掉原字 —— 兩句語意不同(一句講命中/觸控,一句講按鈕盒),而改寫沒有任何揭露。已還原為原字。要動引號內的字,只能拿得出對話原文才動
134
+ - `min-h-chrome-header-height` fixed wrapper 會鎖死高度,**bounded button 失去自然長高能力**(違反上一條的意圖 —— 同樣是 AI 推導,引不出 user 原話)
135
+ - 負 margin:button render / 命中區不變,僅影響 parent flex layout 計算 → 剛好是這裡要的「layout 24,視覺 / 命中 28」(AI 推導的設計目標,引不出 user 原話)
136
+
137
+ **Consumer 使用方式**:
138
+
139
+ ```tsx
140
+ // Dialog / Sheet / Popover / Coachmark(透過 SurfaceHeader)
141
+ <Button data-dismiss iconOnly dismiss size="sm" startIcon={X} aria-label="關閉" />
142
+ // `dismiss` prop → Button 自動標 `data-unbounded`(縮位 trick 判定詞);`data-dismiss` 用途不同,
143
+ // 是 openAutoFocus 排除 marker(popover.tsx / dialog.tsx autofocus selector)。
144
+ // SurfaceHeader 自動套負 my,無需 consumer 手動 y 調整
145
+
146
+ // Header 若塞 bounded button(primary sm)→ Button 不自動標 `data-unbounded`,不套負 my → 自然長高
147
+ <Button variant="primary" size="sm">套用</Button>
148
+
149
+ // Notification banner(Notice / Alert / Toast):px-4 py-3 fixed,dismiss 用 xs 簡化(無 margin trick)
150
+ <Button iconOnly dismiss size="xs" startIcon={X} aria-label="關閉通知" />
151
+ ```
152
+
153
+ **Consumer 實際高度範例**:
154
+ - Dialog header 只有 title + close X(sm,`dismiss` → 自動 `data-unbounded`)→ layout 佔位 24 → header = 48 md / 56 lg ✓
155
+ - Dialog header 有 refresh/share(text variant)/ close(dismiss)sm → 全自動標 `data-unbounded` → 全部 layout 佔位 24 → header 仍 48/56
156
+ - Dialog header 塞 primary sm(bounded,無 `data-unbounded`)→ primary layout 佔 28 → header = 52 md(自然長)
157
+ - Popover header 同 pattern:48 md / 56 lg
158
+
159
+ **Rationale**:Unbounded 無 bg/border → 2×py-tight 過大,縮 layout 佔位至 xs(24)讓 header = chrome-header-height = 48 自然閉合,跟 Sidebar / page header / top bar 對齊。Bounded 自帶視覺重量,自然長到 52+,跟 footer 一致。
160
+
161
+ **共通 rationale**(全 overlay + banner 家族):corner close X 屬 **action group region**,必用 `<Button>` primitive(不自刻 `<button><X /></button>` 繞 DS token / a11y,不用 `ItemInlineActionButton`)。
162
+
163
+ **本 session 震盪歷史備忘(M12 FP 記憶)**:
164
+ - ❌ v1「chrome dismiss 全 xs(DS-wide 統一)」→ 錯:過度簡化 rationale
165
+ - ❌ v2「三家族 modal sm / non-modal xs / banner xs」→ 錯:overlay 內部不必分化
166
+ - ❌ v3「overlay 統一 sm + min-h chrome-header-height 強鎖 48/56」→ 錯:強鎖會讓 bounded button 被鎖死 slot
167
+ - ❌ v4「padding-based + unbounded=xs / bounded=natural」→ 錯:xs 縮小 button 連命中區也縮到 24,與 chrome 的 28 失衡(違反上方「touch 仍 sm」那條 AI 推導的意圖、不是 user 原話 —— 2026-09-27 依 N23 註明;**不是 a11y 問題**,見上方「為什麼用負 margin 而非 fixed wrapper / size="xs"」)
168
+ - ✅ v5「padding-based + unbounded `data-unbounded` 套負 my(native size sm 不變)/ bounded natural」→ 對:button native size 與命中區保 sm,僅 layout 佔位縮回 24,48/56 chrome-header-height 自然達成
169
+
170
+ **SSOT 關聯**:
171
+ - `tokens/uiSize/uiSize.spec.md`「--chrome-header-height」+ `globals.css` 聲明(md=3rem / lg=3.5rem)
172
+ - `tokens/layoutSpace/layoutSpace.spec.md` tight = 12 md / 16 lg
173
+ - `patterns/element-anatomy/inline-action.spec.md`「Dismiss canonical — X close only」
174
+ - `components/Button/button.spec.md`「Dismiss 視覺類」+ unbounded / bounded 判斷
175
+
176
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
177
+
178
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
179
+
180
+ - `overlay-surface.spec.md`
@@ -227,7 +227,7 @@ item 沒有底色時只驗第 2 題(content 對齊 header title);沒有底色**
227
227
  > **不要 → `SurfaceFooter`**(內容左緣對齊**這個浮層的內容左邊界**,見下方「要對齊誰」)
228
228
 
229
229
  判準是「**誰負責左右 gutter**」—— 跟 `../element-anatomy/item-anatomy.spec.md`「Token: `--item-px`」是同一條線:
230
- 列自己帶 gutter 所以容器給 0;按鈕自己沒有 gutter 所以容器給 `loose`。兩者相加就是 2026-09-17 那次 28px 的病。
230
+ 列自己帶 gutter 所以容器給 0;按鈕自己沒有 gutter 所以容器給 `loose`。兩者相加就是 2026-09-17 那次 28px 的病。同一條線也管 body:FileItem `surface="upload-manager"` 的上傳列可點時整列滑過、底色鋪到面板左右邊 → 列自帶 `loose`、面板 body 左右 0(2026-09-25 待辦總帳 B12,推翻 06-03 的「左右交給面板」;owner `../../components/FileItem/file-item.spec.md`「upload-manager 浮層面板 composition」)。
231
231
 
232
232
  | | `SurfaceFooter` | 列式 footer |
233
233
  |---|---|---|
@@ -310,166 +310,9 @@ DatePicker **不是**例外 —— 它的日曆格線有左緣,footer 的預設
310
310
 
311
311
  ---
312
312
 
313
- ## Overlay title typography canonical(modal vs non-modal 分級,2026-04-22)
313
+ ## Overlay chrome 分級尺寸 → `overlay-chrome-sizing.spec.md`(2026-09-27 抽出,獨立 SSOT)
314
314
 
315
- Overlay family 的 header title typography 依「modal vs non-modal」分級,**跟 chrome padding / dismiss behavior 同 rationale(modal 重量級 vs non-modal 輕量)**:
316
-
317
- | 家族 | Title typography | 套用元件 |
318
- |------|------------------|---------|
319
- | **Modal**(阻斷互動)| `text-body-lg font-medium truncate`(**16px**)| `Dialog` / `Sheet` |
320
- | **Non-modal**(可忽略)| `text-body font-medium truncate`(**14px**)| `Popover` / `Coachmark` |
321
-
322
- **Rationale**:
323
- - **Modal**:title 是決策 anchor,user 必須 process → 需視覺重量(16px + 重字重)
324
- - **Non-modal**:title 是輔助標籤,user 可忽略 → 輕量字級(14px)不搶 body content
325
-
326
- **世界級對照**(7 家 DS 同 split): <!-- @benchmark-unverified -->
327
- | DS | Modal title | Non-modal popover title |
328
- |----|-------------|------------------------|
329
- | Material M3 | Headline 24 / body 16 | Smaller 14-16 |
330
- | Polaris | Modal 大 | Popover 較小 |
331
- | Atlassian | Modal 大 | InlineDialog 小 |
332
- | Notion | 16+ | 14 |
333
- | Linear | 16 | 14 |
334
- | Figma | 16 | 13-14 |
335
- | GitHub Primer | 16 | 14 |
336
-
337
- **跟「density 鎖 md」同源**:Popover / Coachmark 把「輕量」貫穿 chrome:density 鎖 md + chrome button 透過 v5 unbounded trick 縮 layout + **title 小一級**。三件一起構成「輕量浮層」視覺語言,跟 Modal heavy 形成明確分化。
338
-
339
- **禁止**:consumer 自刻 `<h2 className="text-body-lg">` 繞 `PopoverTitle` — 若需要大 title 代表該用 Dialog 而非 Popover(選錯元件)。
340
-
341
- **SSOT**:
342
- - `components/Popover/popover.spec.md`「Title typography canonical(non-modal 特化)」(Popover 專用細節)
343
- - `components/Dialog/dialog.spec.md`「Title」(Modal 專用細節)
344
-
345
- ---
346
-
347
- ## 為什麼 SurfaceHeader 是 padding-based(而非 fixed-h)(2026-04-22 設計原則)
348
-
349
- **SurfaceHeader 永遠 padding-based**(`py-tight`,不鎖固定高度)。Header 高度 = `max(title line-height, button slot)+ 2×py`,**slot 設計為 ≤ title line-height** 讓 title 主導 → header 高度 = title 決定(slot 縮位 / CSS var 參數化等實作細節詳下方「Chrome dismiss size canonical」)。SurfaceFooter **不**套 unbounded slot trick(僅 padding + `border-t`,慣例放 bounded action buttons)。**語義宣告**:
350
-
351
- **Padding-based 宣告**:「本 chrome **可以成長** — title 可換行、可附 subtitle / description」。適用 overlay family(Dialog / Sheet / Popover / Coachmark),這些都是 modal/semi-modal 情境,title 有可能長(例如「確認要永久刪除 Marketing Q4 Campaign 這個專案嗎?」兩行 title),或有 subtitle(「這個操作無法復原」補充說明)。
352
-
353
- **Fixed-height 宣告**:「本 chrome **永遠單行固定結構** — 不會長高」。適用 chrome 類如 Sidebar / FileViewer toolbar / app top bar,這些 chrome 的內容是 logo / icons / 短固定 label,不會 grow。
354
-
355
- **兩者視覺上在單行 content 時都是 48/56,但是不同的設計宣告**:
356
- - 若 Dialog 用 fixed-h,未來塞兩行 title / subtitle 會被剪掉 → 違反 modal 作為「完整決策 context」的職責
357
- - 若 Sidebar 用 padding-based,chrome 可能在長 label 時變動 → 違反 sidebar chrome「剛性佈局」的職責
358
-
359
- **判斷 tree**:問「這個 chrome 的 title 有可能多行 / 有 subtitle / 有 description 嗎?」
360
- - **會** → padding-based(SurfaceHeader 或自刻 py-tight)
361
- - **不會** → fixed-h(`h-[var(--chrome-header-height)]`)
362
-
363
- **完整 canonical + 世界級對照**:`tokens/uiSize/uiSize.spec.md`「Chrome header 選型 canonical」節(含「2 種 pattern 對照」)
364
-
365
- ---
366
-
367
- ## Size canonical(per-overlay default size SSOT,2026-05-04)
368
-
369
- > **背景**:Popover / HoverCard 是「輕量浮層」(chrome 45 / slot 21 / title 小一級 / density 鎖 md);Dialog / Sheet 是「heavy commitment chrome」(chrome 48 / slot 24)。Per-surface body+footer button/field default size 跟「輕量 vs heavy」分化對應。
370
- >
371
- > **依據**:Linear / Notion / Airtable / Carbon / Material Menu / Atlassian Popup popover bodies 共識用 sm-density;Material AlertDialog / Carbon Modal / shadcn Dialog 共識用 md。world-class 雙派分明依「浮層密度」分。 <!-- @benchmark-unverified -->
372
-
373
- | Overlay | Header chrome | Body field controls | Body inline action(drag handle / trash / +CTA)| Footer action Buttons |
374
- |--|--|--|--|--|
375
- | **Popover** | unbounded sm → 21 slot(輕)| **sm**(輕量 dense info)| inline-action sm/md = **16+18** | **sm** |
376
- | **HoverCard** | (同 Popover)| **sm** | 同 | **sm** |
377
- | **Dialog** | unbounded sm → 24 slot | **md** | inline-action sm/md = 16+18 | **md** |
378
- | **Sheet** | (同 Dialog)| **md** | 同 | **md** |
379
- | **BulkActionBar** | N/A | N/A | N/A | **md**(default footer placement);未來 top-toolbar variant → sm |
380
-
381
- **核心 invariant**:overlay surface 內 **body field controls + footer Buttons 同一 size**(per-surface 一致)。違反 = 視覺重量割裂。
382
-
383
- **為什麼 Popover all-sm 而非 mix**:Popover 整體已是「輕量浮層」設計語言(chrome 短、title 小、density 鎖 md)。如果 body 用 md fields(32 高)+ footer sm Buttons(28 高),視覺重量割裂破壞「輕量」一致性。**all-sm 是內部一致性**(body 28 / footer 28 同高,延伸 chrome 輕一級的密度)。
384
-
385
- **為什麼 Dialog all-md 而非 mix**:Dialog 是 heavy commitment chrome,body 操作往往 form-heavy,md (32) 是 Field family default(`--field-height-md` SSOT),footer Buttons 同 md commit 視覺重量配得上 modal 結論性。
386
-
387
- **Drag handle / inline-action sizing**(對齊 `patterns/element-anatomy/inline-action.spec.md`):
388
- - Field sm/md 同 row → inline action **16 icon / 18 hover bg**
389
- - Field lg 同 row → inline action **20 icon / 22 hover bg**
390
-
391
- 亦即:在 Popover(field=sm)或 Dialog(field=md)body 內,inline action 都同樣 16+18,差別只在 lg-density 場景。
392
-
393
- ---
394
-
395
- ## Chrome dismiss size canonical
396
-
397
- **User 設計 insight**:header 的 padding-based sizing 在 **unbounded button**(text variant / dismiss,無 bg/border)場景視覺 padding 過大;在 **bounded button** 則剛好。解法 = **保持 button native size 不變(touch target / 視覺 render 都是 sm 原尺寸),但 layout 佔位縮到 title line-box(24,衍生自 --font-body-lg-size×1.5)** via 負 margin。
398
-
399
- **Canonical**:button native size **保留 sm**(touch target / 視覺 render 不動);**unbounded 的靠 CSS 負 my 把 layout 佔位縮到 `--chrome-slot-h`** ≤ title line-height,讓 title 主導 chrome 高度。
400
-
401
- | Button 類型 | 判定(button.tsx L426-427)| Trick 套用 | Layout 佔位 | Dialog/Sheet header (slot 24)| Popover header (slot 21)|
402
- |--|--|--|--|--|--|
403
- | **Unbounded** | `variant === 'text'` OR `dismiss` → `data-unbounded="true"` | ✓ 套負 my | = `var(--chrome-slot-h)` | max(24, 24) + py-tight = **48** | max(21, 21) + py-tight = **45** |
404
- | **Bounded** | `primary` / `tertiary` / `outline` 等(有 bg/border) | ✗ 不套 | = native sm (28 md / 32 lg) | max(24, 28) + py-tight = **52**(自然長)| max(21, 28) + py-tight = **52**(自然長)|
405
-
406
- **為什麼差別**:Unbounded 沒視覺邊界 → native 28 是純 hit-target padding,縮 layout 不損視覺;Bounded 的 bg/border 就是內容,縮會切掉 → 必須讓 chrome 自然長高,**這是設計宣告「此 chrome 有重要 action,視覺重量該配得上」**。
407
-
408
- **實作**:
409
-
410
- ```tsx
411
- // button.tsx ── 自動標記 data-unbounded
412
- const unboundedAttr = resolvedVariant === 'text' || dismiss ? { 'data-unbounded': 'true' } : {}
413
-
414
- // overlay-surface.tsx ── slot 透過 CSS var 參數化(2026-05-04 v3;2026-06-16 default 改衍生)
415
- const CHROME_UNBOUNDED_SLOT =
416
- '[&_[data-unbounded]]:my-[calc((var(--chrome-slot-h,calc(var(--font-body-lg-size)*1.5))-var(--field-height-sm))/2)]'
417
-
418
- // SurfaceHeader default → slot 衍生自 title typography = calc(--font-body-lg-size × 1.5) = 24
419
- // (2026-06-16:從寫死 field-height-xs 改衍生 → title 字級改了 slot 自動跟、不靠巧合;M17 SSOT;
420
- // 1.5 = typography.spec body 行高常數,非 token 故 inline,body 行高改須同步)
421
- // Popover-tier override → COMPACT_HEADER_SLOT(= calc(--font-body-size × 1.5) = 21,衍生自 text-body title)
422
- // 公式 = (slot - native) / 2 ── Dialog md: (24-28)/2 = -2px / Popover md: (21-28)/2 = -3.5px
423
- ```
424
-
425
- **覆蓋範圍**:
426
- - Dismiss X(`<Button dismiss />`)→ data-unbounded ✓
427
- - Text variant action(`<Button variant="text" />` 如 Share / Refresh / Settings)→ data-unbounded ✓
428
- - 所有無視覺邊界的 button,不限 dismiss
429
-
430
- **為什麼用負 margin 而非 fixed wrapper / size="xs"**:
431
- - `size="xs"` 會縮小 button 本身,**touch target 也變 24**(違反 a11y 最小 24+ hit target,也違反 user 意圖「touch 仍 sm」)
432
- - `min-h-chrome-header-height` fixed wrapper 會鎖死高度,**bounded button 失去自然長高能力**(違反 user 意圖)
433
- - 負 margin:button render / touch target 不變,僅影響 parent flex layout 計算 → 剛好 user 想要的「layout 24,視覺 / 觸控 28」
434
-
435
- **Consumer 使用方式**:
436
-
437
- ```tsx
438
- // Dialog / Sheet / Popover / Coachmark(透過 SurfaceHeader)
439
- <Button data-dismiss iconOnly dismiss size="sm" startIcon={X} aria-label="關閉" />
440
- // `dismiss` prop → Button 自動標 `data-unbounded`(縮位 trick 判定詞);`data-dismiss` 用途不同,
441
- // 是 openAutoFocus 排除 marker(popover.tsx / dialog.tsx autofocus selector)。
442
- // SurfaceHeader 自動套負 my,無需 consumer 手動 y 調整
443
-
444
- // Header 若塞 bounded button(primary sm)→ Button 不自動標 `data-unbounded`,不套負 my → 自然長高
445
- <Button variant="primary" size="sm">套用</Button>
446
-
447
- // Notification banner(Notice / Alert / Toast):px-4 py-3 fixed,dismiss 用 xs 簡化(無 margin trick)
448
- <Button iconOnly dismiss size="xs" startIcon={X} aria-label="關閉通知" />
449
- ```
450
-
451
- **Consumer 實際高度範例**:
452
- - Dialog header 只有 title + close X(sm,`dismiss` → 自動 `data-unbounded`)→ layout 佔位 24 → header = 48 md / 56 lg ✓
453
- - Dialog header 有 refresh/share(text variant)/ close(dismiss)sm → 全自動標 `data-unbounded` → 全部 layout 佔位 24 → header 仍 48/56
454
- - Dialog header 塞 primary sm(bounded,無 `data-unbounded`)→ primary layout 佔 28 → header = 52 md(自然長)
455
- - Popover header 同 pattern:48 md / 56 lg
456
-
457
- **Rationale**:Unbounded 無 bg/border → 2×py-tight 過大,縮 layout 佔位至 xs(24)讓 header = chrome-header-height = 48 自然閉合,跟 Sidebar / page header / top bar 對齊。Bounded 自帶視覺重量,自然長到 52+,跟 footer 一致。
458
-
459
- **共通 rationale**(全 overlay + banner 家族):corner close X 屬 **action group region**,必用 `<Button>` primitive(不自刻 `<button><X /></button>` 繞 DS token / a11y,不用 `ItemInlineActionButton`)。
460
-
461
- **本 session 震盪歷史備忘(M12 FP 記憶)**:
462
- - ❌ v1「chrome dismiss 全 xs(DS-wide 統一)」→ 錯:過度簡化 rationale
463
- - ❌ v2「三家族 modal sm / non-modal xs / banner xs」→ 錯:overlay 內部不必分化
464
- - ❌ v3「overlay 統一 sm + min-h chrome-header-height 強鎖 48/56」→ 錯:強鎖會讓 bounded button 被鎖死 slot
465
- - ❌ v4「padding-based + unbounded=xs / bounded=natural」→ 錯:xs 縮小 button 連 touch target 也變 24(違反 a11y / user 意圖)
466
- - ✅ v5「padding-based + unbounded `data-unbounded` 套負 my(native size sm 不變)/ bounded natural」→ 對:button native size 與 touch target 保 sm,僅 layout 佔位縮回 24,48/56 chrome-header-height 自然達成
467
-
468
- **SSOT 關聯**:
469
- - `tokens/uiSize/uiSize.spec.md`「--chrome-header-height」+ `globals.css` 聲明(md=3rem / lg=3.5rem)
470
- - `tokens/layoutSpace/layoutSpace.spec.md` tight = 12 md / 16 lg
471
- - `patterns/element-anatomy/inline-action.spec.md`「Dismiss canonical — X close only」
472
- - `components/Button/button.spec.md`「Dismiss 視覺類」+ unbounded / bounded 判斷
315
+ 「Overlay title typography canonical」(modal 16 / non-modal 14)、「為什麼 SurfaceHeader 是 padding-based(而非 fixed-h)」、「Size canonical」(per-overlay body 控件與 footer 按鈕尺寸)、「Chrome dismiss size canonical」(`data-unbounded` 負 margin 縮位、v1–v5 震盪歷史)四節整段住在 `./overlay-chrome-sizing.spec.md`;本檔只留這個指標。
473
316
 
474
317
  ---
475
318
 
@@ -544,8 +387,8 @@ border-l border-divider">`)/ Atlassian `modal-dialog/examples/101-full-height-il
544
387
 
545
388
  overlay-surface 是 **layout pattern**(`SurfaceHeader` / `SurfaceBody` / `SurfaceFooter`),不持有互動行為 — a11y 大宗在 consumer overlay primitive(Dialog / Sheet / Popover / HoverCard)上,由 Radix 處理:
546
389
 
547
- - **Role + ARIA**:`Dialog.Content` / `Sheet.Content`(皆 wrap Radix Dialog)自帶 `role="dialog"` + `aria-labelledby`(連 DialogTitle id)+ `aria-describedby`(optional Description)。**modality 機制**:Radix 不發 `aria-modal` 屬性,而是用 `hideOthers`(把背景 sibling subtree 套 `aria-hidden`)+ `RemoveScroll` 達成 modal — 對齊 WAI-ARIA APG「aria-hidden on background content」做法(APG 指出 `aria-modal` 的 AT 支援不一致,hideOthers 較穩健)。`Popover.Content` 同樣 wrap Radix(non-modal,Radix `modal` 預設 false)且**也帶** `role="dialog"`(Radix non-modal dialog,APG sanctioned)——但**不** trap focus、**不**自動 `aria-labelledby`(consumer 需自設 `aria-label`)。`HoverCard.Content` 才是真的**無 role**(Radix react-hover-card 不發任何 role)
548
- - **Focus trap**:Dialog / Sheet 自帶 modal focus trap;Popover / HoverCard 不 trap(non-modal canonical)
390
+ - **Role + ARIA**:`Dialog.Content` / `Sheet.Content`(皆 wrap Radix Dialog)自帶 `role="dialog"` + `aria-labelledby`(連 DialogTitle id)+ `aria-describedby`(optional Description)。**modality 機制**:Radix 不發 `aria-modal` 屬性,而是用 `hideOthers`(把背景 sibling subtree 套 `aria-hidden`)+ `RemoveScroll` 達成 modal — 對齊 WAI-ARIA APG「aria-hidden on background content」做法(APG 指出 `aria-modal` 的 AT 支援不一致,hideOthers 較穩健)。`Popover.Content` 同樣 wrap Radix(non-modal,Radix `modal` 預設 false)且**也帶** `role="dialog"`(Radix non-modal dialog,APG sanctioned)——Tab 在面板裡繞圈但滑鼠點外面可離開(見下一條)、**不**自動 `aria-labelledby`(consumer 需自設 `aria-label`)。`HoverCard.Content` 才是真的**無 role**(Radix react-hover-card 不發任何 role)
391
+ - **Focus trap / Tab 走向**(2026-09-25 更正,原句「Popover / HoverCard 不 trap」被讀成 Tab 可以走出 Popover,與實測不符;待辦總帳 B11):**對話框型浮層 Tab 留在裡面** —— Dialog / Sheet 是 modal trap(Tab 繞圈,滑鼠點外面也出不去);Popover 是 non-modal:Tab / Shift+Tab 同樣在面板裡繞圈(Radix FocusScope `loop: true`,`@radix-ui/react-popover` 1.1.15 `dist/index.mjs:225-226`),只是滑鼠點外面 / 程式移焦可離開並關閉。依據 W3C「Like non-modal dialogs, modal dialogs contain their tab sequence.」(<https://github.com/w3c/aria-practices/blob/3f094fde1c81b25dfa69162563bf28d093f854d4/content/patterns/dialog-modal/dialog-modal-pattern.html#L29-L30>)。**選單類浮層 Tab = 收起並往下走**(DropdownMenu、單選下拉;規則在 `components/SelectMenu/select-menu.spec.md`「A11y 預設」與 `components/DropdownMenu/dropdown-menu.spec.md`)。HoverCard 焦點不進卡片(Radix 把卡片內可 Tab 節點設 `tabindex="-1"`),Tab 從觸發元素照頁面順序走
549
392
  - **Esc / 點外面關閉**:Radix 處理(可被 `onEscapeKeyDown` / `onPointerDownOutside` 攔截)
550
393
  - **AutoFocus on open**:consumer 自管 `onOpenAutoFocus`(Popover 範例:`handlePopoverOpenAutoFocus` 找 body 第一個 interactive 元素,跳過 close X 避免 tooltip leak)
551
394
 
@@ -583,11 +426,14 @@ overlay-surface 是 **layout pattern**(`SurfaceHeader` / `SurfaceBody` / `Surfac
583
426
 
584
427
  - `app-shell.spec.md`
585
428
  - `coachmark.spec.md`
429
+ - `date-picker.spec.md`
586
430
  - `dialog.spec.md`
587
431
  - `element-anatomy.spec.md`
588
432
  - `file-item.spec.md`
589
433
  - `header-canonical.spec.md`
434
+ - `item-anatomy.spec.md`
590
435
  - `motion.spec.md`
436
+ - `overlay-chrome-sizing.spec.md`
591
437
  - `popover.spec.md`
592
438
  - `sheet.spec.md`
593
439
  - `time-picker.spec.md`
@@ -27,9 +27,11 @@ import { HEADER_TABS_SLOT_WRAPPER_CLASS } from '@/design-system/patterns/header-
27
27
  * ── Unbounded controls 在 header canonical(v5 trick,2026-04-22)──
28
28
  * Dismiss X(always unbounded)+ text variant header action → **`size="sm"` native**
29
29
  * + SurfaceHeader CSS 自動套負 my trick(對 `[data-unbounded]`),layout 佔位縮回 24
30
- * (xs 等同)。Rationale:button native size 跟 touch target 保留 sm(a11y 最小 24+ hit
31
- * target,視覺 render 仍 28/32),layout 佔位精確匹配 chrome-header-height 幾何。詳
32
- * `overlay-surface.spec.md`「Chrome dismiss size canonical」。
30
+ * (xs 等同)。Rationale:button native size 跟命中區保留 sm(視覺 render 仍 28/32,命中 ≡ 可視
31
+ * → `ds-canonical/references/hit-area-canonical.md`),layout 佔位精確匹配 chrome-header-height 幾何。
32
+ * 縮到 xs 的問題是**與 chrome 的比例**(chrome dismiss 是 sm = 28),不是 a11y —— 24 正好是
33
+ * `tokens/uiSize/uiSize.spec.md`「元件高度地板」訂的最小值。詳
34
+ * `overlay-chrome-sizing.spec.md`「Chrome dismiss size canonical」(2026-09-27 自 `overlay-surface.spec.md` 拆出)。
33
35
  *
34
36
  * **Notification banner family**(Notice / Alert / Toast,fixed `px-4 py-3` variant,
35
37
  * 無 padding-based header)→ dismiss 用 `size="xs"` explicit(24 固定,無 trick)。
@@ -64,11 +64,11 @@ benchmark:
64
64
 
65
65
  取值依據:7px 命中區 / 1px line 非自創——來自下方「世界級對照細節」5 家共識(hit zone 7-8px fingertip-friendly / 1px line non-intrusive)+ DataTable v11 已 ship 的既有 canonical(本 primitive 抽取自它,M17)。
66
66
 
67
- - **命中區**:7px 寬(horizontal)/ 高(vertical),`-3px` outward offset 跨 boundary 抓得到。**外側 3px 必須真的抓得到**(2026-09-10):primitive 給命中區 `z-index: 1`,否則 DOM 順序在後的 positioned 鄰居會蓋住它;消費端的容器不得用 `overflow: hidden` 裁到它(要抑制 flex `min-width: auto` 時改 `min-w-0`)。面板 / 捲動容器的邊界把它裁掉是預期例外(AG Grid 同)。世界級:AG Grid `.ag-header-cell-resize{position:absolute;z-index:2;width:8px;right:-3px}`(https://unpkg.com/ag-grid-community/styles/ag-grid.css)、MUI X `columnSeparator` `position:'absolute', zIndex:30, right:-5`、目標寬 10(https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/components/containers/GridRootStyles.ts)、VS Code `.monaco-sash{position:absolute;z-index:35}`(https://github.com/microsoft/vscode/blob/main/src/vs/base/browser/ui/sash/sash.css)。閘:`scripts/data-table-pinned-resize-invariant.mjs` R3(欄界兩側各 2px 都要命中把手;`--selftest` 注入 overflow:hidden / z-index:auto 必紅)。
67
+ - **命中區**:7px 寬(horizontal)/ 高(vertical),`-3px` outward offset 跨 boundary 抓得到。**外側 3px 必須真的抓得到**(2026-09-10):primitive 給命中區 `z-index: 1`,否則 DOM 順序在後的 positioned 鄰居會蓋住它;消費端的容器不得用 `overflow: hidden` 裁到它(要抑制 flex `min-width: auto` 時改 `min-w-0`)。面板 / 捲動容器的邊界把它裁掉是預期例外(AG Grid 同)。世界級:AG Grid `.ag-header-cell-resize{position:absolute;z-index:2;width:8px;right:-3px}`(https://unpkg.com/ag-grid-community/styles/ag-grid.css)、MUI X `columnSeparator` `position:'absolute', zIndex:30, right:-5`、目標寬 10(https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/components/containers/GridRootStyles.ts)、VS Code `.monaco-sash{position:absolute;z-index:35}`(https://github.com/microsoft/vscode/blob/main/src/vs/base/browser/ui/sash/sash.css)。閘:`scripts/data-table-pinned-resize-invariant.mjs` R3(欄界兩側各 2px 都要命中把手;`--selftest` 注入 overflow:hidden / z-index:auto 必紅);AgentPanel 左緣把手同款,`scripts/agent-panel-breakpoint.mjs`「OE1 把手外側」(面板根節點 2026-09-29 由 `overflow-hidden` 改 `overflow-y-clip` + `min-w-0`,外側 2px 必命中;對照組注入 overflow:hidden 必紅)。
68
68
  - **Indicator**:消費既有 DataTable resize indicator contract,預設覆蓋完整可調整邊;確切 thickness / offset 與 source utility 由 `resize-handle.tsx` 擁有
69
69
  - **idle**:`bg-divider`
70
70
  - **disabled**:`bg-divider`(無 hover affordance)
71
- - **hover**:`bg-[var(--border-hover)]`(via `group/resize` selector)
71
+ - **hover**:`bg-[var(--border-hover)]`(via `group/resize` selector)。**為什麼靜止 `--divider`(neutral-4)滑過跳到 `--border-hover`(neutral-6)而不是下一階**(2026-09-27 補寫;待辦總帳 A8,2026-09-25 R17 篩為「保留、規格補理由」,**AI 推導、未逐題經 user 拍板**):把手線是 `ds-canonical/references/hit-area-canonical.md`「唯一例外」那種**先天只有 1px 寬的線**,滑過只走一階(neutral-4 → 5)在 1px 上幾乎看不出來,回饋等於沒有;世界級同樣直接跳到強調色 —— MUI X 欄分隔線滑過與拖拉中都直接換成 `vars.colors.foreground.accent`(一手:[`GridRootStyles.ts`](https://github.com/mui/mui-x/blob/master/packages/x-data-grid/src/components/containers/GridRootStyles.ts) `columnSeparator` 的 `'&:hover': { color: vars.colors.foreground.accent }` 與 `columnSeparator--resizing` 同值,2026-09-27 讀 master;待辦總帳記的 `:482-485` 是較早版本的行號)、AG Grid 拖拉中 1px 主色(下方「世界級對照細節」表)。本 DS 的折衷:滑過跳到 `--border-hover`(消費 Field 邊框滑過那一階,不自創值)、拖拉中才用主色。`scripts/hover-own-pair-baseline.json` 兩筆 resize-handle 命中因此登記為 `documented`(理由住這一條),`scripts/data-table-pinned-resize-invariant.mjs` R4 量的懸停值 = `--border-hover` 維持不變。
72
72
  - **dragging**:`bg-primary`(拖拉中由元件自己判定 —— pointerdown 到 pointerup / cancel;沒有 `isResizing` prop,舊寫法已更正 2026-09-10)
73
73
  - **idle 線的歸屬**(2026-09-10,user 抓「釘選欄位 resize 時分隔線沒有變藍」):`showLine=false` 只把 **idle** 線交給消費端(DataTable 面板邊界欄由凍結邊界線 `dtPanelBoundaryRight::after` 畫、表格外框欄由外框畫),**hover 與拖拉的狀態色仍由本元件畫**,畫在同一個像素上 —— 左釘選面板的邊界線在面板最後一個像素、與把手線同位,狀態色剛好蓋在它上面;右釘選面板的邊界線與外框在鄰面板 / 外框那一像素,把手線只能畫在自己面板內側相鄰的一像素(面板 `overflow` 裁切,越界不可見),拖拉中看起來是「主色線緊貼灰線」。舊行為:`showLine=false` 連狀態色一起不畫,面板邊界欄拖拉中沒有任何回饋 = 違反本表。閘:`scripts/data-table-pinned-resize-invariant.mjs` R4(釘選邊界欄拖拉中把手線 = primary、放開後回透明)。
74
74
  - **Cursor**:`col-resize` / `row-resize`(`disabled` 時無)
@@ -76,7 +76,7 @@ benchmark:
76
76
 
77
77
  ## a11y
78
78
 
79
- - `role="separator"` + `aria-orientation`(horizontal 拖拉 → `vertical` 分隔線)+ `aria-valuenow / aria-valuemin / aria-valuetext="Npx"`(+ 有上限才 `aria-valuemax`;無上限時 valuetext 避免被讀成百分比)+ `aria-label` 必填;`tabIndex=0`;focus-visible = `outline-2 outline-offset-[-2px] outline-ring`(DataTable 既有字串)。
79
+ - `role="separator"` + `aria-orientation`(horizontal 拖拉 → `vertical` 分隔線)+ `aria-valuenow / aria-valuemin / aria-valuetext="Npx"`(+ 有上限才 `aria-valuemax`;無上限時 valuetext 避免被讀成百分比)+ `aria-label` 必填;`tabIndex=0`;焦點框 = `focus-visible:focus-ring-inset`(內描邊,往內 2px;`resize-handle.tsx:243`)。
80
80
  - 鍵盤:←/→(horizontal)或 ↑/↓(vertical)每步 `step`、Home = min、End = max(有上限才);命中的鍵 preventDefault + stopPropagation(不冒泡到排序 / 欄位拖曳)。
81
81
  - `disabled` = 只畫線:無 role / tabIndex / cursor,`aria-hidden`。
82
82
  - 對照 [APG Window Splitter](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/):Left/Right Arrow 移動垂直 splitter、Home/End 到極限。
@@ -47,7 +47,7 @@
47
47
  要改成往內畫的才加 `focus-ring-inset`(見下方 @utility)。 */
48
48
  :focus-visible {
49
49
  outline: 2px solid var(--ring);
50
- outline-offset: 2px;
50
+ outline-offset: var(--stack-gap); /* 2px;「疊在一起的兩樣東西」之間的縫,全 DS 同一個 token(tokens/uiSize/uiSize.css) */
51
51
  }
52
52
 
53
53
  /* 文字反白 — 底色 token 化(--text-selection;SSOT = color.spec.md「Highlight」段)。
@@ -131,7 +131,12 @@ export const CAT_SOLID_TOKENS: Record<CategoricalHue, { bg: string; text: string
131
131
  magenta: { bg: 'var(--color-magenta-6)', text: 'var(--on-emphasis)' },
132
132
  }
133
133
 
134
- /** Calendar event tile:subtle 底 + hover step-2(1:1)。 */
134
+ /**
135
+ * Calendar event tile:subtle 底 + hover step-2(1:1)。
136
+ * 淡底的滑過 = 同色離底更遠一格:淺色變深、深色變亮(色階號碼 = 離所在底色多遠;primitives.css 檔頭、
137
+ * color.spec.md「Dark mode subtle」)。與上方實心色互動 state 不同 —— 那是 semantic `--{hue}-hover`(深色要反轉),
138
+ * 這裡是淡底區 step-1 → step-2,兩主題同向,直接用 primitive(2026-09-26 深色 step-2..4 改半透明淡底後成立)。
139
+ */
135
140
  export const CAT_EVENT: Record<CategoricalHue, string> = {
136
141
  blue: 'bg-[var(--color-blue-1)] text-[var(--color-blue-7)] hover:bg-[var(--color-blue-2)]',
137
142
  green: 'bg-[var(--color-green-1)] text-[var(--color-green-7)] hover:bg-[var(--color-green-2)]',