@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
@@ -260,6 +260,55 @@ else
260
260
  FAIL=$((FAIL+1)); FAILED="${FAILED}\n - Test 12"
261
261
  fi
262
262
 
263
+ # Test 13: Check 12(2026-09-24)—— 產生檢視漏掉一群 hook 時,SessionStart 必須在 soft 通道印出提示(exit 0、不阻擋)。
264
+ # fixture 用**真實**的 provider-view-group-reachability-invariant.mjs 與它讀的每一份文件的原樣副本
265
+ # (腳本以自己所在目錄的上一層當 ROOT,所以整組搬進 TMP_PROJ 就能對 fixture 文件跑)。
266
+ # 儀器先有對照組:文件齊全時腳本本身要綠、hook 要安靜;之後才拿掉 claude 檢視 PreToolUse 最後一群,
267
+ # 要求 hook 點名該 event / 群組序號與失去覆蓋的 hook 名。序號與 hook 名都從 fixture 文件算,不寫死。
268
+ echo "Test 13: Check 12 provider 檢視漏群組 → SessionStart soft 提示"
269
+ setup_proj
270
+ REPO_ROOT_13="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel)"
271
+ REGISTRY_13="packages/governance/canonical/providers.json"
272
+ REACH_REG_13=$(jq -r '.canonical.hookRegistrations' "$REPO_ROOT_13/$REGISTRY_13")
273
+ CLAUDE_VIEW_13=$(jq -r '.providers[] | select(.id == "claude") | .hookConfig' "$REPO_ROOT_13/$REGISTRY_13")
274
+ REACH_VIEWS_13=$(jq -r '.providers[] | select(.capabilities.nativeHooks == true and .hookConfigFormat == "json") | .hookConfig' "$REPO_ROOT_13/$REGISTRY_13")
275
+ FIXTURE_OK_13=1
276
+ for f in scripts/provider-view-group-reachability-invariant.mjs scripts/lib/provider-runtime-contract.mjs \
277
+ packages/governance/src/provider-review-binding.mjs packages/governance/src/canonical-order.mjs \
278
+ "$REGISTRY_13" "$REACH_REG_13" $REACH_VIEWS_13; do
279
+ if [ ! -f "$REPO_ROOT_13/$f" ]; then
280
+ echo " FAIL Test 13 fixture source missing: $f"; FIXTURE_OK_13=0; break
281
+ fi
282
+ mkdir -p "$TMP_PROJ/$(dirname "$f")" && cp "$REPO_ROOT_13/$f" "$TMP_PROJ/$f"
283
+ done
284
+ if [ "$FIXTURE_OK_13" = "1" ]; then
285
+ # 對照組:文件齊全 → 真實腳本在 fixture 裡要綠,hook 要安靜(證明 fixture 本身不是紅的來源)
286
+ CONTROL_OUT_13=$(cd "$TMP_PROJ" && node scripts/provider-view-group-reachability-invariant.mjs 2>&1); CONTROL_RC_13=$?
287
+ run_hook
288
+ CONTROL_HOOK_EXIT_13="$EXIT"; CONTROL_HOOK_OUT_13="$STDOUT_TEXT"
289
+ # 弄壞:拿掉 claude 檢視 PreToolUse 最後一群;期望的群組序號 = 原群數 − 1,失去覆蓋的 hook 名從 registrations 讀
290
+ GROUPS_13=$(jq -r '.hooks.PreToolUse | length' "$TMP_PROJ/$CLAUDE_VIEW_13")
291
+ LOST_INDEX_13=$((GROUPS_13 - 1))
292
+ LOST_HOOK_13=$(jq -r --argjson i "$LOST_INDEX_13" '.hooks.PreToolUse[$i].hooks[0].hook' "$TMP_PROJ/$REACH_REG_13")
293
+ jq '.hooks.PreToolUse |= .[:-1]' "$TMP_PROJ/$CLAUDE_VIEW_13" > "$TMP_PROJ/view.tmp" && mv "$TMP_PROJ/view.tmp" "$TMP_PROJ/$CLAUDE_VIEW_13"
294
+ run_hook
295
+ if [ "$CONTROL_RC_13" = "0" ] && [ "$CONTROL_HOOK_EXIT_13" = "0" ] && [ -z "$CONTROL_HOOK_OUT_13" ] \
296
+ && [ "$EXIT" = "0" ] \
297
+ && echo "$STDOUT_TEXT" | grep -qF "本 session 有 hook 群組沒有派工入口" \
298
+ && echo "$STDOUT_TEXT" | grep -qF "[claude] PreToolUse 第 ${LOST_INDEX_13} 群" \
299
+ && echo "$STDOUT_TEXT" | grep -qF "失去覆蓋的 hook: ${LOST_HOOK_13}" \
300
+ && echo "$STDOUT_TEXT" | grep -qF "重開 session" \
301
+ && ! echo "$STDOUT_TEXT" | grep -q "BLOCKER"; then
302
+ echo " PASS Test 13 齊全時安靜;漏群組時 soft 點名 PreToolUse 第 ${LOST_INDEX_13} 群 + ${LOST_HOOK_13}"; PASS=$((PASS+1))
303
+ else
304
+ echo " FAIL Test 13 (control: script rc=$CONTROL_RC_13 hook exit=$CONTROL_HOOK_EXIT_13 out='${CONTROL_HOOK_OUT_13:0:120}'; broken: exit=$EXIT out='${STDOUT_TEXT:0:400}')"
305
+ FAIL=$((FAIL+1)); FAILED="${FAILED}\n - Test 13"
306
+ fi
307
+ else
308
+ FAIL=$((FAIL+1)); FAILED="${FAILED}\n - Test 13 (fixture source missing)"
309
+ fi
310
+ teardown_proj
311
+
263
312
  echo ""
264
313
  echo "════ Results: $PASS PASS, $FAIL FAIL ════"
265
314
  [ "$FAIL" -gt 0 ] && { printf "Failed:%b\n" "$FAILED"; exit 1; }
@@ -1,8 +1,10 @@
1
1
  # Canonical references charter
2
2
 
3
- ## 這裡只收:**agent infrastructure reference**(非 product canonical)
3
+ ## 這裡收兩類:**agent infrastructure reference**,以及**跨元件互動 canonical**(2026-09-26 更正)
4
4
 
