@qijenchen/design-system 0.1.0-beta.61 → 0.1.0-beta.63

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 (507) hide show
  1. package/CLAUDE.md +6 -6
  2. package/dist/components/Accordion/accordion.d.ts +1 -1
  3. package/dist/components/Accordion/accordion.js +1 -1
  4. package/dist/components/Accordion/accordion.js.map +1 -1
  5. package/dist/components/Alert/alert.d.ts +2 -2
  6. package/dist/components/Alert/alert.js +4 -3
  7. package/dist/components/Alert/alert.js.map +1 -1
  8. package/dist/components/AppShell/app-shell.d.ts.map +1 -1
  9. package/dist/components/AppShell/app-shell.js +4 -3
  10. package/dist/components/AppShell/app-shell.js.map +1 -1
  11. package/dist/components/Avatar/avatar.d.ts +1 -1
  12. package/dist/components/Avatar/avatar.js +2 -1
  13. package/dist/components/Avatar/avatar.js.map +1 -1
  14. package/dist/components/Badge/badge.d.ts +1 -1
  15. package/dist/components/Badge/badge.js +2 -1
  16. package/dist/components/Badge/badge.js.map +1 -1
  17. package/dist/components/Breadcrumb/breadcrumb.d.ts +1 -1
  18. package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
  19. package/dist/components/BulkActionBar/bulk-action-bar.js.map +1 -1
  20. package/dist/components/Button/button.d.ts +5 -5
  21. package/dist/components/Button/button.d.ts.map +1 -1
  22. package/dist/components/Button/button.js +4 -3
  23. package/dist/components/Button/button.js.map +1 -1
  24. package/dist/components/Calendar/calendar.d.ts +1 -1
  25. package/dist/components/Calendar/calendar.d.ts.map +1 -1
  26. package/dist/components/Calendar/calendar.js +80 -69
  27. package/dist/components/Calendar/calendar.js.map +1 -1
  28. package/dist/components/Carousel/carousel.d.ts.map +1 -1
  29. package/dist/components/Carousel/carousel.js +5 -3
  30. package/dist/components/Carousel/carousel.js.map +1 -1
  31. package/dist/components/Checkbox/checkbox-group.d.ts +2 -1
  32. package/dist/components/Checkbox/checkbox-group.d.ts.map +1 -1
  33. package/dist/components/Checkbox/checkbox-group.js.map +1 -1
  34. package/dist/components/Checkbox/checkbox.d.ts +9 -3
  35. package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
  36. package/dist/components/Checkbox/checkbox.js +8 -3
  37. package/dist/components/Checkbox/checkbox.js.map +1 -1
  38. package/dist/components/Chip/chip.d.ts +2 -2
  39. package/dist/components/Chip/chip.js +3 -2
  40. package/dist/components/Chip/chip.js.map +1 -1
  41. package/dist/components/CircularProgress/circular-progress.d.ts +1 -1
  42. package/dist/components/CircularProgress/circular-progress.js +2 -1
  43. package/dist/components/CircularProgress/circular-progress.js.map +1 -1
  44. package/dist/components/Coachmark/coachmark.d.ts +4 -4
  45. package/dist/components/Coachmark/coachmark.js +2 -1
  46. package/dist/components/Coachmark/coachmark.js.map +1 -1
  47. package/dist/components/Combobox/combobox.d.ts.map +1 -1
  48. package/dist/components/Combobox/combobox.js +17 -13
  49. package/dist/components/Combobox/combobox.js.map +1 -1
  50. package/dist/components/Command/command.d.ts +4 -0
  51. package/dist/components/Command/command.d.ts.map +1 -1
  52. package/dist/components/Command/command.js.map +1 -1
  53. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  54. package/dist/components/DataTable/data-table.js.map +1 -1
  55. package/dist/components/DateGrid/date-grid.d.ts +8 -4
  56. package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
  57. package/dist/components/DateGrid/date-grid.js +2 -2
  58. package/dist/components/DateGrid/date-grid.js.map +1 -1
  59. package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
  60. package/dist/components/DatePicker/date-picker.js +6 -4
  61. package/dist/components/DatePicker/date-picker.js.map +1 -1
  62. package/dist/components/DescriptionList/description-list.js +1 -1
  63. package/dist/components/DescriptionList/description-list.js.map +1 -1
  64. package/dist/components/Dialog/dialog.d.ts.map +1 -1
  65. package/dist/components/Dialog/dialog.js.map +1 -1
  66. package/dist/components/DropdownMenu/dropdown-menu.d.ts +1 -1
  67. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  68. package/dist/components/DropdownMenu/dropdown-menu.js +0 -1
  69. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  70. package/dist/components/Empty/empty.d.ts +1 -1
  71. package/dist/components/Empty/empty.js.map +1 -1
  72. package/dist/components/Field/field-wrapper.js +1 -1
  73. package/dist/components/Field/field-wrapper.js.map +1 -1
  74. package/dist/components/Field/field.d.ts.map +1 -1
  75. package/dist/components/Field/field.js +1 -0
  76. package/dist/components/Field/field.js.map +1 -1
  77. package/dist/components/FieldControlGroup/field-control-group.d.ts.map +1 -1
  78. package/dist/components/FieldControlGroup/field-control-group.js +1 -1
  79. package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
  80. package/dist/components/FileUpload/file-upload.d.ts +8 -1
  81. package/dist/components/FileUpload/file-upload.d.ts.map +1 -1
  82. package/dist/components/FileUpload/file-upload.js +7 -3
  83. package/dist/components/FileUpload/file-upload.js.map +1 -1
  84. package/dist/components/FileViewer/file-viewer.d.ts +1 -1
  85. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  86. package/dist/components/FileViewer/file-viewer.js +25 -14
  87. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  88. package/dist/components/HoverCard/hover-card.d.ts +5 -1
  89. package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
  90. package/dist/components/HoverCard/hover-card.js +2 -1
  91. package/dist/components/HoverCard/hover-card.js.map +1 -1
  92. package/dist/components/Menu/menu-item.d.ts +6 -2
  93. package/dist/components/Menu/menu-item.d.ts.map +1 -1
  94. package/dist/components/Menu/menu-item.js.map +1 -1
  95. package/dist/components/Notice/notice.d.ts +5 -1
  96. package/dist/components/Notice/notice.d.ts.map +1 -1
  97. package/dist/components/Notice/notice.js +2 -1
  98. package/dist/components/Notice/notice.js.map +1 -1
  99. package/dist/components/OverflowIndicator/overflow-indicator.d.ts +4 -0
  100. package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
  101. package/dist/components/OverflowIndicator/overflow-indicator.js +2 -2
  102. package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
  103. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  104. package/dist/components/PeoplePicker/people-picker.js +6 -2
  105. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  106. package/dist/components/Popover/popover.d.ts +1 -1
  107. package/dist/components/Popover/popover.js +2 -1
  108. package/dist/components/Popover/popover.js.map +1 -1
  109. package/dist/components/ProfileCard/profile-card.d.ts +9 -4
  110. package/dist/components/ProfileCard/profile-card.d.ts.map +1 -1
  111. package/dist/components/ProfileCard/profile-card.js.map +1 -1
  112. package/dist/components/RadioGroup/radio-group.d.ts +6 -0
  113. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  114. package/dist/components/RadioGroup/radio-group.js +4 -0
  115. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  116. package/dist/components/ScrollArea/scroll-area.js +1 -1
  117. package/dist/components/ScrollArea/scroll-area.js.map +1 -1
  118. package/dist/components/Select/select.d.ts.map +1 -1
  119. package/dist/components/Select/select.js +14 -4
  120. package/dist/components/Select/select.js.map +1 -1
  121. package/dist/components/SelectMenu/select-menu.d.ts +4 -0
  122. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  123. package/dist/components/SelectMenu/select-menu.js +6 -3
  124. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  125. package/dist/components/SelectionControl/selection-item.d.ts +5 -1
  126. package/dist/components/SelectionControl/selection-item.d.ts.map +1 -1
  127. package/dist/components/SelectionControl/selection-item.js +3 -1
  128. package/dist/components/SelectionControl/selection-item.js.map +1 -1
  129. package/dist/components/Sheet/sheet.d.ts +6 -5
  130. package/dist/components/Sheet/sheet.d.ts.map +1 -1
  131. package/dist/components/Sheet/sheet.js.map +1 -1
  132. package/dist/components/Sidebar/sidebar.d.ts +1 -1
  133. package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
  134. package/dist/components/Sidebar/sidebar.js +3 -2
  135. package/dist/components/Sidebar/sidebar.js.map +1 -1
  136. package/dist/components/Skeleton/skeleton.d.ts +1 -1
  137. package/dist/components/Skeleton/skeleton.js +2 -1
  138. package/dist/components/Skeleton/skeleton.js.map +1 -1
  139. package/dist/components/Slider/slider.d.ts +1 -1
  140. package/dist/components/Slider/slider.d.ts.map +1 -1
  141. package/dist/components/Slider/slider.js +7 -3
  142. package/dist/components/Slider/slider.js.map +1 -1
  143. package/dist/components/Steps/steps.d.ts +1 -1
  144. package/dist/components/Steps/steps.d.ts.map +1 -1
  145. package/dist/components/Steps/steps.js +9 -6
  146. package/dist/components/Steps/steps.js.map +1 -1
  147. package/dist/components/Switch/switch.d.ts +5 -5
  148. package/dist/components/Switch/switch.js +3 -3
  149. package/dist/components/Switch/switch.js.map +1 -1
  150. package/dist/components/Tabs/tabs.js +1 -1
  151. package/dist/components/Tabs/tabs.js.map +1 -1
  152. package/dist/components/Textarea/textarea.js +1 -1
  153. package/dist/components/Textarea/textarea.js.map +1 -1
  154. package/dist/components/TimePicker/time-columns.js +1 -1
  155. package/dist/components/TimePicker/time-columns.js.map +1 -1
  156. package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
  157. package/dist/components/TimePicker/time-picker.js +2 -1
  158. package/dist/components/TimePicker/time-picker.js.map +1 -1
  159. package/dist/components/Toast/toast.js.map +1 -1
  160. package/dist/components/Tooltip/tooltip.d.ts +1 -1
  161. package/dist/components/Tooltip/tooltip.js +2 -1
  162. package/dist/components/Tooltip/tooltip.js.map +1 -1
  163. package/dist/components/TreeView/tree-view.d.ts +4 -4
  164. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  165. package/dist/components/TreeView/tree-view.js +3 -3
  166. package/dist/components/TreeView/tree-view.js.map +1 -1
  167. package/dist/patterns/element-anatomy/item-anatomy.d.ts +3 -3
  168. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  169. package/dist/patterns/header-canonical/chrome-header.d.ts +3 -2
  170. package/dist/patterns/header-canonical/chrome-header.d.ts.map +1 -1
  171. package/dist/patterns/header-canonical/chrome-header.js.map +1 -1
  172. package/dist/patterns/overlay-surface/overlay-surface.d.ts +3 -2
  173. package/dist/patterns/overlay-surface/overlay-surface.d.ts.map +1 -1
  174. package/dist/patterns/overlay-surface/overlay-surface.js.map +1 -1
  175. package/ds-canonical/hooks/_log-fire.sh +3 -1
  176. package/ds-canonical/hooks/check_audit_post_report_validator.sh +21 -1
  177. package/ds-canonical/hooks/check_audit_sample_escape.sh +6 -3
  178. package/ds-canonical/hooks/check_chrome_header_avatar_canonical.sh +8 -0
  179. package/ds-canonical/hooks/check_consumer_app_invariants.sh +321 -0
  180. package/ds-canonical/hooks/check_datatable_invariants.sh +75 -12
  181. package/ds-canonical/hooks/check_escape_marker_abuse.sh +15 -1
  182. package/ds-canonical/hooks/check_field_family_invariants.sh +12 -2
  183. package/ds-canonical/hooks/check_plugin_fork_health.sh +137 -0
  184. package/ds-canonical/hooks/check_propose_discipline.sh +147 -0
  185. package/ds-canonical/hooks/check_solo_workflow.sh +11 -1
  186. package/ds-canonical/hooks/check_story_invariants.sh +63 -9
  187. package/ds-canonical/hooks/check_storybook_addon_packaging.sh +151 -0
  188. package/ds-canonical/hooks/check_tailwind_wildcard_in_docs.sh +8 -2
  189. package/ds-canonical/hooks/lib/_overlay_handcraft.sh +25 -4
  190. package/ds-canonical/hooks/lib/_token_hygiene.sh +9 -1
  191. package/ds-canonical/hooks/session_start_governance_check.sh +7 -2
  192. package/ds-canonical/hooks/stop_self_audit.sh +2 -2
  193. package/ds-canonical/hooks/tests/test_check_addon_subdir_ship.sh +3 -2
  194. package/ds-canonical/hooks/tests/test_check_consumer_app_invariants.sh +12 -0
  195. package/ds-canonical/hooks/tests/test_check_consumer_app_story_title.sh +3 -2
  196. package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +6 -4
  197. package/ds-canonical/hooks/tests/test_check_consumer_no_ds_catalog.sh +7 -4
  198. package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +6 -4
  199. package/ds-canonical/hooks/tests/test_check_data_table_size_num_to_meta_width.sh +3 -2
  200. package/ds-canonical/hooks/tests/test_check_fork_user_plugin_install.sh +3 -2
  201. package/ds-canonical/hooks/tests/test_check_plugin_fork_health.sh +9 -0
  202. package/ds-canonical/hooks/tests/test_check_propose_cite_required.sh +3 -2
  203. package/ds-canonical/hooks/tests/test_check_propose_discipline.sh +10 -0
  204. package/ds-canonical/hooks/tests/test_check_propose_plain_chinese.sh +3 -2
  205. package/ds-canonical/hooks/tests/test_check_storybook_addon_packaging.sh +10 -0
  206. package/ds-canonical/hooks/tests/test_check_storybook_addon_preset_cjs.sh +3 -2
  207. package/ds-canonical/references/build-ui-canonicals.md +2 -2
  208. package/ds-canonical/references/composition-fidelity.md +3 -3
  209. package/ds-canonical/references/naming-conventions.md +1 -0
  210. package/ds-canonical/references/ssot-consultation.md +1 -1
  211. package/ds-canonical/references/ssot-index.md +7 -7
  212. package/ds-canonical/rules/meta-patterns.md +5 -5
  213. package/ds-canonical/rules/self-verify.md +1 -1
  214. package/ds-canonical/rules/story-rules.md +2 -0
  215. package/ds-canonical/rules/ui-development.md +1 -1
  216. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +11 -2
  217. package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +1 -1
  218. package/ds-canonical/skills/design-system-audit/SKILL.md +15 -15
  219. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +4 -3
  220. package/ds-story-manifest.json +15 -21
  221. package/llms-full.txt +9 -5
  222. package/llms.txt +2 -2
  223. package/package.json +1 -1
  224. package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
  225. package/src/components/Accordion/accordion.spec.md +22 -5
  226. package/src/components/Accordion/accordion.tsx +1 -1
  227. package/src/components/Alert/alert.anatomy.stories.tsx +4 -4
  228. package/src/components/Alert/alert.principles.stories.tsx +5 -5
  229. package/src/components/Alert/alert.spec.md +16 -11
  230. package/src/components/Alert/alert.stories.tsx +5 -5
  231. package/src/components/Alert/alert.tsx +2 -2
  232. package/src/components/AppShell/app-shell.principles.stories.tsx +68 -21
  233. package/src/components/AppShell/app-shell.spec.md +17 -24
  234. package/src/components/AppShell/app-shell.tsx +4 -3
  235. package/src/components/AspectRatio/aspect-ratio.anatomy.stories.tsx +3 -3
  236. package/src/components/AspectRatio/aspect-ratio.spec.md +15 -1
  237. package/src/components/Avatar/avatar.anatomy.stories.tsx +1 -1
  238. package/src/components/Avatar/avatar.principles.stories.tsx +8 -8
  239. package/src/components/Avatar/avatar.spec.md +25 -54
  240. package/src/components/Avatar/avatar.tsx +2 -2
  241. package/src/components/Badge/badge.principles.stories.tsx +2 -2
  242. package/src/components/Badge/badge.spec.md +22 -13
  243. package/src/components/Badge/badge.tsx +1 -1
  244. package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +5 -2
  245. package/src/components/Breadcrumb/breadcrumb.spec.md +25 -25
  246. package/src/components/Breadcrumb/breadcrumb.stories.tsx +7 -32
  247. package/src/components/Breadcrumb/breadcrumb.tsx +1 -1
  248. package/src/components/BulkActionBar/bulk-action-bar.principles.stories.tsx +2 -2
  249. package/src/components/BulkActionBar/bulk-action-bar.spec.md +20 -6
  250. package/src/components/BulkActionBar/bulk-action-bar.tsx +2 -2
  251. package/src/components/Button/button.anatomy.stories.tsx +2 -2
  252. package/src/components/Button/button.spec.md +19 -17
  253. package/src/components/Button/button.stories.tsx +1 -1
  254. package/src/components/Button/button.tsx +10 -9
  255. package/src/components/Calendar/calendar.anatomy.stories.tsx +1 -1
  256. package/src/components/Calendar/calendar.spec.md +37 -17
  257. package/src/components/Calendar/calendar.tsx +26 -22
  258. package/src/components/Carousel/carousel.anatomy.stories.tsx +6 -6
  259. package/src/components/Carousel/carousel.principles.stories.tsx +1 -1
  260. package/src/components/Carousel/carousel.spec.md +23 -3
  261. package/src/components/Carousel/carousel.tsx +19 -4
  262. package/src/components/Chart/chart.anatomy.stories.tsx +1 -1
  263. package/src/components/Chart/chart.spec.md +20 -1
  264. package/src/components/Checkbox/checkbox-group.tsx +2 -1
  265. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +4 -4
  266. package/src/components/Checkbox/checkbox.principles.stories.tsx +2 -2
  267. package/src/components/Checkbox/checkbox.spec.md +35 -15
  268. package/src/components/Checkbox/checkbox.stories.tsx +1 -1
  269. package/src/components/Checkbox/checkbox.tsx +14 -3
  270. package/src/components/Chip/chip.anatomy.stories.tsx +5 -5
  271. package/src/components/Chip/chip.principles.stories.tsx +9 -3
  272. package/src/components/Chip/chip.spec.md +8 -9
  273. package/src/components/Chip/chip.tsx +2 -2
  274. package/src/components/CircularProgress/circular-progress.anatomy.stories.tsx +6 -6
  275. package/src/components/CircularProgress/circular-progress.spec.md +10 -11
  276. package/src/components/CircularProgress/circular-progress.stories.tsx +36 -43
  277. package/src/components/CircularProgress/circular-progress.tsx +1 -1
  278. package/src/components/Coachmark/coachmark.anatomy.stories.tsx +1 -1
  279. package/src/components/Coachmark/coachmark.principles.stories.tsx +14 -29
  280. package/src/components/Coachmark/coachmark.spec.md +21 -13
  281. package/src/components/Coachmark/coachmark.tsx +4 -4
  282. package/src/components/Combobox/combobox.anatomy.stories.tsx +28 -28
  283. package/src/components/Combobox/combobox.principles.stories.tsx +1 -1
  284. package/src/components/Combobox/combobox.spec.md +25 -7
  285. package/src/components/Combobox/combobox.tsx +12 -3
  286. package/src/components/Command/command.anatomy.stories.tsx +1 -1
  287. package/src/components/Command/command.principles.stories.tsx +8 -8
  288. package/src/components/Command/command.spec.md +18 -8
  289. package/src/components/Command/command.tsx +8 -3
  290. package/src/components/DataTable/data-table-sort-manager.tsx +1 -1
  291. package/src/components/DataTable/data-table.anatomy.stories.tsx +9 -7
  292. package/src/components/DataTable/data-table.principles.stories.tsx +3 -3
  293. package/src/components/DataTable/data-table.spec.md +15 -11
  294. package/src/components/DataTable/data-table.stories.tsx +58 -13
  295. package/src/components/DataTable/data-table.tsx +13 -0
  296. package/src/components/DataTable/filter-operators.spec.md +19 -27
  297. package/src/components/DateGrid/date-grid.anatomy.stories.tsx +8 -8
  298. package/src/components/DateGrid/date-grid.principles.stories.tsx +7 -7
  299. package/src/components/DateGrid/date-grid.spec.md +17 -14
  300. package/src/components/DateGrid/date-grid.tsx +8 -4
  301. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +11 -15
  302. package/src/components/DatePicker/date-picker.principles.stories.tsx +8 -8
  303. package/src/components/DatePicker/date-picker.spec.md +40 -36
  304. package/src/components/DatePicker/date-picker.stories.tsx +23 -53
  305. package/src/components/DatePicker/date-picker.tsx +12 -6
  306. package/src/components/DescriptionList/description-list.anatomy.stories.tsx +2 -2
  307. package/src/components/DescriptionList/description-list.principles.stories.tsx +4 -18
  308. package/src/components/DescriptionList/description-list.spec.md +9 -3
  309. package/src/components/DescriptionList/description-list.stories.tsx +2 -18
  310. package/src/components/DescriptionList/description-list.tsx +1 -1
  311. package/src/components/Dialog/dialog.principles.stories.tsx +1 -1
  312. package/src/components/Dialog/dialog.spec.md +26 -11
  313. package/src/components/Dialog/dialog.stories.tsx +159 -184
  314. package/src/components/Dialog/dialog.tsx +2 -1
  315. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +2 -2
  316. package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +16 -17
  317. package/src/components/DropdownMenu/dropdown-menu.spec.md +10 -15
  318. package/src/components/DropdownMenu/dropdown-menu.stories.tsx +13 -15
  319. package/src/components/DropdownMenu/dropdown-menu.tsx +12 -2
  320. package/src/components/Empty/empty.spec.md +19 -18
  321. package/src/components/Empty/empty.tsx +1 -1
  322. package/src/components/Field/field-controls.spec.md +52 -41
  323. package/src/components/Field/field-wrapper.tsx +2 -2
  324. package/src/components/Field/field.anatomy.stories.tsx +6 -5
  325. package/src/components/Field/field.principles.stories.tsx +8 -7
  326. package/src/components/Field/field.spec.md +42 -20
  327. package/src/components/Field/field.stories.tsx +9 -7
  328. package/src/components/Field/field.tsx +6 -3
  329. package/src/components/Field/form-validation.spec.md +20 -19
  330. package/src/components/FieldControlGroup/field-control-group.anatomy.stories.tsx +16 -15
  331. package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +5 -1
  332. package/src/components/FieldControlGroup/field-control-group.spec.md +17 -1
  333. package/src/components/FieldControlGroup/field-control-group.stories.tsx +9 -9
  334. package/src/components/FieldControlGroup/field-control-group.tsx +4 -3
  335. package/src/components/FileItem/file-item.anatomy.stories.tsx +7 -17
  336. package/src/components/FileItem/file-item.principles.stories.tsx +7 -7
  337. package/src/components/FileItem/file-item.spec.md +24 -24
  338. package/src/components/FileUpload/file-upload.anatomy.stories.tsx +4 -2
  339. package/src/components/FileUpload/file-upload.principles.stories.tsx +10 -12
  340. package/src/components/FileUpload/file-upload.spec.md +37 -8
  341. package/src/components/FileUpload/file-upload.tsx +5 -3
  342. package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +16 -11
  343. package/src/components/FileViewer/file-viewer.principles.stories.tsx +4 -4
  344. package/src/components/FileViewer/file-viewer.spec.md +7 -19
  345. package/src/components/FileViewer/file-viewer.stories.tsx +3 -3
  346. package/src/components/FileViewer/file-viewer.tsx +42 -16
  347. package/src/components/HoverCard/hover-card.spec.md +20 -10
  348. package/src/components/HoverCard/hover-card.stories.tsx +1 -1
  349. package/src/components/HoverCard/hover-card.tsx +12 -1
  350. package/src/components/Input/input.anatomy.stories.tsx +4 -4
  351. package/src/components/Input/input.principles.stories.tsx +4 -31
  352. package/src/components/Input/input.spec.md +16 -4
  353. package/src/components/LinkInput/link-input.anatomy.stories.tsx +1 -1
  354. package/src/components/LinkInput/link-input.principles.stories.tsx +2 -2
  355. package/src/components/LinkInput/link-input.spec.md +14 -1
  356. package/src/components/Menu/menu-item.principles.stories.tsx +5 -5
  357. package/src/components/Menu/menu-item.spec.md +24 -12
  358. package/src/components/Menu/menu-item.tsx +7 -3
  359. package/src/components/Notice/notice.principles.stories.tsx +7 -7
  360. package/src/components/Notice/notice.spec.md +7 -5
  361. package/src/components/Notice/notice.tsx +5 -1
  362. package/src/components/NumberInput/number-input.anatomy.stories.tsx +4 -4
  363. package/src/components/NumberInput/number-input.principles.stories.tsx +13 -35
  364. package/src/components/NumberInput/number-input.spec.md +19 -0
  365. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +4 -3
  366. package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +2 -5
  367. package/src/components/OverflowIndicator/overflow-indicator.spec.md +9 -1
  368. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +6 -42
  369. package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -3
  370. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +11 -2
  371. package/src/components/PeoplePicker/people-picker.spec.md +26 -12
  372. package/src/components/PeoplePicker/people-picker.stories.tsx +14 -15
  373. package/src/components/PeoplePicker/people-picker.tsx +12 -4
  374. package/src/components/Popover/popover.spec.md +20 -11
  375. package/src/components/Popover/popover.tsx +2 -2
  376. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +1 -1
  377. package/src/components/ProfileCard/profile-card.principles.stories.tsx +29 -25
  378. package/src/components/ProfileCard/profile-card.spec.md +30 -10
  379. package/src/components/ProfileCard/profile-card.tsx +12 -7
  380. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +1 -1
  381. package/src/components/ProgressBar/progress-bar.principles.stories.tsx +7 -5
  382. package/src/components/ProgressBar/progress-bar.spec.md +9 -1
  383. package/src/components/ProgressBar/progress-bar.stories.tsx +1 -1
  384. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +6 -3
  385. package/src/components/RadioGroup/radio-group.principles.stories.tsx +6 -13
  386. package/src/components/RadioGroup/radio-group.spec.md +7 -1
  387. package/src/components/RadioGroup/radio-group.tsx +10 -0
  388. package/src/components/Rating/rating.anatomy.stories.tsx +1 -0
  389. package/src/components/Rating/rating.principles.stories.tsx +9 -6
  390. package/src/components/Rating/rating.spec.md +13 -7
  391. package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +44 -24
  392. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +51 -57
  393. package/src/components/ScrollArea/scroll-area.spec.md +5 -7
  394. package/src/components/ScrollArea/scroll-area.stories.tsx +110 -60
  395. package/src/components/ScrollArea/scroll-area.tsx +1 -1
  396. package/src/components/SegmentedControl/segmented-control.anatomy.stories.tsx +1 -1
  397. package/src/components/SegmentedControl/segmented-control.spec.md +15 -14
  398. package/src/components/SegmentedControl/segmented-control.stories.tsx +1 -1
  399. package/src/components/Select/select.anatomy.stories.tsx +12 -11
  400. package/src/components/Select/select.principles.stories.tsx +3 -3
  401. package/src/components/Select/select.spec.md +34 -8
  402. package/src/components/Select/select.stories.tsx +2 -2
  403. package/src/components/Select/select.tsx +18 -3
  404. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +2 -2
  405. package/src/components/SelectMenu/select-menu.principles.stories.tsx +5 -5
  406. package/src/components/SelectMenu/select-menu.spec.md +19 -12
  407. package/src/components/SelectMenu/select-menu.stories.tsx +34 -27
  408. package/src/components/SelectMenu/select-menu.tsx +14 -3
  409. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +1 -1
  410. package/src/components/SelectionControl/selection-item.spec.md +13 -2
  411. package/src/components/SelectionControl/selection-item.stories.tsx +1 -1
  412. package/src/components/SelectionControl/selection-item.tsx +8 -2
  413. package/src/components/Separator/separator.principles.stories.tsx +2 -2
  414. package/src/components/Separator/separator.spec.md +11 -5
  415. package/src/components/Sheet/sheet.anatomy.stories.tsx +7 -6
  416. package/src/components/Sheet/sheet.principles.stories.tsx +18 -38
  417. package/src/components/Sheet/sheet.spec.md +9 -11
  418. package/src/components/Sheet/sheet.stories.tsx +2 -2
  419. package/src/components/Sheet/sheet.tsx +6 -5
  420. package/src/components/Sidebar/sidebar.anatomy.stories.tsx +42 -33
  421. package/src/components/Sidebar/sidebar.principles.stories.tsx +4 -4
  422. package/src/components/Sidebar/sidebar.spec.md +22 -17
  423. package/src/components/Sidebar/sidebar.stories.tsx +16 -0
  424. package/src/components/Sidebar/sidebar.tsx +15 -7
  425. package/src/components/Skeleton/skeleton.anatomy.stories.tsx +2 -2
  426. package/src/components/Skeleton/skeleton.principles.stories.tsx +20 -7
  427. package/src/components/Skeleton/skeleton.spec.md +6 -4
  428. package/src/components/Skeleton/skeleton.stories.tsx +34 -26
  429. package/src/components/Skeleton/skeleton.tsx +1 -1
  430. package/src/components/Slider/slider.principles.stories.tsx +3 -3
  431. package/src/components/Slider/slider.spec.md +16 -12
  432. package/src/components/Slider/slider.stories.tsx +2 -18
  433. package/src/components/Slider/slider.tsx +6 -2
  434. package/src/components/Steps/steps.anatomy.stories.tsx +3 -3
  435. package/src/components/Steps/steps.principles.stories.tsx +9 -12
  436. package/src/components/Steps/steps.spec.md +31 -25
  437. package/src/components/Steps/steps.stories.tsx +5 -40
  438. package/src/components/Steps/steps.tsx +17 -12
  439. package/src/components/Switch/switch.principles.stories.tsx +1 -1
  440. package/src/components/Switch/switch.spec.md +13 -0
  441. package/src/components/Switch/switch.tsx +3 -3
  442. package/src/components/Tabs/tabs.anatomy.stories.tsx +4 -4
  443. package/src/components/Tabs/tabs.principles.stories.tsx +1 -1
  444. package/src/components/Tabs/tabs.spec.md +13 -6
  445. package/src/components/Tabs/tabs.stories.tsx +3 -3
  446. package/src/components/Tabs/tabs.tsx +2 -2
  447. package/src/components/Tag/tag.anatomy.stories.tsx +15 -15
  448. package/src/components/Tag/tag.principles.stories.tsx +1 -1
  449. package/src/components/Tag/tag.spec.md +25 -5
  450. package/src/components/Textarea/textarea.anatomy.stories.tsx +3 -3
  451. package/src/components/Textarea/textarea.principles.stories.tsx +7 -7
  452. package/src/components/Textarea/textarea.spec.md +15 -3
  453. package/src/components/Textarea/textarea.tsx +1 -1
  454. package/src/components/TimePicker/time-columns.tsx +1 -1
  455. package/src/components/TimePicker/time-picker.anatomy.stories.tsx +8 -2
  456. package/src/components/TimePicker/time-picker.spec.md +23 -3
  457. package/src/components/TimePicker/time-picker.tsx +5 -3
  458. package/src/components/Toast/toast.anatomy.stories.tsx +1 -1
  459. package/src/components/Toast/toast.spec.md +7 -4
  460. package/src/components/Toast/toast.stories.tsx +12 -6
  461. package/src/components/Toast/toast.tsx +1 -1
  462. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +1 -1
  463. package/src/components/Tooltip/tooltip.spec.md +11 -8
  464. package/src/components/Tooltip/tooltip.tsx +1 -1
  465. package/src/components/TreeView/tree-view.anatomy.stories.tsx +25 -9
  466. package/src/components/TreeView/tree-view.principles.stories.tsx +5 -5
  467. package/src/components/TreeView/tree-view.spec.md +11 -9
  468. package/src/components/TreeView/tree-view.stories.tsx +5 -3
  469. package/src/components/TreeView/tree-view.tsx +8 -5
  470. package/src/patterns/action-bar/action-bar.spec.md +11 -4
  471. package/src/patterns/element-anatomy/element-anatomy.spec.md +8 -6
  472. package/src/patterns/element-anatomy/inline-action.spec.md +18 -18
  473. package/src/patterns/element-anatomy/item-anatomy.spec.md +47 -42
  474. package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -6
  475. package/src/patterns/element-anatomy/item-anatomy.tsx +3 -3
  476. package/src/patterns/header-canonical/chrome-header.tsx +3 -2
  477. package/src/patterns/header-canonical/header-canonical.spec.md +24 -11
  478. package/src/patterns/header-canonical/header-canonical.stories.tsx +9 -9
  479. package/src/patterns/horizontal-overflow/horizontal-overflow.spec.md +22 -12
  480. package/src/patterns/overlay-surface/overlay-surface.spec.md +43 -39
  481. package/src/patterns/overlay-surface/overlay-surface.tsx +3 -2
  482. package/src/patterns/resize-handle/resize-handle.spec.md +10 -1
  483. package/src/patterns/resize-handle/resize-handle.stories.tsx +7 -7
  484. package/src/tokens/README.md +5 -2
  485. package/src/tokens/color/color.spec.md +17 -10
  486. package/src/tokens/color/semantic.css +2 -0
  487. package/src/tokens/density/density.spec.md +4 -14
  488. package/src/tokens/elevation/elevation.spec.md +7 -8
  489. package/src/tokens/layoutSpace/layoutSpace.spec.md +20 -27
  490. package/src/tokens/motion/motion.spec.md +15 -7
  491. package/src/tokens/opacity/opacity.spec.md +15 -26
  492. package/src/tokens/orphan-tokens.spec.md +14 -3
  493. package/src/tokens/radius/radius.spec.md +13 -15
  494. package/src/tokens/token-system.spec.md +10 -13
  495. package/src/tokens/typography/typography.spec.md +8 -12
  496. package/src/tokens/uiSize/uiSize.spec.md +28 -16
  497. /package/ds-canonical/hooks/{check_addon_subdir_ship.sh → retired/2026-06-11-prune-merge/check_addon_subdir_ship.sh} +0 -0
  498. /package/ds-canonical/hooks/{check_consumer_app_story_title.sh → retired/2026-06-11-prune-merge/check_consumer_app_story_title.sh} +0 -0
  499. /package/ds-canonical/hooks/{check_consumer_ds_primitive_misuse.sh → retired/2026-06-11-prune-merge/check_consumer_ds_primitive_misuse.sh} +0 -0
  500. /package/ds-canonical/hooks/{check_consumer_no_ds_catalog.sh → retired/2026-06-11-prune-merge/check_consumer_no_ds_catalog.sh} +0 -0
  501. /package/ds-canonical/hooks/{check_consumer_story_baseline.sh → retired/2026-06-11-prune-merge/check_consumer_story_baseline.sh} +0 -0
  502. /package/ds-canonical/hooks/{check_data_table_size_num_to_meta_width.sh → retired/2026-06-11-prune-merge/check_data_table_size_num_to_meta_width.sh} +0 -0
  503. /package/ds-canonical/hooks/{check_fork_user_plugin_install.sh → retired/2026-06-11-prune-merge/check_fork_user_plugin_install.sh} +0 -0
  504. /package/ds-canonical/hooks/{check_plugin_freshness.sh → retired/2026-06-11-prune-merge/check_plugin_freshness.sh} +0 -0
  505. /package/ds-canonical/hooks/{check_propose_cite_required.sh → retired/2026-06-11-prune-merge/check_propose_cite_required.sh} +0 -0
  506. /package/ds-canonical/hooks/{check_propose_plain_chinese.sh → retired/2026-06-11-prune-merge/check_propose_plain_chinese.sh} +0 -0
  507. /package/ds-canonical/hooks/{check_storybook_addon_preset_cjs.sh → retired/2026-06-11-prune-merge/check_storybook_addon_preset_cjs.sh} +0 -0