5
- Agent 在執行時按需讀的深度 reference 檔 — audit protocol / FP 記憶 / workflow recipe / lookup tables。**不是 product design canonical**(那該進 spec.md / `packages/design-system/ds-canonical/rules/*.md`)。
5
+ Agent 在執行時按需讀的深度 reference 檔 — audit protocol / FP 記憶 / workflow recipe / lookup tables。**單一元件的 product design canonical 不在這裡**(那該進該元件 spec.md / `packages/design-system/ds-canonical/rules/*.md`)。
6
+
7
+ **2026-09-26 更正 —— 承認第二類住戶:跨元件互動 canonical**。`hit-area-canonical.md`(滑過原則與命中區)/ `focus-canonical.md`(鍵盤游標與焦點框)/ `keyboard-model-canonical.md`(鍵盤模型與彈出框的 Tab / Esc)/ `drag-canonical.md`(拖曳)四份**就是**跨元件的產品互動 canonical:owner 在這裡,各元件 `spec.md` 只放指標指回來(例:`date-grid.spec.md`、`steps.spec.md`、`sidebar.spec.md` 的命中區段、`file-item.spec.md` 的焦點框段全指回這四份)。理由:這類規則一次管全 DS、不屬於任何一個元件 —— 塞進某個元件的 spec 會變成第二份 SSOT(其他元件得抄),塞進 `rules/*.md` 又會被當成 path-scoped 的編輯規則而不是設計契約。舊 charter「不收 product canonical」的三句與下方 2026-04-24 Lesson 只對**單一元件**的判斷(24px threshold / disabled state / primitive exposure 那類)成立,先前沒把這一類寫出來,四份檔案實際上已經在這裡當 owner 卻與 charter 打架,故補上。條件:元件 spec **只准指標、不准另抄一份**;新的跨元件互動 canonical 也照這個形狀(一個能力、一份跨元件契約、與這四份同層級)。
6
8
 
7
9
  ## 當前居民
8
10
 
@@ -13,8 +15,10 @@ Agent 在執行時按需讀的深度 reference 檔 — audit protocol / FP 記
13
15
  | `composition-fidelity.md` | Composition fidelity SSOT — consumer 用對 DS(conformance)為主,靜態 lint 驗(對齊 Polaris/Atlassian/Carbon);pixel/DOM identity diff 改 opt-in(2026-06-02 model 修正,非追求 product-vs-showcase 一致) |
14
16
  | `cva-patterns.md` | cva 適用 / 不適用 + 例外清單(跟 canonical `packages/design-system/ds-canonical/rules/ui-development.md` shadcn 規範互補) |
15
17
  | `drag-canonical.md` | 現行 drag behavior/visual ownership、DataTable/TreeView 能力矩陣與保留中的未來擴充邊界 |
16
- | `focus-canonical.md` | 鍵盤游標與焦點指示的跨元件 SSOT — 誰能移動游標(只有鍵盤)、游標長什麼樣(有無「懸停→選中」兩段式決定框 vs 共用 focus)、內外描邊判準 |
18
+ | `focus-canonical.md` | 鍵盤游標與焦點指示的跨元件 SSOT — 誰能移動游標(只有鍵盤;已開啟的浮層選單是唯一例外,會搶反白的浮層選單與不搶的常駐清單兩類分開)、游標長什麼樣(一律畫框、不上底色;判準只有一題「是不是插入點控件」—— 2026-09-06 的「懸停→選中兩段式」判準已於 2026-09-09 撤回)、內外描邊判準(外 +2px / 放不下就內 −2px / 填色元素的白線) |
17
19
  | `failure-class-registry.json` | 被抓過的 failure class → mechanical defense/judgment audit 的封閉追蹤表 |
20
+ | `hit-area-canonical.md` | **滑過原則**的跨元件唯一住所(2026-09-26:滑過只為三件事 —— 告訴你能操作、叫出按鈕、給你看資訊;能點的元件「滑過有變化的位置點下去一定有反應、能點的地方不一定要變」;判斷順序四題)+ 可點範圍細則:懸停回饋的形狀 ≡ 命中區、唯一例外(線與點)的四個條件、外擴硬限制、DS 現況盤點 |
21
+ | `keyboard-model-canonical.md` | 一串東西該用 Tab 逐項走還是 Tab 一次進去再用方向鍵的跨元件 SSOT — 五條判準(節點可被施加動作 / 真需要 tree 鍵盤 / 深度無上界 / 內容由使用者產生可改動 / 啟動不保證換 URL,同時滿足才是樹)、「列上有小按鈕的一串」一串一站 + 方向鍵(2026-09-25 user 拍板路線乙)、彈出框開著時 `Tab` / `Esc` 的單一住所、`aria-current` ≠ `aria-selected`、撤回「有沒有選中狀態」「是不是連結」「在不在側邊欄」三條錯判準、宣告 composite 角色就必須實作那套鍵盤 |
18
22
  | `governance-audit-coverage.md` | 治理 home × 稽核機制 × 執行頻率覆蓋表 |
19
23
  | `item-anatomy-recipe.md` | 7 步建立新 row primitive workflow + audit grep guard |
20
24
  | `naming-conventions.md` | 命名詳表 + 禁止清單(AGENTS.md `# 命名與語言一致性` pointer) |
@@ -36,7 +40,7 @@ Agent 在執行時按需讀的深度 reference 檔 — audit protocol / FP 記
36
40
 
37
41
  | 疑似要放這但其實不是 | 正確去處 | 為什麼 |
38
42
  |---------------------|---------|--------|
39
- | 設計 canonical judgment(non-programmable)| `spec.md` 或 `packages/design-system/ds-canonical/rules/*.md` | 元件/模式語意進 spec,跨單元 path-scoped 規則進 canonical rules。AI 做產品時**必讀** spec,不會必讀 references |
43
+ | **單一元件**的設計 canonical judgment(non-programmable)| `spec.md` 或 `packages/design-system/ds-canonical/rules/*.md` | 元件/模式語意進 spec,跨單元 path-scoped 規則進 canonical rules。AI 做產品時**必讀** spec,不會必讀 references。**跨元件互動 canonical 是例外**(見上方 2026-09-26 更正):owner 在本目錄,元件 spec 放指標 |
40
44
  | 實作值 / 計算公式 | tsx / cva / CSS | programmable rule 進 code |
41
45
  | 跨 session 狀態 | `memory/` | references 不是 state 檔 |
42
46
  | 多步驟 workflow + checkpoint | `packages/design-system/ds-canonical/skills/` | skill 管 workflow,reference 是 skill 按需讀的;provider skill home 只是 generated discovery view |
@@ -44,9 +48,11 @@ Agent 在執行時按需讀的深度 reference 檔 — audit protocol / FP 記
44
48
  ## 新 reference 的 criteria
45
49
 
46
50
  1. **Audit / skill 按需查的 lookup data**(表格 / 詳細對照 / 反例清單)
47
- 2. **不含 canonical judgment**(判斷 rule 在 spec / `packages/design-system/ds-canonical/rules/*.md`)
51
+ 2. **不含單一元件的 canonical judgment**(那在該元件 spec / `packages/design-system/ds-canonical/rules/*.md`);**跨元件互動 canonical 例外**,條件是各元件 spec 只放指標指回來、不得另抄一份(2026-09-26 更正)
48
52
  3. **被 ≥ 1 skill / AGENTS.md / spec cite**(orphan file 不收,定期 prune 會 retire)
49
53
 
50
54
  ## 2026-04-24 Lesson
51
55
 
52
- 前曾把 canonical judgment(24px threshold / disabled state 策略 / primitive exposure 3 題)錯搬到 references,違反 2-home 架構(spec 該是 canonical home 讓 AI 做產品時讀)。Restored 回 spec。references 現在嚴格只收 agent-use lookup。
56
+ 前曾把 canonical judgment(24px threshold / disabled state 策略 / primitive exposure 3 題)錯搬到 references,違反 2-home 架構(spec 該是 canonical home 讓 AI 做產品時讀)。Restored 回 spec。references 當時嚴格只收 agent-use lookup。
57
+
58
+ **2026-09-26 補**:這條 Lesson 管的是**單一元件層級**的判斷(上面三個例子都只屬於一個元件或一個 primitive)。跨元件互動 canonical(hit-area / focus / keyboard-model / drag)不在此列 —— 它們沒有「該回去的那個 spec」,owner 就在本目錄,見上方更正。
@@ -74,7 +74,9 @@ TreeView、DataTable row 與 DataTable column 都使用 `@dnd-kit/core` 的
74
74
  故 SSOT 擁有的不是「一組鍵」而是**「情境 → 鍵位」對照表,每個分支各附世界級 cite**;
75
75
  消費者只宣告自己屬於哪個情境。這樣表格不是「例外」,而是命中對照表的另一列 —— 仍是 SSOT,不是分岔。
76
76
 
77
- 6. **Pointer 與鍵盤都要可完成合法操作**:TreeView 因 `aria-activedescendant` 使用自建鍵盤分支;
77
+ 6. **Pointer 與鍵盤都要可完成合法操作**:TreeView 使用自建鍵盤分支(Cmd/Ctrl+Shift+方向鍵,每按即 commit)——
78
+ dnd-kit `KeyboardSensor` 是「按住 → 方向鍵搬 → 放開」的抓取模式,啟動鍵 Enter / 空白鍵正是樹的「選取目前列」
79
+ (`tree-view.tsx` 鍵盤重排段註解;2026-09-25 更正:舊理由「因 `aria-activedescendant`」在列改為真焦點後已不成立,待辦總帳 B9);
78
80
  DataTable 無 `SortableContext`,不可誤套 `sortableKeyboardCoordinates`。
79
81
 
80
82
  ## Collision canonical
@@ -10,6 +10,15 @@
10
10
  `patterns/element-anatomy/item-anatomy.spec.md`)。本檔不重述那些值,只在它們之間定分工。
11
11
  與 `drag-canonical.md` 同層級、同形狀(一個能力、一份跨元件契約)。
12
12
 
13
+ **彈出框開著時按 `Tab` / `Esc` 做什麼、關了之後焦點回哪,不住在本檔**:單一住所是 `keyboard-model-canonical.md`
14
+ 「彈出框開著時的 Tab 與 Esc」(2026-09-25 user 拍板;含全 DS 規則「`Esc` 一次只關最內層」)。本檔只管焦點回到那裡之後,框怎麼畫。
15
+
16
+ **焦點框與命中區是兩件事,各有 owner**:焦點框是鍵盤游標的指示器 —— 畫在哪、往內還是往外,本檔說了算;
17
+ 滑鼠點得到的是多大一塊叫**可點範圍**,owner = `hit-area-canonical.md`(規則:有自己滑過形狀的小控件,**命中區 ≡ 懸停回饋形狀**;
18
+ 可以更大的只有屬於它的標籤盒子;沒有懸停回饋的按鈕才退化成可視形狀;預覽亮著時縫與角的點擊是整個元件確認預覽、不是外擴;
19
+ 唯一准外擴的是先天無法當目標的線與點 —— 全文見該檔「滑過原則」一-4、一-6 與「一-4 細則」,本檔不重述;2026-09-27 更正,舊句「命中區恆等於可視形狀」已被那三處取代)。
20
+ 兩者互不決定:同一顆鈕可以焦點框往內畫,命中區照樣只由它的懸停回饋決定。
21
+
13
22
  ## 一句話
14
23
 
15
24
  **鍵盤游標只由鍵盤移動;滑鼠只上色,不搬游標。**(唯一例外:已開啟的暫時性彈出層,沿用不外擴)
@@ -100,12 +109,12 @@ user 原話(問句):「滑鼠會搶反白的元件,搶完之後,那鍵盤是否
100
109
  | 瀏覽器 `:hover` / `:focus-visible`(DS 的 Sidebar / Tabs / DataTable / TimePicker 欄走真焦點) | pseudo-class | pseudo-class | 兩個獨立 pseudo-class,同一元素可同時 match(每一顆網頁上的按鈕都是這樣) |