@@ -70,7 +70,7 @@ Semantic token 直接指向 primitive(無中間層)。
70
70
  **注意(categorical `red` vs semantic `--error` vs primitive `deep-orange` 三者獨立)**:
71
71
  - `--error` = `--color-deep-orange-6`(primitive `deep-orange`,hue 38)—— semantic 狀態色,用於錯誤訊息。
72
72
  - Tag / Avatar / Calendar 的 categorical `red` variant = `--color-red-*`(品牌紅家族 hue 25,與 `--brand` `#DF3232` 同族)。
73
- - **三者無映射關係**:`red`(categorical 色相 hue 25)≠ `deep-orange`(primitive hue 38)≠ `--error`(semantic = deep-orange)。categorical 色相 1:1 對 `--color-{hue}-*`,零 offset(SSOT `tokens/categorical-color.ts`)。2026-06-04 修正原「red variant 接 deep-orange」offset。
73
+ - **三者無映射關係**:categorical `red`(hue 25)≠ `deep-orange`(primitive hue 38)≠ `--error`(semantic = deep-orange)。categorical 色相 1:1 對 `--color-{hue}-*`,零 offset(SSOT `tokens/categorical-color.ts`)。2026-06-04 修正原「red variant 接 deep-orange」offset。
74
74
 
75
75
  Tailwind utility 透過 `@theme inline` 橋接 semantic token,元件寫 `bg-primary` 或 `bg-error` 即可。Tag / Avatar 使用 CSS 變數任意值(`bg-[var(--color-blue-6)]`)。
76
76
 
@@ -174,6 +174,8 @@ Semantic token 按**載體類型**分成四個 family,**family 之間的 token
174
174
 
175
175
  ## Icon 色彩原則
176
176
 
177
+ Icon 色彩 canonical 的 SSOT 住 `patterns/element-anatomy/item-anatomy.spec.md`「Icon 色彩原則」——核心規則:icon 代表內容/類別 → 與 label 同色;icon 純指示方向 → `fg-muted`;disabled 統一 `fg-disabled`。本檔不重述(Rule-of-3 pointer)。
178
+
177
179
  ## 語義色
178
180
 
179
181
  ### Action — Primary
@@ -225,7 +227,7 @@ Semantic token 按**載體類型**分成四個 family,**family 之間的 token
225
227
 
226
228
  | 底色 | 文字色 | 原因 |
227
229
  |------|--------|------|
228
- | `bg-warning`(yellow-6,滿版) | `text-on-emphasis-dark`(`black-a85`,深色) | 黃色亮度高,白字對比不足,必須用深色(通用亮底深字 token,非 warning 專屬) |
230
+ | `bg-warning`(yellow-6,滿版) | `text-on-emphasis-dark`(`black-a85`,深色) | 黃色亮度高,白字對比不足,必須用深色(通用亮底深字 token,非 warning 專屬;定義見下「`--on-emphasis` / `--on-emphasis-dark` 配對」段) |
229
231
  | `bg-warning-subtle`(淡黃) | `text-[yellow-7]`(step-7) | subtle 底色夠淺,深一階的黃色文字可辨識(見「文字色 Step 原則」) |