101
110
  | Material 3 / [material-web `_menu-item.scss`](https://raw.githubusercontent.com/material-components/material-web/main/menu/internal/menuitem/_menu-item.scss) | `md-ripple` 的 `hover-state-layer-*`([`_md-sys-state.scss`](https://raw.githubusercontent.com/material-components/material-web/main/tokens/versions/v0_192/_md-sys-state.scss):hover 0.08 / focus 0.12 / pressed 0.12) | `md-focus-ring`(獨立元素) | 兩個獨立元素,各畫各的 |
102
111
  | [VS Code `listWidget.ts`](https://raw.githubusercontent.com/microsoft/vscode/main/src/vs/base/browser/ui/list/listWidget.ts) `DefaultStyleController.style()` | `.monaco-list-row:hover:not(.selected):not(.focused) { background-color: listHoverBackground }` | `.monaco-list:focus .monaco-list-row.focused { outline: 1px solid listFocusOutline; outline-offset: -1px }` + `listFocusBackground` | **部分反例**:焦點列自帶 `listFocusBackground`(底色通道已被焦點佔走),所以 hover 底色在焦點列上被 `:not(.focused)` 排除;hover 別列時兩者同時可見。DS 的鍵盤框不佔底色通道,所以同一列上底色 + 框可疊(AI 推導,見來源總帳) |
103
- | TreeView(DS 自家,`aria-activedescendant` 虛擬游標) | CSS `:hover` | `showRing`(`useInputModality`) | 獨立;`scripts/virtual-cursor-modality-invariant.mjs` E1/E2 實測同一列底色 + 框都在 |
112
+ | TreeView(DS 自家;2026-09-25 起列上 roving tabindex 真焦點,待辦總帳 B9 —— 之前是 `aria-activedescendant` 虛擬游標 + `useInputModality`) | CSS `:hover` | 列的 `focus-visible:focus-ring-inset`(瀏覽器 `:focus-visible`) | 獨立;`scripts/virtual-cursor-modality-invariant.mjs` E1/E2 實測同一列底色 + 框都在 |
104
113
 
105
114
  **兩類怎麼分**:滑鼠移過去反白會不會跟過來(規則一的例外)。會 → 反白是唯一游標,適用本節;不會 → 常駐清單,hover 與框獨立。
106
115
  DS 內屬於前者的:`CommandItem`(Select / SelectMenu / Combobox / PeoplePicker / Command inline+dialog / AgentPanel 歷史清單都經它)與
107
116
  DropdownMenu 四種項目(Item / SubTrigger / CheckboxItem / RadioItem)。其餘全是後者。
108
- **分類看項目的函式庫行為(pointermove 會不會搬焦點 / 反白),不看它住不住在 Popover 裡**(2026-09-24 補,user 問「出現鍵盤焦點之後再用滑鼠 hover 日期,按照我們其他元件搶焦點的邏輯,鍵盤焦點不是應該要消失嗎?」):DatePicker 浮層裡的 DateGrid 日期格是 react-day-picker 的 roving tabindex 真焦點(`node_modules/react-day-picker/dist/esm/DayPicker.js` 的 mouseenter 只轉呼叫 callback、不 `setFocused`)、TimeColumns 走 `:focus-visible`,都是後者;有格層級鍵盤游標的世界級日曆([MUI X `DayCalendar.tsx`](https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/DateCalendar/DayCalendar.tsx) `focusedDay` 只由 keydown / focus 改、[react-day-picker `DayPicker.tsx`](https://github.com/gpbl/react-day-picker/blob/main/packages/react-day-picker/src/DayPicker.tsx) mouseenter 只轉呼叫 callback、[flatpickr `index.ts`](https://github.com/flatpickr/flatpickr/blob/master/src/index.ts) `onMouseOver` 只增刪 class、[Polaris `DatePicker.tsx`](https://github.com/Shopify/polaris/blob/main/polaris-react/src/components/DatePicker/DatePicker.tsx) `focusDate` 與 `hoverDate` 兩個 state、[W3C APG datepicker-dialog.js](https://www.w3.org/WAI/content-assets/wai-aria-practices/patterns/dialog-modal/examples/js/datepicker-dialog.js) 的 cell 只綁 click / keydown / focus)沒有一家在 hover 時搬或抹焦點;一手對照 [React Aria `useCalendarCell.ts`](https://cdn.jsdelivr.net/npm/@react-aria/calendar/src/useCalendarCell.ts):「Highlight the date on hover or drag over a date when selecting a range.」→ `state.highlightDate(date)`,`setFocusedDate` 只在 `onFocus` / `onPressStart`。
117
+ **分類看項目的函式庫行為(pointermove 會不會搬焦點 / 反白),不看它住不住在 Popover 裡**(2026-09-24 補,user 問 —— 逐字節錄,全句見本檔「來源總帳」:「為何出現鍵盤焦點之後,再用滑鼠hover在日期上,按照我們其他元件搶焦點的邏輯的話,鍵盤焦點不是應該要消失嗎?」;舊句是改寫,2026-09-27 依 M36(a) 換回逐字):DatePicker 浮層裡的 DateGrid 日期格是 react-day-picker 的 roving tabindex 真焦點(`node_modules/react-day-picker/dist/esm/DayPicker.js` 的 mouseenter 只轉呼叫 callback、不 `setFocused`)、TimeColumns 走 `:focus-visible`,都是後者;有格層級鍵盤游標的世界級日曆([MUI X `DayCalendar.tsx`](https://github.com/mui/mui-x/blob/master/packages/x-date-pickers/src/DateCalendar/DayCalendar.tsx) `focusedDay` 只由 keydown / focus 改、[react-day-picker `DayPicker.tsx`](https://github.com/gpbl/react-day-picker/blob/main/packages/react-day-picker/src/DayPicker.tsx) mouseenter 只轉呼叫 callback、[flatpickr `index.ts`](https://github.com/flatpickr/flatpickr/blob/master/src/index.ts) `onMouseOver` 只增刪 class、[Polaris `DatePicker.tsx`](https://github.com/Shopify/polaris/blob/main/polaris-react/src/components/DatePicker/DatePicker.tsx) `focusDate` 與 `hoverDate` 兩個 state、[W3C APG datepicker-dialog.js](https://www.w3.org/WAI/content-assets/wai-aria-practices/patterns/dialog-modal/examples/js/datepicker-dialog.js) 的 cell 只綁 click / keydown / focus)沒有一家在 hover 時搬或抹焦點;一手對照 [React Aria `useCalendarCell.ts`](https://cdn.jsdelivr.net/npm/@react-aria/calendar/src/useCalendarCell.ts):「Highlight the date on hover or drag over a date when selecting a range.」→ `state.highlightDate(date)`,`setFocusedDate` 只在 `onFocus` / `onPressStart`。
109
118
 
110
119
  **所以修改範疇只有會搶反白的元件**(user 問「這個更改範疇應該只有會搶反白的元件吧?」——對):把它們項目上的 `hover:` 樣式全部拿掉、
111
120
  畫法改由「反白來歷」決定(`hooks/use-input-modality.ts` `useCursorMover` + `markPointerGrab`),常駐清單一行都不用改。
@@ -143,8 +152,10 @@ DropdownMenu 四種項目(Item / SubTrigger / CheckboxItem / RadioItem)。其餘
143
152
  [WICG focus-visible explainer「Example heuristic」](https://github.com/WICG/focus-visible/blob/main/explainer.md):
144
153
  「if the most recent user interaction was via the keyboard; and the key press did not include a meta,
145
154
  alt/option, or control key; then the modality is keyboard. Otherwise, the modality is not keyboard.」
146
- 機械載體 = `hooks/use-input-modality.ts`(document capture 監聽、**模組載入即安裝**;第一版的「引用計數安裝」實測會漏掉開啟前的按鍵,見該檔註解)。
147
- **這個判準只給不搶反白的常駐虛擬游標用(TreeView `showRing`)**:WICG polyfill 只把 keydown / mousedown / pointerdown / touchstart 當輸入,
155
+ 機械載體原本是 `hooks/use-input-modality.ts` 的 `useInputModality()`(document capture 監聽、**模組載入即安裝**;第一版的「引用計數安裝」實測會漏掉開啟前的按鍵)。
156
+ **這個判準只給不搶反白的常駐虛擬游標用**(原本的唯一消費者是 TreeView `showRing`;2026-09-25 TreeView 改成列上真焦點、交給瀏覽器的 `:focus-visible`(待辦總帳 B9)之後沒有消費者,
157
+ **2026-09-26 刪掉 `useInputModality()` 這份零消費者實作**(待辦總帳〇節「按鍵規則合併」:沒人讀的第二套判準會讓人以為常駐清單還有兩種畫框依據;同檔的反白來歷 `useCursorMover` 保留)——
158
+ 判準留在這裡,常駐清單若再出現虛擬游標,照這條判準重建、並先問為什麼不能用真焦點):WICG polyfill 只把 keydown / mousedown / pointerdown / touchstart 當輸入,
148
159
  **滑鼠移動不算**(mousemove 只在載入時用來判初始模態、第一次移動後就移除 listener —— [`src/focus-visible.js`](https://github.com/WICG/focus-visible/blob/main/src/focus-visible.js) `onInitialPointerMove`),
149
160
  所以常駐清單的鍵盤框不會被滑鼠一晃就抹掉,跟瀏覽器對真焦點的行為一致。
150
161
 
@@ -161,11 +172,11 @@ MUI Autocomplete 只在 `reason === 'keyboard'` 才加 `Mui-focusVisible`,打字
161
172
  `setActive(第一項)`([rc-select OptionList](https://unpkg.com/rc-select/es/OptionList.js)),樣式是 `optionActiveBg` 底色、`outline: none`
162
173
  ([antd select dropdown style](https://unpkg.com/antd/es/select/style/dropdown.js))。閘:`virtual-cursor-modality-invariant.mjs` F 段。
163
174
  兩個訊號不能共用:拿 WICG 模態畫反白,滑鼠搶走反白後模態仍是鍵盤,被搶到的列會畫框而不是底色(2026-09-09 下午閘 D3 抓到);
164
- 拿反白來歷畫 TreeView,滑鼠一晃鍵盤框就消失。反白因此只有兩種長相:
175
+ 拿反白來歷畫常駐清單(當時的 TreeView 虛擬游標),滑鼠一晃鍵盤框就消失。反白因此只有兩種長相:
165
176
  **滑鼠搬的**反白 = hover → 底色、無框;**鍵盤搬的**反白 = 游標 → 框、無底色,而且滑鼠停留列的底色一起消失(項目上沒有 `hover:` 樣式)。
166
177
  開啟時的落點(cmdk 放在已選項或第一項、Radix 不放)沒有人搬過,用開啟那一下的輸入畫:滑鼠點開 → 底色、鍵盤開 → 框。
167
178
  消費者:`CommandItem`(SelectMenu / Select / Combobox / PeoplePicker / Command / AgentPanel 歷史清單都經它)/ DropdownMenu 四種項目(`radixCursorClass`);
168
- TreeView(`showRing`)仍走 `useInputModality`。
179
+ TreeView 2026-09-25 起是列上真焦點,框交給瀏覽器的 `:focus-visible`,不再經 `useInputModality`(待辦總帳 B9)。
169
180
  錨:user 2026-09-08「為何我用滑鼠一開 select 選單明明就沒有鍵盤操作,卻會直接出現鍵盤焦點?」——
170
181
  cmdk 開啟時把游標放在已選項上(`select-menu.tsx` `defaultValue={selectedOption?.value}`),
171
182
  畫框規則沒有模態條件,滑鼠一點開就畫。閘:`scripts/virtual-cursor-modality-invariant.mjs`
@@ -202,13 +213,14 @@ cmdk 開啟時把游標放在已選項上(`select-menu.tsx` `defaultValue={selec
202
213
  |---|---|---|
203
214
  | 線 | `outline: 2px solid var(--ring)`;填色元素上 `outline: 1px solid var(--on-emphasis)` | `styles/base.css` `:focus-visible` 全域規則(外描邊)、`@utility focus-ring-inset`(內描邊)與 `@utility focus-ring-inset-emphasis`(填色元素內描邊),值只寫這三處 |
204
215
  | 顏色 | `--ring`(= primary);填色元素上 `--on-emphasis`(主色底上的前景,兩個主題都是白) | token owner `tokens/color/color.spec.md`;本檔不定值 |
205
- | 位置(預設) | **往外** `outline-offset: 2px`;元件**什麼都不用寫** | 「問題二」:預設就是往外長(user 2026-09-07 逐字) |
216
+ | 位置(預設) | **往外** `outline-offset: var(--stack-gap)`(2px;「疊在一起的兩樣東西」之間的縫,全 DS 同一個 token,`tokens/uiSize/uiSize.css`);元件**什麼都不用寫** | 「問題二」:預設就是往外長(user 2026-09-07 逐字) |
206
217
  | 位置(被裁切/貼鄰居) | **往內** `outline-offset: -2px`,寫 `focus-visible:focus-ring-inset`(真焦點)或 `focus-ring-inset`(虛擬游標,由元件 state 掛上) | 「問題二」:被聚焦元素四周最小淨空 < 4px 才往內;撐滿容器寬度的列(選單項 / 側欄鈕 / tab)都屬此類 |
207
218
  | 位置(往內,而且**元素自己的底色就是主色**) | **1px `--on-emphasis` 白線,退 3px**(`outline-offset: -3px`),寫 `[&>button]:focus-visible:focus-ring-inset-emphasis` 掛在填色格的 modifier 上;目前只有 DateGrid 的選中日 / 區間端點 | 「問題二」→「填色元素上的內描邊」:藍線畫在藍底上同色看不見;白線貼最外圈只是把藍圓削小;退進去、外圈留藍(user 2026-09-23 拍板 D) |
208
219
  | 圓角 | 跟著元素的 `border-radius` | `outline` 原生行為,不必特別處理(「不需要為它開分支」) |
220
+ | 位置(框的一段被元素**自己**貼邊的內容疊住) | 幾何不變 —— 仍是 `focus-ring-inset`,只是掛在與元素同形同大的 `::before`「框圖層」上,被疊住的那一段(兩端各多 2px 縫)用遮罩挖空、露出真正的底;**不是第四種幾何**(線寬、顏色、退距、圓角都沒變)。框畫在元素本身時,元素是那段內容的祖先,遮罩會連內容一起挖掉,所以要另一層。目前唯一案例:FileItem compact 列底的進度條(FileUpload 清單列共用) | `components/FileItem/file-item.spec.md`「焦點框 × 貼著列底的進度條」;機制 `file-item.tsx` `FILE_ITEM_RING_LAYER_CLASS` / `fileItemRingCutoutStyle`。方向 user 2026-09-26 選、挖空 + 縫 AI 推導(本檔「這條規則的來源總帳」) |
209
221
  | 只准三種幾何 | 全域外描邊 / `focus-ring-inset` / 填色元素專用的 `focus-ring-inset-emphasis`;禁 `ring-offset-*`、禁 `focus-visible:ring-*`、禁手寫三件組、禁手寫其他退距 | `scripts/focus-geometry-invariant.mjs` R1–R6 |
210
222
  | 什麼時候畫(真焦點) | 瀏覽器 `:focus-visible` | 元件不判斷模態 |
211
- | 什麼時候畫(常駐清單的虛擬游標,TreeView) | `useInputModality() === 'keyboard'` 才掛 `focus-ring-inset`(WICG 模態:keydown / pointerdown,滑鼠移動不算) | 上一節;`scripts/virtual-cursor-modality-invariant.mjs` |
223
+ | 什麼時候畫(常駐清單) | 真焦點(規則一「兩類元件」第二表那幾個;TreeView 2026-09-25 起也是,待辦總帳 B9)= 瀏覽器 `:focus-visible`;容器 `aria-activedescendant` 型(TimePicker 欄)= 容器 `:focus-visible` 時畫在被指到的那一格(`time-columns.tsx` `group-focus-visible/listbox:`);常駐虛擬游標若再出現,才照 WICG 模態判準畫(上一節;`useInputModality()` 零消費者實作 2026-09-26 已刪,屆時重建) | 上一節;`scripts/virtual-cursor-modality-invariant.mjs` |
212
224
  | 什麼時候畫(會搶反白的浮層選單,cmdk / Radix) | `useCursorMover() === 'keyboard'` 才掛 `focus-ring-inset`,否則反白上 `bg-neutral-hover`(反白來歷:方向鍵 / Home / End / PageUp / PageDown / Tab / Esc,或非文字輸入框上的任何鍵 / 滑鼠移過項目 `markPointerGrab`;停著不算、在文字輸入框裡打字不算) | 上一節;同一支閘 D 段 |
213
225
  | **選中 × 游標** | 框疊在 `bg-neutral-selected` 上 | 規則二疊加表 |
214
226
  | **hover × 游標(常駐清單)** | `bg-neutral-hover` + 框都在 | 規則二疊加表 |
@@ -220,7 +232,7 @@ cmdk 開啟時把游標放在已選項上(`select-menu.tsx` `defaultValue={selec
220
232
  | 指標 | 數字 |
221
233
  |---|---|
222
234
  | 用 `focus-visible:` 的元件檔 | 47 |
223
- | `ring-ring` 出現次數 | 85 |
235
+ | `ring-ring` 出現次數 | 85(2026-09-06 當時)→ **2026-09-24 重數 = 0 個活用法**;現存 2 筆都是記錄遷移的歷史註解(`radio-group.tsx` / `file-item.tsx`)|
224
236
  | 用 `focus-within:`(即共用 focus 那類)的元件 | 8 — AgentPanel / Carousel / DataTable / Field / FileViewer / LinkInput / PeoplePicker / Select |
225
237
  | `ring-inset` | 2(DataTable、TreeView)|
226
238
  | `--neutral-selected-focus` 的用法 | **0**(2026-09-07 退役;2026-09-06 當時是 4 活 + 1 死)|
@@ -344,9 +356,9 @@ cmdk 開啟時把游標放在已選項上(`select-menu.tsx` `defaultValue={selec
344
356
 
345
357
  | 類 | 判準(**看什麼**) | 框由誰畫 | 實例 |
346
358
  |---|---|---|---|
347
- | **A. 虛擬游標/程式游標** | 它身上有 `aria-activedescendant`;或它是函式庫管理游標的項目(cmdk `data-selected` / Radix `data-highlighted`),而瀏覽器的 `:focus-visible` 看不到那個游標 | **元件自己**,畫在**被指到的那一項**上(`focus-ring-inset`;常駐清單看 `useInputModality`、會搶反白的選單看反白來歷 `useCursorMover`;容器/項目抑制瀏覽器預設外框) | TreeView 根(`tree-view.tsx:1394` showRing)/ DataTable 根 / TimePicker 欄(`time-columns.tsx` 被指到的 option)/ DropdownMenu 項(`dropdown-menu.tsx` `radixCursorClass`)/ CommandItem(`command.tsx`) |
359
+ | **A. 虛擬游標/程式游標** | 它身上有 `aria-activedescendant`;或它是函式庫管理游標的項目(cmdk `data-selected` / Radix `data-highlighted`);或元件 state 管的程式游標(DataTable 試算表模式的格游標,框由 `data-table-interaction-layer.tsx` 畫,2026-09-26),而瀏覽器的 `:focus-visible` 看不到那個游標 | **元件自己**,畫在**被指到的那一項**上(`focus-ring-inset`;常駐清單的容器看自己的 `:focus-visible`、會搶反白的選單看反白來歷 `useCursorMover`;容器/項目抑制瀏覽器預設外框) | DataTable 根 / TimePicker 欄(`time-columns.tsx` 被指到的 option)/ DropdownMenu 項(`dropdown-menu.tsx` `radixCursorClass`)/ CommandItem(`command.tsx`)。TreeView 2026-09-25 起改列上真焦點(待辦總帳 B9),已不屬本類 |
348
360
  | **B. 插入點控件** | **可機械判別**:標籤名是 `input`(`type` 為文字類:未指定 / text / search / email / url / tel / password / number)或 `textarea`,或元素帶 `contenteditable`。Field 家族控件在此之上另有 wrapper 邊框轉色(`field-wrapper.tsx:49` `focus-within:!border-primary`)。grep 判準 = `scripts/focus-suppression-registry.mjs:125-127`(往上 40 行找得到 `<input>` / `<textarea>`,或共用 style 常數所服務的檔案真的渲染該標籤) | **唯一不畫框的例外**。指示 = 閃動的插入點(caret);Field 家族再加欄位邊框轉 primary | Input / Textarea / Combobox / DatePicker / Command 與 SelectMenu 搜尋框 / AgentPromptInput |
349
- | **C. 祖先畫框(邊框轉色)** | 從**自己往上**找,有元素在聚焦時改邊框(`focus-within:` / `:has(…:focus-visible)` / `focus-visible:border-`) | **那個元素**(可以是自己這圈外框,也可以是祖先);它就是這個 tab stop 的框 | 欄位外框自己(`combobox.tsx:857` / `time-picker.tsx:379`)/ 祖先畫(`inline-edit.tsx:396`)/ DatePicker 範圍模式兩顆鈕(另加底線區分,見下) |
361
+ | **C. 祖先畫框(邊框轉色)** | 從**自己往上**找,有元素在聚焦時改邊框(`focus-within:` / `:has(…:focus-visible)` / `focus-visible:border-`) | **那個元素**(可以是自己這圈外框,也可以是祖先);它就是這個 tab stop 的框。自己的 `::before` 框圖層(「框怎麼畫」框圖層列)也算自己這圈 —— 元素本身抑制全域外描邊,承擔者寫成掛 `focus-visible:before:focus-ring-inset` 那一行的 `檔名.tsx:行號`(2026-09-26 FileUpload 清單列) | 欄位外框自己(`combobox.tsx:857` / `time-picker.tsx:379`)/ 祖先畫(`inline-edit.tsx:396`)/ DatePicker 範圍模式兩顆鈕(另加底線區分,見下) |
350
362
  | **E. 浮層程式落點** | 它 `tabIndex=-1`,而且是浮層開啟時被程式 `.focus()` 的殼 | **回規則一(問題一)**:殼本身不可操作 → 不畫;它不在 Tab 順序裡(`-1` 是 Radix 設的,不必也不能拿掉)。若某個殼是 `tabIndex≥0` 的空焦點站,修法是**拿掉 tabIndex**,不是畫框。內部控件各自有指示 | Popover / HoverCard / DropdownMenuContent / FileViewer |
351
363
 
352
364
  > **這張表只收「可操作、但瀏覽器預設那圈不是它的框」的情況。**
@@ -410,7 +422,7 @@ DatePicker 自己早就有那個指示 —— 作用端下方一條主色粗線
410
422
  |---|---|---|---|
411
423
  | 1 | **它可以被操作嗎?**(有 onClick / onKeyDown / 是原生互動元素?) | **否 → 不畫**,而且要拿掉 tabIndex。這張表不適用 | `N`,寫「不可操作」 |
412
424
  | 2 | **它的 `tabIndex` 是 `-1`,而且是某個浮層開啟時被程式 `.focus()` 的殼嗎?** | **E** — 不畫(回問題一) | 「浮層開啟時的程式落點;內部控件各自有指示」 |
413
- | 3 | **它身上有 `aria-activedescendant`,或它是 cmdk / Radix 管理游標的項目嗎?** | **A** — 容器不畫瀏覽器那圈,框由元件畫在被指到的那個元素上(常駐清單:鍵盤模態 `useInputModality`;會搶反白的選單:鍵盤來歷 `useCursorMover`) | 那個元素/那條 class 的 file:line(例:`tree-view.tsx:1394` 的 `showRing`)|
425
+ | 3 | **它身上有 `aria-activedescendant`,或它是 cmdk / Radix 管理游標的項目嗎?** | **A** — 容器不畫瀏覽器那圈,框由元件畫在被指到的那個元素上(常駐清單:容器的 `:focus-visible`;會搶反白的選單:鍵盤來歷 `useCursorMover`) | 那個元素/那條 class 的 file:line(例:`time-columns.tsx` 的 `group-focus-visible/listbox:aria-selected:focus-ring-inset`)|
414
426
  | 4 | **它的標籤名是 `input`(文字類)或 `textarea`,或帶 `contenteditable` 嗎?** | **B** — 不畫,插入點(caret)就是指示 | 「caret」,外框另有 focus 樣式時一併寫上 |
415
427
  | 5 | **從自己往上找,有沒有元素在聚焦時改邊框?**(`focus-within:` / `:has(…:focus-visible)` / `focus-visible:border-`) | **C** — 不另外畫外框,那圈邊框就是指示 | 那個元素的 file:line 與 class(自己也算)|
416
428
  | 6 | **以上皆否** | **要畫**(幾何走「框怎麼畫」) | — |
@@ -486,7 +498,7 @@ DatePicker 自己早就有那個指示 —— 作用端下方一條主色粗線
486
498
  > **只有當元素「可能合法地被塞在四周沒有足夠視覺空間的地方」,才往內長。**
487
499
 
488
500
  機械化的量法:量「被聚焦的那個元素」四邊到最近**正當障礙**的距離,取最小值。
489
- **≥ 4px → 往外**(`outline-offset: 2px`)/ **< 4px → 往裡**(`outline-offset: -2px`)。
501
+ **≥ 4px → 往外**(`outline-offset: var(--stack-gap)` = 2px)/ **< 4px → 往裡**(`outline-offset: -2px`)。
490
502
 
491
503
  ### 「正當障礙」—— 這是本判準最容易做錯的地方
492
504
 
@@ -649,6 +661,7 @@ v3 之所以能把 `overflow` 完全踢出判準,是因為**裁切邊只有在
649
661
  | 「填色格不能只是往內畫,要保住藍底」 | **user 2026-09-23 逐字**:「第五點,應該不只往內畫吧?否則整個選中狀態只會看起來是比較小的藍底?」(問句,但指出了「白線貼邊只是削小藍圓」這個事實;C / D 兩個候選與數值是 AI 依 Carbon 配方提出) |
650
662
  | 「1px 白線退 3px(D),不是 2px 退 4px(C)」 | **user 2026-09-23 拍板**,逐字:「我會想要選D,因為 c的白線幾乎要切到文字了,你覺得呢?」+ 結構化選擇「D:1px 白線,退 3px」(AI 同意 D 並列出兩者的淨空數字,user 在兩者間定案) |
651
663
  | 「第三種幾何只給往內畫的填色元素,不外擴」 | **AI 推導**:DS 內目前只有 DateGrid 選中日 / 端點同時是「往內 + 填色」;往外畫的填色元件框在頁面底上不受影響 |
664
+ | 「框的一段被元素自己貼邊的內容疊住時,框改畫在 `::before` 框圖層並在那一段挖空、兩端留 2px 縫」(「框怎麼畫」框圖層列) | **方向 = user 2026-09-26 選**,逐字:「我喜歡墊在鍵盤焦點上的方向,依此方向仔細研究怎樣最好」(主 session 轉述其意為「進度條留在框上面、底下墊東西讓框不透出來」;另一句原話「我他媽不想要動到這邊的一般視覺」)。**挖空而不是墊底色、縫寬 2px、框改畫在 `::before`** 為 AI 推導,user 同日回「我覺得方向可以,確保整個設計符合我們一致的設計語言且不違背世界級的設計就照你建議」:實測固定墊 `--canvas` 在深色卡片 / 被滑過的列上錯色,「容器宣告底色」的變數在卡片放進浮層面板時錯色(深色 `--surface` 半透明),挖空在四種底 × 兩主題 × 滑過全部與平常 0 差;2px 同全域外描邊的退距與頭像堆疊的縫。**已寫入**(待辦總帳「09-26 第五輪」進度條(續)列:user 原話「我覺得方向可以,確保整個設計符合我們一致的設計語言且不違背世界級的設計就照你建議」→ 已寫入 file-item / file-upload、兩份 spec 與本列;2026-09-27 拿掉過期的「待 user 確認」) |
652
665
 
653
666
  ---
654
667
 
@@ -10,7 +10,7 @@
10
10
  | `packages/design-system/ds-canonical/rules/*.md`(M-rules 等) | counters(M-rule 數)+ `extract-canonical-rules --check` + canonical-reviewer agent(edit 時)+ knowledge-prune D1/D3/D4 | 每 edit + 每發版 + 季度 | ✅ 強 |
11
11
  | `*.spec.md` | deep-audit dims 6/7/8(NO-SAMPLE judgment)+ A.1b claim-vs-code 逐句 + `audit-spec-deadlinks --check` + `add-reciprocal-pointers --check` + `check_spec_class_drift` hook + `audit-content-quality --check`(**scope 註:此 script 只掃 components/ 的 spec/story,非治理 md**) | 每 deep-audit + 每發版 | ✅ 強 |
12
12
  | registered hooks | `audit:hook-quality`(有可信 telemetry 時才判 fire 活性/假死;缺資料 = unobserved)+ `audit-hook-test-coverage --check`(BLOCKER hook 必有 test)+ `tests/run-all` + fork classification gate(`build-fork-governance --check`,新 hook 未分類 = 擋發版)+ dynamic counters(數量 cap) | 每 deep-audit + 每發版 + 季度 | ✅ 結構強 / ⚠️ live telemetry 視環境可為 UNOBSERVED |
13
- | canonical skills | knowledge-prune D7(只在有可信 invoke telemetry 時判活性)+ file-size hook + deep-audit A.0 全讀 + governance-health 月度;inventory 由 canonical tree 動態枚舉 | 每 deep-audit + 季度 + 月度 | ⚠️ 中(read 層有了;逐句 claim-vs-behavior 仍無機械閘 = 弱軸 2) |
13
+ | canonical skills | knowledge-prune D7(只在有可信 invoke telemetry 時判活性)+ file-size hook + governance-health 月度;inventory 由 canonical tree 動態枚舉。**沒有 read 閘**:deep-audit Phase A 必讀清單(`deep-audit-cross-codex/references/phase-a-workflow.md`)不含 `skills/*/SKILL.md`(2026-07-10 hunt 判 OVERCLAIM,2026-09-29 覆核仍無) | 每 deep-audit + 季度 + 月度 | ⚠️ 中(read 層與逐句 claim-vs-behavior 都無機械閘 = 弱軸 2) |
14
14
  | committed memory SSOT + provider cache | session-start 對 repo SSOT cap 檢查(≤20)+ `sync-memory --check` content-hash drift + knowledge-prune D8(recency/orphan) | 每 session + 季度 | ✅ 強 |
15
15
  | `references/`(registry / 對照表) | dim 91 registry gate(failure-class)+ `check_story_invariants` R8(story-baseline-registry 消費)+ repo-hygiene exact inventory/duplicate gate + prune D1/D4/D2 references-orphan | 每 deep-audit + 每發版 + 季度 | ⚠️ 中(結構/registry 強;純文字語意仍靠季度 judgment) |
16
16
  | `planning/`(Level 9 plan doc) | `validate-planning-registry.mjs` 驗 exact inventory/status/executable contract;knowledge-prune D8 驗 active memory pointer、stale/orphan | 每 deep-audit + 每發版 + 季度 | ⚠️ 中(狀態機械;內容 recency 仍是 judgment) |