230
232
 
231
233
  ### Indicator — Notification
@@ -455,7 +457,7 @@ Dark mode 覆寫:hover/active 方向反轉(hover → step-7,active → ste
455
457
  - 跨 mode 一致的方向(dark mode 必須 swap step 號)
456
458
  - 但 Tag 的「藍」≠ semantic primary(解耦:改 primary 不應影響 Tag)
457
459
 
458
- 直接用 primitive `--color-blue-5/-7` 不行——dark mode 公式互換會方向顛倒。所以擴展 semantic 互動 token 模式到所有 8 個非語意色相。
460
+ 直接用 primitive `--color-blue-5/-7` 不行——dark mode 公式互換會方向顛倒。所以擴展 semantic 互動 token 模式到全部 12 個 categorical 色相(SSOT `tokens/categorical-color.ts` `CATEGORICAL_HUES`)。
459
461
 
460
462
  #### 嚴格限制
461
463
 
@@ -657,7 +659,7 @@ Dark mode 覆寫:hover/active 方向反轉(hover → step-7,active → ste
657
659
 
658
660
  **跟 `bg-neutral-hover` / `bg-neutral-active` 的區別**:neutral 系列表達**互動**狀態(hover / 選中);muted / secondary 表達**結構性的靜態層級** — 即使沒有互動,它永遠是這個顏色。
659
661
 
660
- **邊界 — component disabled bg 不走 muted**:Button / Input / Checkbox 等元件 disabled state 走 `--bg-disabled` semantic,不是 `--muted`(同值 neutral-2 但不同 owner — `--bg-disabled` 是 component-state token,`--muted` 是 surface-non-interactive token,per L169「同值不同語意拆 token」rule)
662
+ **邊界 — component disabled bg 不走 muted**:Button / Input / Checkbox 等元件 disabled state 走 `--bg-disabled` semantic,不是 `--muted`(同值 neutral-2 但不同 owner — `--bg-disabled` 是 component-state token,`--muted` 是 surface-non-interactive token,per「為什麼同值仍分兩個 token」段 rule)。**Readonly state 同理但用自己的 token `--bg-readonly`**(2026-06-10):readonly ≠ disabled(可聚焦/選取/提交,僅不可改值,per Carbon「navigable but not operable」),不借 `--bg-disabled` 名;也不走 `--muted`(readonly 是互動元件 state,非 Skeleton 類靜態 surface)。三者同值 neutral-2、owner 獨立,可分離演進。
661
663
 
662
664
  ```tsx
663
665
  <Skeleton className="h-4 w-32" /> {/* bg-muted — placeholder 語意 */}
@@ -755,6 +757,16 @@ CSS 變數在定義元素上解析。`:root` 的 `--foreground: var(--color-neut
755
757
 
756
758
  容器自身的樣式(如 tooltip 的 `bg-tooltip`)不受子 div 的 `data-theme` 影響——`data-theme` 在子 div 上,只影響子元素。
757
759
 
760
+ ## 常見誤解
761
+
762
+ 各誤解的完整推理已在本檔對應段落,此處彙整索引:
763
+
764
+ - 「`--primary` 跟 `--info` 同色所以可互換」— 語義截然不同,status 元件混入 `--primary` 即 fail(見「Status」段 + `status-color-invariant.mjs`)。
765
+ - 「`--fg-disabled` 剛好是我要的灰,拿來當 bg」— 跨 family 借用是 smell(見「fg token 不可當 bg 用」段 Slider case)。
766
+ - 「`bg-muted` / `bg-secondary` 都是淡灰隨便選」— 前者 = 退化 / placeholder,後者 = 正常存在但退後一級(見「Static Subtle Background」段)。
767
+ - 「`--neutral-active` / `--neutral-selected` 同值可合併」— transient vs persistent 語意獨立(見「active vs selected」段)。
768
+ - 「categorical `red` = `--error`」— hue 25 vs deep-orange,完全無關(見「消費規則」注意事項)。
769
+
758
770
  ## 禁止事項
759
771
 
760
772
  ```tsx
@@ -774,16 +786,11 @@ SSOT → `.claude/references/structural-token-retention.md`(6 類保留 + sub-ag
774
786
 
775
787
  > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
776
788
 
777
- - `opacity.spec.md`
778
-
779
- ## 被引用(auto-maintained,Dim 3 reciprocal audit)
780
-
781
- > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
782
-
783
789
  - `chart.spec.md`
784
790
  - `date-grid.spec.md`
785
791
  - `file-item.spec.md`
786
792
  - `notice.spec.md`
793
+ - `opacity.spec.md`
787
794
  - `progress-bar.spec.md`
788
795
  - `separator.spec.md`
789
796
  - `skeleton.spec.md`
@@ -328,6 +328,7 @@
328
328
  --neutral-hover: var(--color-neutral-1);
329
329
  --neutral-active: var(--color-neutral-2);
330
330
  --bg-disabled: var(--color-neutral-2);
331
+ --bg-readonly: var(--color-neutral-2); /* readonly 鎖定欄位 chrome — 同值但獨立 owner(≠ disabled:可聚焦/選取/提交,僅不可改值);詳 color.spec.md Static Subtle 邊界 */
331
332
 
332
333
  /* Neutral Interactive — Selected state family
333
334
  ─────────────────────────────────────────────────────────────
@@ -515,6 +516,7 @@
515
516
  --color-neutral-hover: var(--neutral-hover);
516
517
  --color-neutral-active: var(--neutral-active);
517
518
  --color-disabled: var(--bg-disabled);
519
+ --color-readonly: var(--bg-readonly);
518
520
 
519
521
  /* Neutral Interaction — Selected state family */
520
522
  --color-neutral-selected: var(--neutral-selected);
@@ -18,7 +18,7 @@ Density 由**兩個獨立維度**構成,並配合一個 convenience attribute
18
18
 
19
19
  **反例**(耦合):Material M3 / Polaris density 模式綁 control size + spacing — 無法「寬版面 + 標準 control」的場景。
20
20
 
21
- **我們走 decouple 流派**:解決 Dialog / overlay chrome 的痛點 — header 想要寬鬆呼吸(layout=lg),但不要被 button chrome 撐高(ui-size 跟 page 走 md)。
21
+ **我們走 decouple 流派**:解決 Dialog / overlay chrome 的痛點 — header 想要版面間距寬鬆(layout-space=lg),但不要被 button chrome 撐高(ui-size 跟 page 走 md)。
22
22
 
23
23
  ## 預設同步(density convenience)
24
24
 
@@ -35,7 +35,7 @@ Density 由**兩個獨立維度**構成,並配合一個 convenience attribute
35
35
 
36
36
  ## 解耦用法(canonical 情境)
37
37
 
38
- 當需要「layout 寬鬆 + control 標準」時,**顯式設兩個 attribute**:
38
+ 當需要「版面間距寬鬆(layout-space)+ 控件高度標準(ui-size)」時,**顯式設兩個 attribute**:
39
39
 
40
40
  ### Canonical 情境 1 — 歷史備忘(Dialog 已撤回)
41
41
 
@@ -108,20 +108,10 @@ document.documentElement.setAttribute('data-layout-space', 'md')
108
108
  | Tooltip | `data-density="md"` | 同 Popover |
109
109
  | Sidebar | 無(繼承 page) | Sidebar 是 inline chrome(非 Portal 逃逸),跟隨 page density;size="md" 在 density="lg" 下自動變 36px row(見 sidebar.spec.md「Row size 跟 density 的差別」)|
110
110
 
111
+ **邊界:page density=lg 下的 Portal overlay**——Popover / DropdownMenu / Tooltip 在 `data-density="lg"` 的 page 上仍鎖 `md`(code:各 Content 自設 `data-density="md"`)。這不是漏接:Portal 到 body 本就不繼承 subtree density(M3),鎖 md 是 overlay「compact」語意的刻意設計(2026-04-22 v5 canonical)。
112
+
111
113
  ## Anti-patterns(禁止)
112
114
 
113
115
  - ❌ 元件同時設 `data-density` + `data-ui-size`(重複,以後者為準但混亂)
114
116
  - ❌ Overlay Portal 元件不自設 density(Portal 到 body 不繼承 trigger — 見 Meta-Pattern M3)
115
117
  - ❌ 為了追求表面一致性硬把 Dialog button 綁 lg ui-size(犧牲 header 高度 / strapline 彈性)
116
-
117
- ## 被引用(auto-maintained,Dim 3 reciprocal audit)
118
-
119
- > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
120
-
121
- - `dialog.spec.md`
122
- - `dropdown-menu.spec.md`
123
- - `popover.spec.md`
124
- - `sheet.spec.md`
125
- - `sidebar.spec.md`
126
- - `tooltip.spec.md`
127
- - `uiSize.spec.md`
@@ -1,3 +1,5 @@
1
+ <!-- @benchmark-cited: D5 retrofit backfill 2026-06-10 — body world-class claims marked per-claim inline;對齊 token spec 家族 7/9 既有 marker 慣例(deep-audit A.0 抓漏)。 -->
2
+
1
3
  # Elevation 設計原則
2
4
 
3
5
  Elevation 定義陰影層級,區分內容層(Card)和浮層(Modal/Popover)的視覺深度。
@@ -16,11 +18,11 @@ Elevation 定義陰影層級,區分內容層(Card)和浮層(Modal/Popove
16
18
  | Token | 用途 | 對應元件 |
17
19
  |-------|------|----------|
18
20
  | `--elevation-100` | 頁面內容層,靜止 | Card |
19
- | `--elevation-100-hover` | 頁面內容層,hover / 拖拽 | 可拖拽 card |
21
+ | `--elevation-100-hover` | 頁面內容層,hover / 拖拽 lift | —(目前無 DS 內建 consumer;預留給 consumer 的可拖拽 / hover-lift card,如 board card drag) |
20
22
  | `--elevation-200` | 浮層,靜止 | Modal、popover、dropdown、overlay drawer |
21
- | `--elevation-200-hover` | 浮層,hover | — |
23
+ | `--elevation-200-hover` | 浮層,hover | —(同上,預留) |
22
24
 
23
- elevation-100 < elevation-200,數字越大浮起越高。
25
+ elevation-100 < elevation-200,數字越大浮起越高。`*-hover` 兩枚為靜止 token 的「抬升一階」變體:元素被 hover / 拖起時切換,幾何(offset / blur)不變、只加深陰影 alpha(`tokens/color/primitives.css` 定義,light / dark 各一組)。
24
26
 
25
27
  ## 與 Surface 的配對規則
26
28
 
@@ -46,6 +48,8 @@ elevation-100 < elevation-200,數字越大浮起越高。
46
48
 
47
49
  **SSOT** → `tokens/elevation/overlay-geometry.ts` exports `OVERLAY_SIDE_OFFSET = 8` / `OVERLAY_COLLISION_PADDING = 8`。所有 primitive `default` 必 import 該 const(M17 SSOT 必可傳播);Radix `sideOffset` 接 number 不接 CSS var,因此用 JS const 共用,改值只動一處全部聯動。
48
50
 
51
+ **視窗邊緣碰撞(邊界案例)**:浮層貼近 viewport 邊不足以容納時,Radix `avoidCollisions`(預設開)自動翻轉 / 平移,並與邊緣保持 `collisionPadding` = `OVERLAY_COLLISION_PADDING`(8px;Tooltip / Popover / DropdownMenu 皆接此 const)。例外:HoverCard 用 12(Radix / browser rounding 讓 visual padding 少 1-2px 的補償,見 `hover-card.tsx` 註解)。
52
+
49
53
  | 浮層類型 | sideOffset | 說明 |
50
54
  |---------|-----------|------|
51
55
  | Tooltip | 8px | TooltipContent 預設值 |
@@ -70,10 +74,5 @@ elevation-100 < elevation-200,數字越大浮起越高。
70
74
  > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
71
75
 
72
76
  - `motion.spec.md`
73
-
74
- ## 被引用(auto-maintained,Dim 3 reciprocal audit)
75
-
76
- > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
77
-
78
77
  - `slider.spec.md`
79
78
  - `token-system.spec.md`
@@ -1,4 +1,4 @@
1
- <!-- @benchmark-cited: D5 retrofit 2026-05-18 — body claims marked per-claim @benchmark-unverified inline; canonical source URLs in frontmatter benchmark list. -->
1
+ <!-- @benchmark-cited: D5 retrofit 2026-05-18 — body claims marked per-claim @benchmark-unverified inline(M22(d) 顯式撤回;本檔 frontmatter benchmark list,來源 URL 未補)。 -->
2
2
 
3
3
  # LayoutSpace 設計原則
4
4
 
@@ -105,7 +105,7 @@ Pattern C 的視覺邏輯見 `overlay-surface.spec.md`「Hover bg 貼邊 chrome
105
105
 
106
106
  **核心**:gap 只看親疏不看 role(原 v1「block-adjacent 一律 tight」過機械,違 Gestalt proximity)。
107
107
 
108
- 世界級對齊:Material 3 / Polaris / Apple HIG / Atlassian 都按「relationship not type」決定 spacing。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
108
+ 世界級對齊:Material 3 / Polaris / Apple HIG / Atlassian 都按「relationship not type」決定 spacing。 <!-- @benchmark-unverified -->
109
109
 
110
110
  ### 規則 4:底部 — 拆兩個 distinct 概念
111
111
 
@@ -137,22 +137,19 @@ Pattern C 的視覺邏輯見 `overlay-surface.spec.md`「Hover bg 貼邊 chrome
137
137
 
138
138
  **為何 loose 而非 tight**:Chrome 是 surface 視覺邊界 + 內容呼吸區;`tight` 足夠 inline list item,chrome 需更穩定 anchor 讓 title / dismiss / actions 不貼邊。
139
139
 
140
- **M8 8 家世界級對照**(default density 共識 16px):Material 3 Top App Bar 16dp / Carbon UI Shell 16px / Polaris Page Header 16px / Atlassian Page Header 16px / Apple HIG macOS Toolbar 16-20pt / Linear / Notion / GitHub Primer / Figma 全 16px。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
140
+ **M8 8 家世界級對照**(default density 共識 16px):Material 3 Top App Bar 16dp / Carbon UI Shell 16px / Polaris Page Header 16px / Atlassian Page Header 16px / Apple HIG macOS Toolbar 16-20pt / Linear / Notion / GitHub Primer / Figma 全 16px。 <!-- @benchmark-unverified -->
141
141
 
142
142
  **禁止**:硬寫 `px-4` / 自創值(`px-5`)/ 用 tight 當 chrome inline / 同 surface header/body/footer inline padding 不一致(三層左邊界必對齊)。
143
143
 
144
+ **RTL**:本系統水平 padding 一律 `px-*`(左右對稱、無方向性),RTL 下行為不變;方向性 spacing(`ps-*`/`pe-*`)未使用。
145
+
144
146
  ---
145
147
 
146
148
  ## 心智模型(三步推理 + 具體 self-questions)
147
149
 
148
150
  ### Step 1 — 判角色(對單一元素)
149
151
 
150
- 3 題:
151
- 1. 在該層 layout 占主導(寬度撐滿 + 高度 flex-1)嗎?
152
- 2. 視覺重量是「畫布」(占據 layout)還是「控件」(局部塊)?
153
- 3. 是該層展示主角(主導內容)嗎?
154
-
155
- 多數 yes → **region**;反之 → **element**。
152
+ 跑上方「元件角色」節的**判斷 3 題**(占主導? / 畫布 vs 控件? / 展示主角?)— 多數 yes → **region**;反之 → **element**。
156
153
 
157
154
  若 region 再問 1 題:有視覺邊界(底色 / 邊框 / 上下分隔線)嗎?
158
155
  - 有 → **bounded**(Card / Table with borders / Panel)
@@ -195,7 +192,7 @@ Pattern C 的視覺邏輯見 `overlay-surface.spec.md`「Hover bg 貼邊 chrome
195
192
  - **判親疏**:
196
193
  - bundled?(在元件 spec 裡寫成 bundle 嗎?) → **否**(consumer-composed)→ 跨範疇
197
194
  - functional 交互?A 不驅動 B,parallel siblings → **不相關**
198
- - **答**:`loose`(16/24)— 對齊 Material / Polaris / Apple HIG / Atlassian 共識 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
195
+ - **答**:`loose`(16/24)— 對齊 Material / Polaris / Apple HIG / Atlassian 共識 <!-- @benchmark-unverified -->
199
196
 
200
197
  ### 範例 2:Cmd+K menu 中 search input ↔ result list
201
198
 
@@ -221,16 +218,16 @@ Pattern C 的視覺邏輯見 `overlay-surface.spec.md`「Hover bg 貼邊 chrome
221
218
 
222
219
  - **走規則**:規則 4
223
220
  - **判**:後接 action button(在 SurfaceFooter 內)?**是** → 套 `bottom 48`
224
- - **答**:48(概念 A commitment 前留白)。`dialog.tsx:203` body 預設 `pb-bottom` 是此規則的實作(預期 body 後接 SurfaceFooter buttons),非 Dialog 例外
221
+ - **答**:48(概念 A commitment 前留白)。`dialog.tsx` DialogBody 預設 `pb-bottom` 是此規則的實作(預期 body 後接 SurfaceFooter buttons),非 Dialog 例外
225
222
 
226
223
  ### 範例 6:SurfaceFooter 內 [Cancel] ↔ [Save] gap
227
224
 
228
225
  - **走範疇判**(在規則 3 之前):
229
226
  - bundled?**是**(`button-group.spec` + `overlay-surface.spec` 都自帶 button arrangement canonical = `gap-2`/8px)
230
227
  - → 同範疇 / bundled 第一級,**layoutSpace 一般規則跳過**
231
- - **答**:`gap-2`(8)— 由 `button-group.tsx:51` / `overlay-surface.tsx:92`(SurfaceFooter)自帶 canonical own
228
+ - **答**:`gap-2`(8)— 由 `button-group.tsx:51` / `overlay-surface.tsx` SurfaceFooter 自帶 canonical own
232
229
 
233
- **注意**:規則 5「橫排並列」**只**適用 input fields(line 102 明文),不套 button group。Button spacing 屬 bundled-family canonical,不走 layoutSpace 一般 rule。
230
+ **注意**:規則 5「橫排並列」**只**適用 input fields,不套 button group(button spacing 屬 bundled-family canonical own,不走 layoutSpace 一般 rule)
234
231
 
235
232
  ---
236
233
 
@@ -270,19 +267,20 @@ Pattern C 的視覺邏輯見 `overlay-surface.spec.md`「Hover bg 貼邊 chrome
270
267
 
271
268
  ---
272
269
 
273
- ## 模式切換
270
+ ## 常見誤解
274
271
 
275
- ```html
276
- <html data-density="md">
277
- ```
272
+ - ❌ **元素間 gap 硬寫 `gap-4`**:容器級 gap 走規則 3 token(`tight` / `loose`);固定 `gap-2` / `gap-4` 只限規則 5 橫排 input 與 bundled family 自帶 canonical
273
+ - ❌ **Pattern C 場景把 padding 寫在 list 容器**:hover bg 需 flush 貼邊,padding 必須 item 自帶(規則 1C);寫在容器 = hover bg 縮一圈
274
+ - ❌ **unbounded list 漏自帶 py**:規則 2 / 4 的「0」前提是 list 自帶 py 撐 spacing;漏 py = 內容貼 chrome 邊
278
275
 
279
- ```ts
280
- document.documentElement.setAttribute('data-density', 'lg')
281
- ```
276
+ ---
282
277
 
283
- 單獨控制版面間距而不影響元件尺寸:
278
+ ## 模式切換
284
279
 
285
280
  ```ts
281
+ // 全域 density(含 layout space)
282
+ document.documentElement.setAttribute('data-density', 'lg')
283
+ // 單獨控制版面間距而不影響元件尺寸
286
284
  document.documentElement.setAttribute('data-layout-space', 'lg')
287
285
  ```
288
286
 
@@ -301,13 +299,8 @@ document.documentElement.setAttribute('data-layout-space', 'lg')
301
299
  > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
302
300
 
303
301
  - `app-shell.spec.md`
304
-
305
- ## 被引用(auto-maintained,Dim 3 reciprocal audit)
306
-
307
- > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
308
-
309
302
  - `description-list.spec.md`
310
303
  - `empty.spec.md`
311
- - `file-viewer.spec.md`
304
+ - `overlay-surface.spec.md`
312
305
  - `token-system.spec.md`
313
306
  - `uiSize.spec.md`
@@ -14,27 +14,29 @@ benchmark:
14
14
 
15
15
  <!-- @benchmark-cited: D5 retrofit 2026-05-18 — body claims marked per-claim @benchmark-unverified inline; canonical source URLs in frontmatter benchmark list. -->
16
16
 
17
- # Motion tokens — hover delay 設計原則
17
+ # Motion 設計原則
18
18
 
19
19
  > **Foundational SSOT rationale**(2026-05-18 ship per user 拍板 #3A):跨 5+ overlay 消費者
20
20
  > (Tooltip / HoverCard / ProfileCard / Avatar / OverflowIndicator)的 hover 開啟 / 關閉延遲統一。
21
21
 
22
22
  ## 定位
23
23
 
24
- Hover delay token 是「hover 觸發 → overlay 顯示」之間的等待時間。**目的不是動畫長度,是「user 真的想看」過濾器** — 短暫滑過不該觸發 expensive overlay(ProfileCard fetch 資料 / Tooltip 視覺擾動)。
24
+ Hover delay token 是「hover 觸發 → 延遲 N ms → overlay 顯示」的延遲時間(對齊 token 名 `delay` 術語)。**目的不是動畫長度,是「user 真的想看」過濾器** — 短暫滑過不該觸發 expensive overlay(ProfileCard fetch 資料 / Tooltip 視覺擾動)。
25
+
26
+ **Scope 邊界**:本 token 系統僅管 hover open / close 延遲;overlay 開啟後的 fetch loading 視覺(skeleton / 留空)屬各 consumer 元件 spec(HoverCard / ProfileCard),不在 motion token scope。
25
27
 
26
28
  ## 三層 tier 系統
27
29
 
28
30
  | Token | 值 | 用於 | 為何 |
29
31
  |---|---|---|---|
30
- | `--hover-delay-plain` | `500ms` | Tooltip 純文字提示 | 被動 hint,需 user「真停留」才觸發,避免滑過列表時 N 次視覺擾動。對齊 Material 3 plain tooltip 500ms / Apple HIG ~500ms / shadcn-Radix default 500ms 主流共識 |
32
+ | `--hover-delay-plain` | `500ms` | Tooltip 純文字提示 | 被動 hint,需 user「真停留」才觸發,避免滑過列表時 N 次視覺擾動。對齊 Material 3 plain tooltip 500ms / Apple HIG ~500ms / shadcn-Radix default 500ms 主流共識 | <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
31
33
  | `--hover-delay-rich` | `700ms` | HoverCard / ProfileCard 內容預覽 | 含 avatar / fields / actions 的 rich content(可能含 fetch)。User 必須「真的想看」才停留 700ms,避免列表掃視時誤觸發 N 個 fetch waterfall |
32
34
  | `--hover-delay-close` | `200ms` | 所有 overlay 關閉 | Mouse leave 後給 200ms 緩衝(user 可能誤滑出再回來)。對齊 UX 共識「close delay ≤ open delay」+ 既有 Avatar `closeDelay={200}` 值 |
33
35
 
34
36
  ## 為何不用單一值 / 為何不沿用過去 200ms
35
37
 
36
38
  - **過去 200/300ms 偏快**(2026-05-18 ship,2026-05-20 user 抓「太快很容易干擾人」撤回):200ms plain 滑過列表 N 次觸發 Tooltip 視覺擾動;300ms rich 在含 fetch 的 HoverCard 場景列表掃視會打 N 次 server request waterfall。
37
- - **MUI/Ant 100ms 是 fast-tier 例外**:適合 form input help text 等「我就是要快」的 dense 場景,不適合通用 chrome tooltip。
39
+ - **MUI/Ant 100ms 是 fast-tier 例外**:適合 form input help text 等「我就是要快」的 dense 場景,不適合通用 chrome tooltip。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
38
40
  - **單一值** 失去 plain / rich 語意區分:ProfileCard 含 fetch + image + actions 應比 Tooltip(純文字)delay 長,單一值會讓 ProfileCard 滑過列表時整列誤觸發 fetch waterfall。
39
41
  - **過短**(< 100ms):每滑必觸發 → 視覺擾動 + 不必要 server request。
40
42
  - **過長**(> 1s):user 已不期待 overlay,等出來變干擾。
@@ -66,8 +68,8 @@ Hover delay token 是「hover 觸發 → overlay 顯示」之間的等待時間
66
68
 
67
69
  ## 消費者
68
70
 
69
- - `components/Avatar/avatar.tsx:299` — HoverCard openDelay / closeDelay(原硬寫 300/200,migrate 到 token)
70
- - `components/HoverCard/hover-card.tsx` — Radix Provider 預設 delayDuration override 為 `--hover-delay-rich`
71
+ - `components/Avatar/avatar.tsx` — HoverCard openDelay / closeDelay 消費 `HOVER_DELAY_RICH_MS` / `HOVER_DELAY_CLOSE_MS`(原硬寫 300/200,migrate 到 token)
72
+ - `components/HoverCard/hover-card.tsx` — Root 預設 `openDelay`=`--hover-delay-rich` / `closeDelay`=`--hover-delay-close`(Radix HoverCard 無 Provider;2026-06-11 落地,原宣稱與 code 脫鉤)
71
73
  - `components/Tooltip/tooltip.tsx` — Radix Provider 預設 delayDuration override 為 `--hover-delay-plain`
72
74
  - `components/ProfileCard/profile-card.tsx`(consumer of HoverCard)— 繼承 `--hover-delay-rich`
73
75
  - `components/OverflowIndicator/overflow-indicator.tsx`(consumer)— 用 `--hover-delay-plain`
@@ -86,7 +88,7 @@ Hover delay token 是「hover 觸發 → overlay 顯示」之間的等待時間
86
88
  | MUI / Ant Tooltip | 100ms(dense form input fast-tier) | — |
87
89
  | **DS canonical(本 spec)** | **500ms** | **700ms** |
88
90
 
89
- 500ms 對齊 Material 3 / Apple HIG / shadcn 主流共識(三家集中在 500ms),避 MUI/Ant 100ms(form input fast-tier 不適通用 chrome)+ Radix 700(過保守)兩極端。Rich 700ms 比 plain 多 200ms 反映 fetch / multi-section content「真的想看」門檻。
91
+ 500ms 對齊 Material 3 / Apple HIG / shadcn 主流共識(三家集中在 500ms),避 MUI/Ant 100ms(form input fast-tier 不適通用 chrome)+ Radix 700(過保守)兩極端。Rich 700ms 比 plain 多 200ms 反映 fetch / multi-section content「真的想看」門檻。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
90
92
 
91
93
  ## 相關
92
94
 
@@ -95,3 +97,9 @@ Hover delay token 是「hover 觸發 → overlay 顯示」之間的等待時間
95
97
  - `../../components/Tooltip/tooltip.spec.md`(consumer)
96
98
  - `../../components/HoverCard/hover-card.spec.md`(consumer)
97
99
  - `../../components/Avatar/avatar.spec.md`(consumer)
100
+
101
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
102
+
103
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
104
+
105
+ - `hover-card.spec.md`
@@ -17,22 +17,24 @@ Opacity 定義元件停用狀態的透明度,確保全系統 disabled 視覺
17
17
  停用狀態有兩種視覺策略(詳見 `color.spec.md`「Disabled 狀態」節 / 「兩種 disabled 策略」):
18
18
 
19
19
  - **Token swap**(預設):disabled 時換成專用 token(`fg-disabled`、`bg-disabled`),精確控制每個層的顏色。適用於多層結構的元件(Button、Input)。
20
- - **Opacity blanket**:對整個元件套 `opacity-disabled`,一次處理所有子元素。適用於結構簡單、子元素多的元件(Avatar、Switch thumb、Slider)。
20
+ - **Opacity blanket**:對整個元件套 `opacity-disabled`,一次處理所有子元素。適用於結構簡單、子元素多的元件(Avatar、Switch thumb、Rating)。Slider 屬灰階 token-swap 派,**不**用 opacity(`slider.spec.md`「Disabled 策略」反覆確認後的結論)。
21
21
 
22
22
  不可混用——同一元件要嘛用 token swap,要嘛用 opacity,不兩者同時。
23
23
 
24
+ **Scope**:opacity 只負責 disabled 一個 role——error / warning 等 state 走 semantic color token 變色(`border-error` 等)、hover / active 走 `-hover` / `-active` token,皆無透明度變化(role 隔離,詳「設計哲學」(2);全 DS production code 無 error-state opacity 用例)。**已 codify 的 reuse 例外**(reuse 同一 token,非新增 opacity role):DataTable 整表 refresh loading(`data-table.spec.md`「狀態處理職責邊界」)與 drag source 半透(同 spec「Drag visual SSOT」+ `lib/drag-visual.ts`)。
25
+
24
26
  ## 為什麼 0.45
25
27
 
26
- 0.45 在 light mode 和 dark mode 都能對 disabled 元件產生足夠辨識度(明顯區分於 active state),同時保持文字可讀(WCAG 不要求 disabled 元素的對比度,但仍需辨識)。
28
+ 0.45 在 light mode 和 dark mode 都能對 disabled 元件產生足夠辨識度(明顯區分於 active state)。「辨識」與「閱讀」是兩個不同要求:WCAG 2.1 SC 1.4.3 明文豁免 inactive UI component 的文字對比(無法定「可讀對比」門檻);但 UX 上使用者仍須**辨識**出「這裡有一個控件、且目前停用」——0.45 服務的是辨識,不是閱讀。
27
29
 
28
- 選 0.45 的位置:
30
+ 選 0.45 的位置: <!-- @benchmark-unverified -->
29
31
 
30
32
  - 比 **Material 0.38** 略亮(Material 在白底 dark text 0.38 太弱,DS 使用 lg / dark mode 共用一個值需折衷)
31
33
  - 比 **Apple iOS 0.4 / Atlassian 0.4** 稍亮(iOS 是 mobile-first 對比偏強,DS desktop 場景文字密集需更可辨識)
32
34
  - 比 **Polaris 0.5 / Tailwind 0.5** 稍暗(0.5 對 disabled 元件辨識度不足,容易誤判為 hover state)
33
35
  - **0.45 是 0.4-0.5 區間中位數**,跨 light / dark mode 都 robust
34
36
 
35
- 世界級對照(2026-05-01 加):
37
+ 世界級對照(2026-05-01 加): <!-- @benchmark-unverified -->
36
38
 
37
39
  | DS | Material 3 | Carbon | Tailwind v4 | Ant Design | Polaris | Apple HIG | Atlassian |
38
40
  |----|-----------|--------|-------------|------------|---------|-----------|-----------|
@@ -44,41 +46,28 @@ Opacity 定義元件停用狀態的透明度,確保全系統 disabled 視覺
44
46
 
45
47
  兩個關鍵決策,各自有世界級先例支撐:
46
48
 
47
- **(1) 雙策略並存(token swap 為主 + opacity blanket 為輔)— 對齊 Carbon / Atlassian 折衷哲學**
49
+ **(1) 雙策略並存(token swap 為主 + opacity blanket 為輔)— 對齊 Carbon / Atlassian 折衷哲學** <!-- @benchmark-unverified -->
48
50
 
49
51
  純 token swap(Material / Ant / Polaris):每元件每層 disabled 自己一個 token,精確但 token 數激增(Material 有 50+ disabled token);純 opacity blanket(早期 Bootstrap):一律 0.5 簡單但無法表達 multi-layer hierarchy(disabled Button 的 icon / label / border 三層該有不同程度 fade)。
50
52
 
51
53
  本 DS 採 Carbon-aligned 折衷:**多層結構元件用 token swap**(Button 有 fg / bg / border 各自 disabled token);**簡單元件用 opacity blanket**(Avatar / Switch thumb 一個視覺單位,opacity 0.45 一次處理所有子元素)。明文「不可混用」避免 disabled overlay 重疊產生「過度褪色」(0.45 × 0.45 = 0.2 不可讀)。
52
54
 
53
- **(2) Single tier 0.45 而非 Tailwind multi-tier opacity scale — 對齊 Polaris / Apple 單值哲學**
55
+ **(2) Single tier 0.45 而非 Tailwind multi-tier opacity scale — 對齊 Polaris / Apple 單值哲學** <!-- @benchmark-unverified -->
54
56
 
55
57
  Tailwind 提供 `opacity-{5/10/20/30/40/50/60/70/80/90/95}` 百分比 ladder,但這是 utility scale 非 semantic role — 每個 consumer 自己挑值,跨元件不一致(A 用 opacity-50 / B 用 opacity-40 都 disabled)。
56
58
 
57
59
  本 DS 為 disabled 場景 single semantic token(`opacity-disabled = 0.45`),所有 disabled 用同一值 — 對齊 Polaris `opacity-disabled` / Material `disabled-on-surface` / Apple `UIDisabled` 「single semantic value for one role」哲學。捨棄 Tailwind multi-tier 的代價是「無法表達多層 hover/active fade」,但 hover / active 走 hover-bg / pressed-bg token,opacity 只負責 disabled,role 隔離。
58
60
 
59
- ## 消費者
60
-
61
- Avatar、Sidebar、MenuItem、Slider、Switch、Steps、Chip。
62
-
63
- ## 反向引用
64
-
65
- - Disabled 策略選擇框架:`tokens/color/color.spec.md`
61
+ ## A11y(disabled 訊號不只透明度)
66
62
 
67
- ## 被引用(auto-maintained,Dim 3 reciprocal audit)
63
+ 透明度是視覺輔助,不是 disabled 的唯一訊號:語意由 native `disabled` / `aria-disabled` attribute 傳達給輔助技術(SR 朗讀 unavailable,非依賴視覺),並伴隨互動阻斷(無法觸發 / `cursor-not-allowed`)提供非色彩線索——色弱使用者不依賴 0.45 fade 也能辨識停用狀態。
68
64
 
69
- > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
65
+ ## 消費者
70
66
 
71
- - `avatar.spec.md`
72
- - `chip.spec.md`
73
- - `color.spec.md`
74
- - `menu-item.spec.md`
75
- - `sidebar.spec.md`
76
- - `slider.spec.md`
77
- - `steps.spec.md`
78
- - `switch.spec.md`
67
+ 直接套用 `opacity-disabled` 的元件(grep 驗證 2026-06-11):Avatar(Field disabled context self-dim)、Button(`aria-disabled` 分支)、MenuItem、Rating(disabled / loading 整塊)、Steps、Switch、Textarea(disabled 分支)、DataTable(drag source 半透 + 整表 refresh loading reuse,經 `lib/drag-visual.ts`)。
79
68
 
80
- ## 被引用(auto-maintained,Dim 3 reciprocal audit)
69
+ 非消費者(曾誤列):Slider / Sidebar 走灰階 token swap;Chip 無 opacity 用例;Field wrapper blanket 已移除(Avatar self-dim 取代,見 field-wrapper.tsx 註解)。
81
70
 
82
- > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
71
+ ## 反向引用
83
72
 
84
- - `token-system.spec.md`
73
+ - Disabled 策略選擇框架:`tokens/color/color.spec.md`
@@ -10,10 +10,15 @@ benchmark:
10
10
  - Polaris Design Tokens — semantic SOP 5-piece set canonical https://polaris.shopify.com/design/colors
11
11
  ---
12
12
 
13
- # Orphan Token 分類 SSOT(retire vs structural-keep)
13
+ # Orphan Token 分類設計原則(retire vs structural-keep SSOT)
14
14
 
15
15
  > **Foundational context**(2026-05-21 codify per user verbatim「決策四你他媽仔細給我確認到底該retire的是否真的該retire還是應該結構性保留,請全盤檢查,然後確認之後請下次不要再煩我,尤其是Palette tier」+「都給我做到好」):**永久解決**「audit 每次抓 X 個 orphan tokens」噪音。本 spec 明文哪些 token 結構性保留 + 自動 audit script 識別,user 不需重複確認同一題。
16
16
 
17
+ ## Scope(何時用 / 何時不用)
18
+
19
+ - **用**:DS 作者稽核 token bloat(retire vs structural-keep 判定)— `audit-orphan-tokens.mjs` + design-system-audit Dim 48 消費本分類,屬 DS-internal audit SSOT
20
+ - **不用**:consumer 選 token 的使用指南 — 那是 `tokens/README.md` + 各 token spec 的職責
21
+
17
22
  ## 為什麼會出現「假孤兒」
18
23
 
19
24
  簡單的 `grep var(--X)` 抓不到以下消費路徑,造成 token **實際有用但 audit 報「無消費」false positive**:
@@ -79,7 +84,7 @@ benchmark:
79
84
 
80
85
  ### 7. SOP 5-piece semantic 完整集(1+ token,structural)
81
86
 
82
- **Rule**:每個 semantic role(primary / error / success / warning / info)必有 5 件套:`base / hover / active / subtle / text`,即使當前 `text` variant 無消費者也保留。
87
+ **Rule**:每個 semantic role(primary / error / success / warning / info)必有 5 件套:`base / hover / active / subtle / text`;機械保護集另含 `emphasis / foreground / focus`(下方 Regex 共 7 後綴,與 `audit-orphan-tokens.mjs` 一致;無後綴 base 由消費者直接引用不在 regex 內)。即使當前 variant 無消費者也保留。
83
88
 
84
89
  **Why**:Consistency invariant — 缺 `-text` variant 設計時找不到「on-emphasis 文字色」會 hot-create,違反 SSOT。Polaris「Status colors complete set」canonical。
85
90
 
@@ -104,9 +109,15 @@ benchmark:
104
109
  2. **Git blame** declare 提交 — 提交訊息 / PR 描述是否說明用途
105
110
  3. 兩 step 都無 → safe retire,從 `tokens/**/*.css` 刪宣告 + 加 git commit message cite 本 spec
106
111
 
112
+ ## 邊界案例
113
+
114
+ - **Audit 間 token 重獲消費者(0 → N)**:audit 為每次執行的即時 snapshot(無跨次狀態),token 重獲消費後自動退出 retire 候選;無 deprecation period 機制
115
+ - **新 structural-keep token**:不在 baseline → `--check` fail,需 `--update` 顯式 justify(防 regex 過寬 silent absorb;baseline 縮減不 fail)— baseline SSOT `scripts/audit-orphan-tokens.baseline.json`
116
+ - **Dark-mode token mirror 驗證**:非本 audit scope — script 只驗「消費存在性」,不驗 light / dark 配對完整性
117
+
107
118
  ## Audit chain
108
119
 
109
- - **Dim 48** (`design-system-audit/SKILL.md`)— chain 本 spec + `audit-orphan-tokens.mjs --check`(not raw `grep var()`)
120
+ - **Dim 48**(= `design-system-audit/SKILL.md` 的「Unused / orphan token detector」audit 維度)— chain 本 spec + `audit-orphan-tokens.mjs --check`(not raw `grep var()`)
110
121
  - **CI**:`npm run audit:tokens`(future add to `package.json` scripts)— `node scripts/audit-orphan-tokens.mjs --check` fail = real orphan 出現
111
122
  - **Hook**:無 hook(本 audit run-time / monthly cadence,非 PreToolUse 攔截場景)
112
123
 
@@ -27,7 +27,7 @@ CSS 定義了 `--radius-sm`(目前 = 4px,與 md 同值),但**不在元件中使
27
27
  - Chart legend swatch(8×8 色塊)
28
28
  - 未來其他 micro indicator(若尺寸 ≥ 12px 請改 `rounded-md`,不要為了「更圓」使用 xs)
29
29
 
30
- **判斷**:`rounded-md`(4px)在 8×8 元素上接近 50% 填滿,視覺變成 pill2px 才維持「色塊」而非「膠囊」語意。≥ 12px 4px 比例適當,不需 xs。
30
+ **判斷**(radius / 邊長比):4px 在 8×8 元素上 = 邊長 50%(radius 達半邊長即成 pill,類別色塊語意流失);2px = 25%,輪廓保持方形。≥ 12px 元素上 4px 33%,比例適當,不需 xs。
31
31
 
32
32
  ### `rounded-md`(4px)— 一般元件
33
33
 
@@ -57,7 +57,7 @@ CSS 定義了 `--radius-sm`(目前 = 4px,與 md 同值),但**不在元件中使
57
57
  ## 禁止事項
58
58
 
59
59
  ```tsx
60
- // ❌ 不要用非 token 的圓角(包含 rounded-md、rounded 等)
60
+ // ❌ 不要用非 token 的圓角(bare rounded、rounded-xl、rounded-2xl 等)
61
61
  <div className="rounded" /> // 4px,但意圖不明
62
62
  <div className="rounded-xl" /> // 12px,超出 token 範圍
63
63
  <div className="rounded-2xl" /> // 16px,超出 token 範圍
@@ -81,15 +81,19 @@ CSS 定義了 `--radius-sm`(目前 = 4px,與 md 同值),但**不在元件中使
81
81
  <span className="rounded-full" />
82
82
  ```
83
83
 
84
+ ### 省略 radius 的行為(空值驗證)
85
+
86
+ 不寫 `rounded-*` → `border-radius: 0`(CSS 預設直角),不 fallback 任何 token;無圓角需求的元素本就不寫,不強制每元素標 radius。**有意**的圓角必用上表 4 tier class——bare `rounded`(Tailwind 預設 4px,意圖不明)與硬寫值由上方禁止事項擋。
87
+
84
88
 
85
89
  ## 世界級對照
86
90
 
87
- 對齊 M8(binary strict rule 必 ≥3 家世界級對照),「禁 `rounded-xl` / `rounded-2xl` raw utility」+「禁硬寫 `rounded-[6px]`」是本 spec 的 binary strict rule,以下為支撐 rationale。
91
+ 對齊 M8(binary strict rule 必 ≥3 家世界級對照),「禁 `rounded-xl` / `rounded-2xl` raw utility」+「禁硬寫 `rounded-[6px]`」是本 spec 的 binary strict rule,以下為支撐 rationale。 <!-- @benchmark-unverified -->
88
92
 
89
93
  | 維度 | 本 DS | Material 3 | Carbon | Tailwind v4 | Ant Design | Polaris | shadcn/Apple |
90
94
  |------|-------|-----------|--------|-------------|------------|---------|--------------|
91
- | Tier 數 | **4 tier**(xs/md/lg/full)+ 1 reserved sm | 6 tier(extra-small ~ extra-large + full) | 3 tier(0/1/2) | 7 tier(none/sm/md/lg/xl/2xl/3xl/full)| **4 tier**(XS/SM/Default/LG)| 6 tier(050/100/200/300/400/500/full)| 1 base + calc(shadcn)/ Squircle 連續曲率(Apple)|
92
- | 數值序列 | **2 / 4 / 8 / 9999** geometric × 2 | 4 / 8 / 12 / 16 / 28 額外 | 0 / 2px / 4px(token rem)| 2 / 4 / 6 / 8 / 12 / 16 / 24 | 2 / 4 / 6 / 8 | 2 / 4 / 6 / 8 / 12 / 16 | `--radius` × calc 變化 |
95
+ | Tier 數 | **4 tier**(xs/md/lg/full)+ 1 reserved sm | 6 tier(extra-small ~ extra-large + full) | 3 tier(0/1/2) | 8 tier(xs/sm/md/lg/xl/2xl/3xl/4xl)+ none/full | **4 tier**(XS/SM/Default/LG)| 6 tier(050/100/200/300/400/500/full)| 1 base + calc(shadcn)/ Squircle 連續曲率(Apple)|
96
+ | 數值序列 | **2 / 4 / 8 / 9999** geometric × 2 | 4 / 8 / 12 / 16 / 28 額外 | 0 / 2px / 4px(token rem)| 2 / 4 / 6 / 8 / 12 / 16 / 24 / 32 | 2 / 4 / 6 / 8 | 2 / 4 / 6 / 8 / 12 / 16 | `--radius` × calc 變化 |
93
97
  | Pill 方案 | `rounded-full` 9999px | `shape-corner-full` | 不顯式提供 | `rounded-full` 9999px | `borderRadiusOuter` ad-hoc | `border-radius-full` | 視 component shape |
94
98
  | 動態 shape | 無(靜態 4 tier)| Dynamic shape morphing(可動畫) | 無 | 無 | 無 | 無 | Apple 連續曲率動態 |
95
99
 
@@ -97,32 +101,26 @@ CSS 定義了 `--radius-sm`(目前 = 4px,與 md 同值),但**不在元件中使
97
101
 
98
102
  四個關鍵決策,各自有世界級先例支撐:
99
103
 
100
- **(1) 4 tier(xs/md/lg/full)— 對齊 Ant Design 4-tier minimal,捨多家 6+ tier**
104
+ **(1) 4 tier(xs/md/lg/full)— 對齊 Ant Design 4-tier minimal,捨多家 6+ tier** <!-- @benchmark-unverified -->
101
105
 
102
106
  Material 3 / Polaris / Tailwind 6-7 tier 過細 — 每 tier 只差 2-4px,reader 視覺難分(「rounded-md 6px」vs「rounded-lg 8px」差 25% 但目視幾乎相同)。Carbon 3 tier(0/1/2)太極簡無法表達 elevation 層級(浮層 vs inline 同 radius 失去視覺 hierarchy)。
103
107
 
104
108
  本 DS 4 tier 是「視覺可區分 + 維護友善」最佳交集 — `xs(2)→ md(4)→ lg(8)→ full` 每跳一級數值翻倍,目視差異 ≥ 50%(Weber-Fechner law 知覺閾值),不會出現「rounded-md vs rounded-mdlg 哪個對」糾結。
105
109
 
106
- **(2) Geometric scale(2 / 4 / 8 doubling)— 對齊 Tailwind / Polaris 慣例**
110
+ **(2) Geometric scale(2 / 4 / 8 doubling)— 對齊 Tailwind / Polaris 慣例** <!-- @benchmark-unverified -->
107
111
 
108
112
  數值 doubling 確保 reader 一眼感知「不同層級」(2→4→8 比 4→6→8 對比明顯)。對齊 Tailwind sm(2)/ md(4)/ lg(8) + Polaris 100(4)/ 200(6 — 偏離)/ 300(8) 的 powers-of-2 idiom。
109
113
 
110
114
  捨棄連續 ratio(Material 4/8/12/16/28 等差 + 跳級)的代價是「中段 size 表現空間」(無 6px tier),DS 場景無此需求(中段需求都歸入 md=4)。
111
115
 
112
- **(3) `rounded-full` 9999px 而非 50%(對齊 Tailwind / Polaris)**
116
+ **(3) `rounded-full` 9999px 而非 50%(對齊 Tailwind / Polaris)** <!-- @benchmark-unverified -->
113
117
 
114
118
  50% percentage 在「短矩形」(高 < 寬,如 horizontal Switch)變橢圓而非 pill — 9999px 確保任意 aspect ratio 都圓形(實際 capped 在 height/2)。對齊 Tailwind / Polaris 全 pill 慣例,避免短矩形 edge case。
115
119
 
116
- **(4) 保留 `--radius-sm` token 但不用 — 對齊 Material「reserve for future dense pattern」**
120
+ **(4) 保留 `--radius-sm` token 但不用 — 對齊 Material「reserve for future dense pattern」** <!-- @benchmark-unverified -->
117
121
 
118
122
  CSS 定義 `--radius-sm = 4px`(目前同 md),component 強制 `rounded-md` 不引用 sm。為什麼留:未來若引入 dense mode(`density="compact"` 介於 md / xs 之間),可開新 sm tier 不破壞既有 xs/md/lg/full 命名階梯(避免 rename 引發全 DS grep refactor)。對齊 Material 3 的「extra-small reserved tier」哲學。
119
123
 
120
124
  捨棄「立即啟用 sm」的代價是命名空間預占,接受 — 命名穩定 > 短期 utility。
121
125
 
122
126
  捨棄「Apple Continuous Corner / Squircle」的代價是「平台一致性」(Apple HIG 用連續曲率非單一 radius,iOS 元件視覺更柔)— DS 是 cross-platform web,採 Material/Tailwind 標準 border-radius 對齊大多數 OS native 元件,避免引入 SVG path 額外 runtime 成本。
123
-
124
- ## 被引用(auto-maintained,Dim 3 reciprocal audit)
125
-
126
- > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
127
-
128
- - `token-system.spec.md`
@@ -228,16 +228,13 @@ Tailwind v4 `@theme inline` 把 CSS variable 升級成 utility class。每 famil
228
228
 
229
229
  ---
230
230
 
231
- ## 被引用(auto-maintained,Dim 3 reciprocal audit)
232
-
233
- > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護。
234
-
235
- - `tokens/README.md`(Public vs Internal token cross-reference)
236
- - `color/color.spec.md`(L1/L2 上游 SSOT)
237
- - `uiSize/uiSize.spec.md`(L3 Family + L4 Layout 上游 SSOT)
238
- - `layoutSpace/layoutSpace.spec.md`(L4 Layout 上游 SSOT)
239
- - `elevation/elevation.spec.md`(L1 co-location rationale)
240
- - `opacity/opacity.spec.md`(L1 classification)
241
- - `radius/radius.spec.md`(L3 Family classification)
242
- - `typography/typography.spec.md`(L3 Family classification)
243
- - `.claude/rules/ui-development.md`「Token 命名 4 條硬規則」(下游 lint-style summary)
231
+ ## 相關
232
+
233
+ - `README.md`(tokens charter)— 檔案路徑 + Public vs Internal token 表
234
+ - `color/color.spec.md` — L1/L2 色彩 family 具體規則(含 Tag / Avatar 直接消費 L1 的流派定位)
235
+ - `uiSize/uiSize.spec.md` L3 Family / L4 Layout 尺寸 token
236
+ - `typography/typography.spec.md` `--font-*` family
237
+ - `elevation/elevation.spec.md` `--elevation-*`(住 `color/primitives.css`,理由見「跨 family co-location 規則」)
238
+ - `layoutSpace/layoutSpace.spec.md` `--layout-space-*` 抽象 spacing rhythm
239
+
240
+ ---