@qijenchen/design-system 0.1.0-beta.81 → 0.1.0-beta.83

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 (333) hide show
  1. package/CLAUDE.md +2 -3
  2. package/dist/components/Avatar/avatar.d.ts.map +1 -1
  3. package/dist/components/Avatar/avatar.js +1 -2
  4. package/dist/components/Avatar/avatar.js.map +1 -1
  5. package/dist/components/BulkActionBar/bulk-action-bar.d.ts +3 -0
  6. package/dist/components/BulkActionBar/bulk-action-bar.d.ts.map +1 -1
  7. package/dist/components/BulkActionBar/bulk-action-bar.js +2 -2
  8. package/dist/components/BulkActionBar/bulk-action-bar.js.map +1 -1
  9. package/dist/components/Button/button.d.ts +1 -1
  10. package/dist/components/Button/button.d.ts.map +1 -1
  11. package/dist/components/Button/button.js +5 -2
  12. package/dist/components/Button/button.js.map +1 -1
  13. package/dist/components/Calendar/calendar.d.ts +3 -1
  14. package/dist/components/Calendar/calendar.d.ts.map +1 -1
  15. package/dist/components/Calendar/calendar.js +40 -17
  16. package/dist/components/Calendar/calendar.js.map +1 -1
  17. package/dist/components/Carousel/carousel.d.ts +1 -1
  18. package/dist/components/Carousel/carousel.d.ts.map +1 -1
  19. package/dist/components/Carousel/carousel.js +3 -1
  20. package/dist/components/Carousel/carousel.js.map +1 -1
  21. package/dist/components/Checkbox/checkbox.d.ts +1 -1
  22. package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
  23. package/dist/components/Checkbox/checkbox.js +2 -1
  24. package/dist/components/Checkbox/checkbox.js.map +1 -1
  25. package/dist/components/Chip/chip.d.ts +2 -2
  26. package/dist/components/Chip/chip.d.ts.map +1 -1
  27. package/dist/components/Chip/chip.js +41 -12
  28. package/dist/components/Chip/chip.js.map +1 -1
  29. package/dist/components/Coachmark/coachmark.d.ts.map +1 -1
  30. package/dist/components/Coachmark/coachmark.js +6 -6
  31. package/dist/components/Coachmark/coachmark.js.map +1 -1
  32. package/dist/components/Combobox/combobox.d.ts +1 -1
  33. package/dist/components/Combobox/combobox.d.ts.map +1 -1
  34. package/dist/components/Combobox/combobox.js +5 -2
  35. package/dist/components/Combobox/combobox.js.map +1 -1
  36. package/dist/components/Command/command.d.ts +1 -1
  37. package/dist/components/Command/command.d.ts.map +1 -1
  38. package/dist/components/Command/command.js +2 -1
  39. package/dist/components/Command/command.js.map +1 -1
  40. package/dist/components/DataTable/data-table.d.ts +29 -1
  41. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  42. package/dist/components/DataTable/data-table.js +71 -13
  43. package/dist/components/DataTable/data-table.js.map +1 -1
  44. package/dist/components/DataTable/filter-tree.d.ts.map +1 -1
  45. package/dist/components/DateGrid/date-grid.d.ts +2 -2
  46. package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
  47. package/dist/components/DateGrid/date-grid.js +54 -10
  48. package/dist/components/DateGrid/date-grid.js.map +1 -1
  49. package/dist/components/DatePicker/date-picker.d.ts +2 -8
  50. package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
  51. package/dist/components/DatePicker/date-picker.js +15 -3
  52. package/dist/components/DatePicker/date-picker.js.map +1 -1
  53. package/dist/components/DescriptionList/description-list.d.ts.map +1 -1
  54. package/dist/components/DescriptionList/description-list.js +1 -1
  55. package/dist/components/DescriptionList/description-list.js.map +1 -1
  56. package/dist/components/DropdownMenu/dropdown-menu.d.ts +3 -3
  57. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  58. package/dist/components/DropdownMenu/dropdown-menu.js +14 -4
  59. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  60. package/dist/components/Empty/empty.d.ts.map +1 -1
  61. package/dist/components/Empty/empty.js +1 -1
  62. package/dist/components/Empty/empty.js.map +1 -1
  63. package/dist/components/Field/field.d.ts +1 -1
  64. package/dist/components/Field/field.d.ts.map +1 -1
  65. package/dist/components/Field/field.js +2 -1
  66. package/dist/components/Field/field.js.map +1 -1
  67. package/dist/components/Field/use-form-validation.d.ts.map +1 -1
  68. package/dist/components/Field/use-form-validation.js +5 -7
  69. package/dist/components/Field/use-form-validation.js.map +1 -1
  70. package/dist/components/FileUpload/file-upload.d.ts +1 -1
  71. package/dist/components/FileUpload/file-upload.d.ts.map +1 -1
  72. package/dist/components/FileUpload/file-upload.js +11 -5
  73. package/dist/components/FileUpload/file-upload.js.map +1 -1
  74. package/dist/components/FileViewer/can-render-image.d.ts +6 -0
  75. package/dist/components/FileViewer/can-render-image.d.ts.map +1 -0
  76. package/dist/components/FileViewer/can-render-image.js +11 -0
  77. package/dist/components/FileViewer/can-render-image.js.map +1 -0
  78. package/dist/components/FileViewer/file-viewer.d.ts +2 -2
  79. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  80. package/dist/components/FileViewer/file-viewer.js +20 -13
  81. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  82. package/dist/components/FileViewer/image-renderer.d.ts +0 -5
  83. package/dist/components/FileViewer/image-renderer.d.ts.map +1 -1
  84. package/dist/components/FileViewer/image-renderer.js +1 -9
  85. package/dist/components/FileViewer/image-renderer.js.map +1 -1
  86. package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
  87. package/dist/components/HoverCard/hover-card.js +3 -1
  88. package/dist/components/HoverCard/hover-card.js.map +1 -1
  89. package/dist/components/Input/input.d.ts +26 -3
  90. package/dist/components/Input/input.d.ts.map +1 -1
  91. package/dist/components/Input/input.js +11 -3
  92. package/dist/components/Input/input.js.map +1 -1
  93. package/dist/components/LinkInput/link-input.d.ts +1 -1
  94. package/dist/components/LinkInput/link-input.d.ts.map +1 -1
  95. package/dist/components/LinkInput/link-input.js.map +1 -1
  96. package/dist/components/Menu/menu-item.d.ts.map +1 -1
  97. package/dist/components/Menu/menu-item.js +4 -3
  98. package/dist/components/Menu/menu-item.js.map +1 -1
  99. package/dist/components/NumberInput/number-input.d.ts +1 -1
  100. package/dist/components/NumberInput/number-input.d.ts.map +1 -1
  101. package/dist/components/NumberInput/number-input.js +2 -1
  102. package/dist/components/NumberInput/number-input.js.map +1 -1
  103. package/dist/components/Pagination/index.d.ts +2 -0
  104. package/dist/components/Pagination/index.d.ts.map +1 -0
  105. package/dist/components/Pagination/index.js +6 -0
  106. package/dist/components/Pagination/index.js.map +1 -0
  107. package/dist/components/Pagination/pagination.d.ts +49 -0
  108. package/dist/components/Pagination/pagination.d.ts.map +1 -0
  109. package/dist/components/Pagination/pagination.js +182 -0
  110. package/dist/components/Pagination/pagination.js.map +1 -0
  111. package/dist/components/PeoplePicker/people-picker.d.ts +1 -1
  112. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  113. package/dist/components/PeoplePicker/people-picker.js +2 -1
  114. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  115. package/dist/components/PeoplePicker/person-display.d.ts +4 -0
  116. package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
  117. package/dist/components/PeoplePicker/person-display.js +1 -1
  118. package/dist/components/PeoplePicker/person-display.js.map +1 -1
  119. package/dist/components/Popover/popover.d.ts.map +1 -1
  120. package/dist/components/Popover/popover.js +58 -32
  121. package/dist/components/Popover/popover.js.map +1 -1
  122. package/dist/components/ProfileCard/profile-card.d.ts +6 -1
  123. package/dist/components/ProfileCard/profile-card.d.ts.map +1 -1
  124. package/dist/components/ProfileCard/profile-card.js +14 -4
  125. package/dist/components/ProfileCard/profile-card.js.map +1 -1
  126. package/dist/components/RadioGroup/radio-group.d.ts +1 -1
  127. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  128. package/dist/components/RadioGroup/radio-group.js +2 -1
  129. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  130. package/dist/components/SegmentedControl/segmented-control.d.ts +2 -2
  131. package/dist/components/SegmentedControl/segmented-control.d.ts.map +1 -1
  132. package/dist/components/SegmentedControl/segmented-control.js +16 -8
  133. package/dist/components/SegmentedControl/segmented-control.js.map +1 -1
  134. package/dist/components/Select/select.d.ts +1 -1
  135. package/dist/components/Select/select.d.ts.map +1 -1
  136. package/dist/components/Select/select.js +13 -2
  137. package/dist/components/Select/select.js.map +1 -1
  138. package/dist/components/SelectMenu/index.js +3 -2
  139. package/dist/components/SelectMenu/select-menu.d.ts +15 -3
  140. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  141. package/dist/components/SelectMenu/select-menu.js +150 -99
  142. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  143. package/dist/components/Sheet/sheet.d.ts.map +1 -1
  144. package/dist/components/Sheet/sheet.js +1 -1
  145. package/dist/components/Sheet/sheet.js.map +1 -1
  146. package/dist/components/Sidebar/sidebar.d.ts +2 -2
  147. package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
  148. package/dist/components/Sidebar/sidebar.js +5 -2
  149. package/dist/components/Sidebar/sidebar.js.map +1 -1
  150. package/dist/components/Slider/slider.d.ts +1 -1
  151. package/dist/components/Slider/slider.d.ts.map +1 -1
  152. package/dist/components/Slider/slider.js +7 -3
  153. package/dist/components/Slider/slider.js.map +1 -1
  154. package/dist/components/Switch/switch.d.ts +1 -1
  155. package/dist/components/Switch/switch.d.ts.map +1 -1
  156. package/dist/components/Switch/switch.js +10 -2
  157. package/dist/components/Switch/switch.js.map +1 -1
  158. package/dist/components/Tabs/tabs.d.ts +3 -3
  159. package/dist/components/Tabs/tabs.d.ts.map +1 -1
  160. package/dist/components/Tabs/tabs.js +29 -9
  161. package/dist/components/Tabs/tabs.js.map +1 -1
  162. package/dist/components/Tag/tag.d.ts.map +1 -1
  163. package/dist/components/Tag/tag.js +13 -1
  164. package/dist/components/Tag/tag.js.map +1 -1
  165. package/dist/components/Textarea/textarea.d.ts.map +1 -1
  166. package/dist/components/Textarea/textarea.js +4 -1
  167. package/dist/components/Textarea/textarea.js.map +1 -1
  168. package/dist/components/TimePicker/time-picker.d.ts +1 -1
  169. package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
  170. package/dist/components/TimePicker/time-picker.js +20 -7
  171. package/dist/components/TimePicker/time-picker.js.map +1 -1
  172. package/dist/components/Toast/toast.d.ts.map +1 -1
  173. package/dist/components/Toast/toast.js +4 -1
  174. package/dist/components/Toast/toast.js.map +1 -1
  175. package/dist/components/TreeView/tree-view.d.ts +1 -1
  176. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  177. package/dist/components/TreeView/tree-view.js +8 -3
  178. package/dist/components/TreeView/tree-view.js.map +1 -1
  179. package/dist/hooks/use-controllable.d.ts.map +1 -1
  180. package/dist/hooks/use-controllable.js +4 -2
  181. package/dist/hooks/use-controllable.js.map +1 -1
  182. package/dist/hooks/use-is-touch-device.d.ts.map +1 -1
  183. package/dist/hooks/use-is-touch-device.js +3 -1
  184. package/dist/hooks/use-is-touch-device.js.map +1 -1
  185. package/dist/index.d.ts +1 -0
  186. package/dist/index.d.ts.map +1 -1
  187. package/dist/index.js +3 -0
  188. package/dist/index.js.map +1 -1
  189. package/dist/patterns/element-anatomy/item-anatomy.d.ts +1 -1
  190. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
  191. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  192. package/ds-canonical/fork/governance.lock +14 -8
  193. package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +15 -4
  194. package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +8 -0
  195. package/ds-canonical/fork/hooks/check_story_determinism.sh +37 -0
  196. package/ds-canonical/fork/manifest.json +5 -0
  197. package/ds-canonical/fork/preamble.md +3 -1
  198. package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +6 -0
  199. package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +7 -0
  200. package/ds-canonical/fork/skills/performance-audit/SKILL.md +4 -2
  201. package/ds-canonical/fork/skills/visual-audit/SKILL.md +8 -0
  202. package/ds-canonical/hooks/check_benchmark_citation.sh +5 -3
  203. package/ds-canonical/hooks/check_ds_anchor_preflight.sh +15 -4
  204. package/ds-canonical/hooks/check_opacity_token_usage.sh +8 -0
  205. package/ds-canonical/hooks/check_propose_without_benchmark.sh +6 -2
  206. package/ds-canonical/hooks/check_ssot_header_declaration.sh +53 -0
  207. package/ds-canonical/hooks/check_story_determinism.sh +37 -0
  208. package/ds-canonical/hooks/tests/test_check_benchmark_citation.sh +3 -3
  209. package/ds-canonical/hooks/tests/test_check_fork_user_plugin_install.sh +3 -1
  210. package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +2 -2
  211. package/ds-canonical/hooks/tests/test_check_ssot_header_declaration.sh +72 -0
  212. package/ds-canonical/rules/self-verify.md +1 -1
  213. package/ds-canonical/rules/spec-rules.md +1 -1
  214. package/ds-canonical/rules/ui-development.md +2 -0
  215. package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +6 -0
  216. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +11 -15
  217. package/ds-canonical/skills/delivery-handoff/SKILL.md +5 -0
  218. package/ds-canonical/skills/design-system-audit/SKILL.md +1 -1
  219. package/ds-canonical/skills/governance-health/SKILL.md +1 -0
  220. package/ds-canonical/skills/new-component/SKILL.md +2 -0
  221. package/ds-canonical/skills/performance-audit/SKILL.md +2 -2
  222. package/ds-canonical/skills/visual-audit/SKILL.md +8 -0
  223. package/ds-story-manifest.json +27 -4
  224. package/llms-full.txt +6 -1
  225. package/llms.txt +2 -1
  226. package/package.json +1 -1
  227. package/src/components/Avatar/avatar.spec.md +10 -30
  228. package/src/components/Avatar/avatar.tsx +13 -7
  229. package/src/components/Badge/badge.spec.md +1 -0
  230. package/src/components/Breadcrumb/breadcrumb.spec.md +1 -1
  231. package/src/components/BulkActionBar/bulk-action-bar.anatomy.stories.tsx +1 -1
  232. package/src/components/BulkActionBar/bulk-action-bar.tsx +8 -2
  233. package/src/components/Button/button.spec.md +1 -0
  234. package/src/components/Button/button.tsx +4 -1
  235. package/src/components/Calendar/calendar.anatomy.stories.tsx +3 -1
  236. package/src/components/Calendar/calendar.principles.stories.tsx +3 -1
  237. package/src/components/Calendar/calendar.spec.md +2 -1
  238. package/src/components/Calendar/calendar.stories.tsx +3 -1
  239. package/src/components/Calendar/calendar.tsx +53 -19
  240. package/src/components/Carousel/carousel.tsx +3 -1
  241. package/src/components/Checkbox/checkbox.tsx +2 -1
  242. package/src/components/Chip/chip.anatomy.stories.tsx +8 -8
  243. package/src/components/Chip/chip.principles.stories.tsx +3 -3
  244. package/src/components/Chip/chip.spec.md +6 -3
  245. package/src/components/Chip/chip.tsx +56 -11
  246. package/src/components/Coachmark/coachmark.tsx +10 -8
  247. package/src/components/Combobox/combobox.tsx +8 -2
  248. package/src/components/Command/command.tsx +2 -1
  249. package/src/components/DataTable/data-table.spec.md +52 -95
  250. package/src/components/DataTable/data-table.stories.tsx +47 -0
  251. package/src/components/DataTable/data-table.tsx +145 -11
  252. package/src/components/DataTable/filter-tree.ts +178 -51
  253. package/src/components/DateGrid/date-grid.spec.md +5 -4
  254. package/src/components/DateGrid/date-grid.tsx +64 -11
  255. package/src/components/DatePicker/date-picker.tsx +19 -3
  256. package/src/components/DescriptionList/description-list.tsx +3 -1
  257. package/src/components/DropdownMenu/dropdown-menu.spec.md +4 -3
  258. package/src/components/DropdownMenu/dropdown-menu.tsx +22 -4
  259. package/src/components/Empty/empty.spec.md +0 -1
  260. package/src/components/Empty/empty.tsx +4 -1
  261. package/src/components/Field/field-controls.spec.md +1 -1
  262. package/src/components/Field/field.tsx +2 -1
  263. package/src/components/Field/form-validation.spec.md +1 -1
  264. package/src/components/Field/use-form-validation.ts +11 -7
  265. package/src/components/FileItem/file-item.spec.md +9 -0
  266. package/src/components/FileUpload/file-upload.spec.md +1 -1
  267. package/src/components/FileUpload/file-upload.tsx +18 -7
  268. package/src/components/FileViewer/can-render-image.ts +15 -0
  269. package/src/components/FileViewer/file-viewer.tsx +43 -18
  270. package/src/components/FileViewer/image-renderer.tsx +3 -8
  271. package/src/components/HoverCard/hover-card.spec.md +1 -1
  272. package/src/components/HoverCard/hover-card.tsx +3 -1
  273. package/src/components/Input/input.tsx +10 -4
  274. package/src/components/LinkInput/link-input.tsx +4 -1
  275. package/src/components/Menu/menu-item.anatomy.stories.tsx +1 -1
  276. package/src/components/Menu/menu-item.spec.md +2 -2
  277. package/src/components/Menu/menu-item.tsx +12 -3
  278. package/src/components/NumberInput/number-input.tsx +2 -1
  279. package/src/components/Pagination/index.ts +5 -0
  280. package/src/components/Pagination/pagination.anatomy.stories.tsx +143 -0
  281. package/src/components/Pagination/pagination.principles.stories.tsx +81 -0
  282. package/src/components/Pagination/pagination.spec.md +150 -0
  283. package/src/components/Pagination/pagination.stories.tsx +98 -0
  284. package/src/components/Pagination/pagination.tsx +263 -0
  285. package/src/components/PeoplePicker/people-picker.tsx +2 -1
  286. package/src/components/PeoplePicker/person-display.tsx +5 -1
  287. package/src/components/Popover/popover.anatomy.stories.tsx +1 -1
  288. package/src/components/Popover/popover.spec.md +2 -1
  289. package/src/components/Popover/popover.tsx +86 -37
  290. package/src/components/ProfileCard/profile-card.tsx +24 -6
  291. package/src/components/RadioGroup/radio-group.tsx +2 -1
  292. package/src/components/SegmentedControl/segmented-control.anatomy.stories.tsx +1 -1
  293. package/src/components/SegmentedControl/segmented-control.spec.md +6 -2
  294. package/src/components/SegmentedControl/segmented-control.tsx +15 -7
  295. package/src/components/Select/select.spec.md +1 -1
  296. package/src/components/Select/select.tsx +26 -4
  297. package/src/components/SelectMenu/select-menu.spec.md +2 -1
  298. package/src/components/SelectMenu/select-menu.tsx +86 -12
  299. package/src/components/Sheet/sheet.spec.md +1 -0
  300. package/src/components/Sheet/sheet.tsx +2 -1
  301. package/src/components/Sidebar/sidebar.tsx +5 -2
  302. package/src/components/Slider/slider.anatomy.stories.tsx +4 -4
  303. package/src/components/Slider/slider.spec.md +19 -85
  304. package/src/components/Slider/slider.tsx +13 -5
  305. package/src/components/Steps/steps.spec.md +1 -0
  306. package/src/components/Switch/switch.spec.md +1 -0
  307. package/src/components/Switch/switch.tsx +9 -1
  308. package/src/components/Tabs/tabs.anatomy.stories.tsx +4 -4
  309. package/src/components/Tabs/tabs.spec.md +13 -47
  310. package/src/components/Tabs/tabs.tsx +38 -9
  311. package/src/components/Tag/tag.principles.stories.tsx +1 -1
  312. package/src/components/Tag/tag.spec.md +11 -43
  313. package/src/components/Tag/tag.tsx +23 -1
  314. package/src/components/Textarea/textarea.principles.stories.tsx +2 -1
  315. package/src/components/Textarea/textarea.tsx +4 -1
  316. package/src/components/TimePicker/time-picker.tsx +31 -10
  317. package/src/components/Toast/toast.tsx +4 -1
  318. package/src/components/TreeView/tree-view.spec.md +1 -1
  319. package/src/components/TreeView/tree-view.tsx +10 -3
  320. package/src/hooks/use-controllable.ts +7 -2
  321. package/src/hooks/use-is-touch-device.ts +8 -1
  322. package/src/index.ts +1 -0
  323. package/src/patterns/element-anatomy/inline-action.spec.md +1 -1
  324. package/src/patterns/element-anatomy/item-anatomy.spec.md +1 -2
  325. package/src/patterns/element-anatomy/item-anatomy.tsx +4 -5
  326. package/src/patterns/horizontal-overflow/horizontal-overflow.stories.tsx +137 -0
  327. package/src/patterns/overlay-surface/overlay-surface.stories.tsx +116 -0
  328. package/src/tokens/color/color.spec.md +5 -7
  329. package/src/tokens/color/semantic.css +8 -2
  330. package/src/tokens/layoutSpace/layoutSpace.spec.md +1 -0
  331. package/src/tokens/motion/motion.stories.tsx +142 -0
  332. package/src/tokens/opacity/opacity.spec.md +1 -1
  333. package/src/tokens/uiSize/uiSize.stories.tsx +103 -0
@@ -0,0 +1,116 @@
1
+ // @story-baseline: patterns/header-canonical/header-canonical.stories.tsx#Overview — SurfaceHeader 段(title text-body-lg font-medium + dismiss size=sm)+ components/Dialog/dialog.stories.tsx footer 檔式(取消 tertiary + primary CTA)
2
+ //
3
+ // Internal Pattern 參照 story(對標 patterns/header-canonical 的 anatomy 參照定位)。
4
+ // SurfaceHeader / SurfaceBody / SurfaceFooter 是 @internal primitive——end-user 用
5
+ // DialogHeader / SheetHeader / PopoverHeader 等 wrapper,不直接 import;
6
+ // 本頁給 DS contributor 看「overlay 三段式結構 + padding / 分隔線契約」長什麼樣。
7
+ import type { Meta, StoryObj } from '@storybook/react'
8
+ import type { ReactNode } from 'react'
9
+ import { X } from 'lucide-react'
10
+ import { cn } from '@/lib/utils'
11
+ import { SurfaceHeader, SurfaceBody, SurfaceFooter } from './overlay-surface'
12
+ import { Button } from '@/design-system/components/Button/button'
13
+
14
+ const meta: Meta = {
15
+ title: 'Design System/Internal Patterns/Overlay Surface',
16
+ parameters: {
17
+ layout: 'padded',
18
+ docs: {
19
+ description: {
20
+ component: `
21
+ **@internal** — Dialog / Sheet / Popover / Coachmark 共用的浮層結構 primitive(SurfaceHeader / SurfaceBody / SurfaceFooter),統一 padding(\`px-loose py-tight\`)+ 分隔線(\`border-divider\`)語言,消除各 overlay 自寫 chrome 的漂移空間。
22
+
23
+ end-user 不直接 import——用 DialogHeader / SheetHeader / PopoverHeader 等 consumer wrapper;本頁是 DS contributor 的結構參照。
24
+
25
+ 完整規則:\`packages/design-system/src/patterns/overlay-surface/overlay-surface.spec.md\`(padding-based header canonical / unbounded slot trick / ScrollArea canonical / dismiss size canonical)
26
+ `,
27
+ },
28
+ },
29
+ },
30
+ }
31
+
32
+ export default meta
33
+ type Story = StoryObj
34
+
35
+ /** 模擬 consumer Content 外殼——radius / border / shadow / bg 是浮層外殼職責,
36
+ * 由 Dialog / Popover 的 Content 自己套(spec「不屬本 primitive 的職責」段 token 組)。 */
37
+ function Shell({ children, className }: { children: ReactNode; className?: string }) {
38
+ return (
39
+ <div
40
+ className={cn(
41
+ 'overflow-hidden rounded-lg border border-border bg-surface-raised shadow-[var(--elevation-200)]',
42
+ className,
43
+ )}
44
+ >
45
+ {children}
46
+ </div>
47
+ )
48
+ }
49
+
50
+ /** 1. 三段式結構 — Header(border-b)/ Body / Footer(border-t)各自的 padding 契約。
51
+ * 對標 Dialog「邀請成員」場景;header title = modal-tier typography(text-body-lg font-medium)。 */
52
+ export const ThreePartStructure: Story = {
53
+ name: '三段式結構',
54
+ render: () => (
55
+ <div className="flex flex-col gap-3">
56
+ <Shell className="w-[420px]">
57
+ <SurfaceHeader>
58
+ <h2 className="flex-1 truncate text-body-lg font-medium text-foreground">邀請成員加入專案</h2>
59
+ <Button iconOnly dismiss size="sm" startIcon={X} aria-label="關閉" />
60
+ </SurfaceHeader>
61
+ <SurfaceBody>
62
+ <p className="text-body text-foreground">
63
+ 輸入 Email 即可邀請成員加入「Acme 品牌改版」專案。
64
+ </p>
65
+ <p className="mt-2 text-caption text-fg-secondary">
66
+ 被邀請者會收到通知信,接受後自動取得專案的檢視與留言權限。
67
+ </p>
68
+ </SurfaceBody>
69
+ <SurfaceFooter>
70
+ <Button variant="tertiary">取消</Button>
71
+ <Button variant="primary">寄出邀請</Button>
72
+ </SurfaceFooter>
73
+ </Shell>
74
+ <p className="max-w-[420px] text-caption text-fg-muted">
75
+ 三段共用 px-loose / py-tight;Header 自畫 border-b、Footer 自畫 border-t。Header 是
76
+ padding-based(title 可換行、chrome 隨內容長高),dismiss 按鈕 native size 保 sm、
77
+ layout 佔位由 unbounded slot trick 縮回 title 行高 → header 自然閉合 48px。
78
+ </p>
79
+ </div>
80
+ ),
81
+ }
82
+
83
+ /** 2. 內文捲動 — 定高浮層下 header / footer 固定、body 內捲。
84
+ * Shell 需 flex flex-col(viewport-aware scroll chain:中間 wrapper 斷鏈 = body 不捲,spec K11 invariant)。 */
85
+ export const BodyScroll: Story = {
86
+ name: '內文捲動',
87
+ render: () => (
88
+ <div className="flex flex-col gap-3">
89
+ <Shell className="flex h-[280px] w-[420px] flex-col">
90
+ <SurfaceHeader>
91
+ <h2 className="flex-1 truncate text-body-lg font-medium text-foreground">服務條款更新</h2>
92
+ <Button iconOnly dismiss size="sm" startIcon={X} aria-label="關閉" />
93
+ </SurfaceHeader>
94
+ <SurfaceBody>
95
+ <div className="flex flex-col gap-3 text-body text-foreground">
96
+ <p>1. 資料保存期限由 30 天調整為 90 天,到期後自動匿名化。</p>
97
+ <p>2. 新增歐盟區域資料中心選項,既有工作區可在設定頁遷移。</p>
98
+ <p>3. API 免費額度調整為每月 10,000 次呼叫,超額部分依用量計費。</p>
99
+ <p>4. 子處理商清單新增兩家 CDN 供應商,完整清單見信任中心。</p>
100
+ <p>5. 帳單爭議申訴窗口由 14 天延長為 30 天。</p>
101
+ <p>6. 本次更新於 2026 年 8 月 1 日生效,繼續使用即視為同意。</p>
102
+ </div>
103
+ </SurfaceBody>
104
+ <SurfaceFooter>
105
+ <Button variant="tertiary">稍後再讀</Button>
106
+ <Button variant="primary">我已閱讀並同意</Button>
107
+ </SurfaceFooter>
108
+ </Shell>
109
+ <p className="max-w-[420px] text-caption text-fg-muted">
110
+ SurfaceBody 恆套 flex-1 min-h-0 overflow-y-auto:定高(或 viewport 太小)時 header / footer
111
+ 永遠可見、body 內捲。注意:Dialog / Sheet 正式 consumer 的 body 走 ScrollArea canonical
112
+ (跨 OS 捲軸一致),此處為 primitive 裸展示。
113
+ </p>
114
+ </div>
115
+ ),
116
+ }
@@ -159,10 +159,7 @@ Semantic token 按**載體類型**分成四個 family,**family 之間的 token
159
159
 
160
160
  > **Case**:Slider disabled 的 Range(填充段)一開始寫成 `bg-fg-disabled`。理由:`--fg-disabled`(neutral-6)剛好是我想要的「比 track 深但比文字淺」的灰度。但 `--fg-disabled` 語意是「**disabled 文字的前景色**」,拿來當 bg 等於借 fg token 當 bg 用。
161
161
  >
162
- > **問題**:
163
- > 1. **語意矛盾**:consumer 讀 code 時 `bg-fg-disabled` 會困惑「這到底是 bg 還是 fg」
164
- > 2. **耦合未來變動**:未來若微調 `--fg-disabled`(例如從 n-6 改成 n-7 讓 disabled 文字更可讀),Slider range 會被迫一起變,但它不是文字、不需要文字可讀性的約束
165
- > 3. **缺乏單一來源的 bg token**:應該存在一個「disabled 狀態的中層填充色」的 bg token(如果沒有,要新增一個 semantic alias,而不是借 fg)
162
+ > **問題**:(1)**語意矛盾**——consumer 讀 `bg-fg-disabled` 會困惑這是 bg 還是 fg;(2)**耦合未來變動**——微調 `--fg-disabled`(如 n-6→n-7 提高 disabled 文字可讀)會被迫連動 range,但 range 非文字、無文字可讀性約束;(3)**缺單一來源 bg token**——應存在「disabled 中層填充」bg token(沒有就新增 semantic alias,不是借 fg)
166
163
  >
167
164
  > **修正**:改用 `bg-border`(neutral-5)。`--border` 屬於 Border family,語意是「視覺分隔線 / 容器邊框 / 階層分隔的視覺元件」——跟 range 的「填充視覺指示器」角色接近,且 family 對得上(非文字的視覺填充類)。
168
165
 
@@ -677,14 +674,14 @@ Dark mode 覆寫:hover/active 方向反轉(hover → step-7,active → ste
677
674
  | Utility | Token | 用途 |
678
675
  |---------|-------|------|
679
676
  | `border-border` | neutral-5 alpha 15% | 元件標準邊框(input / Field family / standalone control)|
680
- | `border-border-hover` | neutral-6 alpha 25% | input、checkbox、radio 的 hover 邊框 |
677
+ | `border-border-hover` | neutral-6 alpha 25% | input、checkbox、radio 的 hover 邊框——**未 focus 的欄位 hover 走中性、不搶藍**(2026-07-07 源碼實查:MUI text.primary / Polaris input-border-hover / Fluent NeutralStroke1Hover / Carbon・shadcn 不變 = 多數派;Ant colorPrimaryHover 藍 hover 為少數派不採,藍色保留給 focus / 選中)|
681
678
  | `border-divider` | neutral-4 alpha 9% | 分隔線(比 border 更淡)/ **table 外框 + row divider 同色**(T-junction connectivity)|
682
679
  | `border-[var(--border-opaque)]` | neutral-5 opaque | alpha-immune 變體;cell bg 非白(disabled 灰底 / nested surface)時用 |
683
680
 
684
- 選中狀態的邊框或文字使用 hover token:
681
+ 選中狀態的邊框或文字使用 base token(2026-07-06 拍板:持續選中站 base、hover 階專屬瞬時態——Ant / Atlassian / Material 三家「瞬時弱、持續強」實錘;SSOT = semantic.css「選中狀態」段):
685
682
 
686
683
  ```tsx
687
- <div className="border-primary-hover text-primary-hover" />
684
+ <div className="border-primary text-primary" />
688
685
  ```
689
686
 
690
687
  ### T-junction connectivity 原則(2026-05-04 升 SSOT)
@@ -798,4 +795,5 @@ SSOT → `.claude/references/structural-token-retention.md`(6 類保留 + sub-ag
798
795
  - `progress-bar.spec.md`
799
796
  - `separator.spec.md`
800
797
  - `skeleton.spec.md`
798
+ - `slider.spec.md`
801
799
  - `token-system.spec.md`
@@ -67,7 +67,13 @@
67
67
  │ --border-hover input/checkbox/radio hover 邊框(neutral-6) │
68
68
  │ --divider 分隔線(neutral-4,比 border 更淡) │
69
69
  │ --ring focus 輪廓(= primary) │
70
- │ 選中狀態的邊框或文字 → 直接使用 var(--primary-hover)
70
+ │ 選中狀態的邊框或文字 → 直接使用 var(--primary)
71
+ │ (2026-07-06 拍板:持續選中站 base、hover 階專屬瞬時態—— │
72
+ │ Ant / Atlassian / Material 三家「瞬時弱、持續強」實錘) │
73
+ │ 選中之上的互動 = 同色相升降階(完整三階,2026-07-07 補): │
74
+ │ hover → var(--primary-hover)、按壓 → var(--primary-active) │
75
+ │ (Button pressed hover / Ant active 頁 hover 同派;實心填色家族 │
76
+ │ 同理:bg-primary → hover bg-primary-hover,Checkbox/Switch/DateGrid)│
71
77
  └─────────────────────────────────────────────────────────────────────┘
72
78
 
73
79
  ┌─ Static Subtle ─────────────────────────────────────────────────────┐
@@ -137,7 +143,7 @@
137
143
  │ (不橋接成 utility class——只有 Tag/Avatar dismiss 一個 consumer)│
138
144
  └─────────────────────────────────────────────────────────────────────┘
139
145
 
140
- 選中邊框/文字 → border-[var(--primary-hover)] / text-[var(--primary-hover)]
146
+ 選中邊框/文字 → border-primary / text-primary(2026-07-06 持續選中改 base,hover 階專屬瞬時態)
141
147
  ═══════════════════════════════════════════════════════════════════════ */
142
148
 
143
149
 
@@ -320,5 +320,6 @@ document.documentElement.setAttribute('data-layout-space', 'lg')
320
320
  - `description-list.spec.md`
321
321
  - `empty.spec.md`
322
322
  - `overlay-surface.spec.md`
323
+ - `pagination.spec.md`
323
324
  - `token-system.spec.md`
324
325
  - `uiSize.spec.md`
@@ -0,0 +1,142 @@
1
+ // @story-baseline: components/HoverCard/hover-card.stories.tsx#LinkPreview — 延遲體感 demo 消費真實 consumer(Button iconOnly auto-Tooltip + HoverCard 預設 delay),非手刻浮層
2
+ import type { Meta, StoryObj } from '@storybook/react'
3
+ import { Download } from 'lucide-react'
4
+ import { Button } from '@/design-system/components/Button/button'
5
+ import {
6
+ HoverCard,
7
+ HoverCardTrigger,
8
+ HoverCardContent,
9
+ } from '@/design-system/components/HoverCard/hover-card'
10
+
11
+ const meta: Meta = {
12
+ title: 'Design System/Tokens/Motion',
13
+ parameters: {
14
+ layout: 'padded',
15
+ docs: {
16
+ description: {
17
+ component: `
18
+ Motion token 系統。目前唯一 token 家族 = **hover delay 3-tier**(「hover 觸發 → 延遲 N ms → overlay 顯示」)——目的不是動畫長度,是「user 真的想看」過濾器;overlay 開閉的 enter / exit 動畫由 Radix data-state + CSS 處理,系統**無** duration / easing token。
19
+
20
+ 完整規則:\`packages/design-system/src/tokens/motion/motion.spec.md\`
21
+
22
+ **JS mirror**:Radix props(\`delayDuration\` / \`openDelay\` / \`closeDelay\`)只吃 number 不認 CSS var,故 consumer 消費 \`motion.ts\` 的 \`HOVER_DELAY_PLAIN_MS\` / \`HOVER_DELAY_RICH_MS\` / \`HOVER_DELAY_CLOSE_MS\`(與 \`motion.css\` 同值鏡像)。
23
+ `,
24
+ },
25
+ },
26
+ },
27
+ }
28
+
29
+ export default meta
30
+ type Story = StoryObj
31
+
32
+
33
+ function DelayRow({ token, value, usage, consumers }: {
34
+ token: string; value: string; usage: string; consumers: string
35
+ }) {
36
+ return (
37
+ <div className="grid items-center gap-x-6 gap-y-1 border-b border-border py-4 last:border-0"
38
+ style={{ gridTemplateColumns: '200px 80px 1fr 220px' }}>
39
+ <div>
40
+ <code className="block text-caption font-medium text-fg-secondary">{token}</code>
41
+ </div>
42
+ <div className="text-caption font-mono text-fg-muted">{value}</div>
43
+ <div className="text-body text-foreground">{usage}</div>
44
+ <div className="text-caption text-fg-muted">{consumers}</div>
45
+ </div>
46
+ )
47
+ }
48
+
49
+
50
+ export const Overview: Story = {
51
+ name: '總覽',
52
+ render: () => (
53
+ <div className="max-w-4xl">
54
+ <h2 className="text-h3 mb-2">Hover Delay Tokens</h2>
55
+ <p className="text-body text-fg-secondary mb-6">
56
+ 三層 tier:<code>plain</code>(被動文字提示)/ <code>rich</code>(含 fetch 的內容預覽,門檻更高)/
57
+ <code>close</code>(通用關閉緩衝)。命名對齊 Material 3「plain / rich tooltip」術語 +
58
+ DS 既有 <code>compact / rich</code> mode 詞彙。
59
+ </p>
60
+
61
+ <DelayRow
62
+ token="--hover-delay-plain"
63
+ value="500ms"
64
+ usage="純文字提示——被動 hint,user 真停留才觸發,避免滑過列表時 N 次視覺擾動"
65
+ consumers="Tooltip / OverflowIndicator"
66
+ />
67
+ <DelayRow
68
+ token="--hover-delay-rich"
69
+ value="700ms"
70
+ usage="內容預覽——含 fetch / multi-section,避免列表掃視誤觸發 fetch waterfall"
71
+ consumers="HoverCard / ProfileCard / Avatar"
72
+ />
73
+ <DelayRow
74
+ token="--hover-delay-close"
75
+ value="200ms"
76
+ usage="通用關閉緩衝——mouse leave 後 200ms 內移回不會關(誤滑出容錯)"
77
+ consumers="所有 hover overlay"
78
+ />
79
+
80
+ <p className="text-caption text-fg-muted mt-6">
81
+ 實際 CSS 值見 <code>packages/design-system/src/tokens/motion/motion.css</code>;
82
+ JS number 鏡像見同目錄 <code>motion.ts</code>;tier 選擇表(何時用哪 token)見 <code>motion.spec.md</code>。
83
+ </p>
84
+ </div>
85
+ ),
86
+ }
87
+
88
+
89
+ /* 延遲體感 — 用真實 consumer 展示三個 token 的實際時序(非模擬動畫):
90
+ Tooltip 走全域 TooltipProvider delayDuration=500(= plain);
91
+ HoverCard Root 預設 openDelay=700 / closeDelay=200(= rich / close)。 */
92
+ export const DelayFeel: Story = {
93
+ name: '延遲體感',
94
+ render: () => (
95
+ <div className="flex max-w-2xl flex-col gap-8">
96
+ <section className="flex flex-col gap-2">
97
+ <div className="text-body font-medium text-foreground">plain(500ms)— 工具列 icon 按鈕的文字提示</div>
98
+ <p className="text-caption text-fg-secondary">
99
+ hover 下方按鈕停留 500ms 才出現 tooltip;快速滑過不觸發。移開後 tooltip 立即依全域
100
+ Provider 收合節奏消失。
101
+ </p>
102
+ <div>
103
+ <Button iconOnly variant="text" size="sm" startIcon={Download} aria-label="下載簡報" />
104
+ </div>
105
+ </section>
106
+
107
+ <section className="flex flex-col gap-2">
108
+ <div className="text-body font-medium text-foreground">rich(700ms)+ close(200ms)— 留言裡的人名預覽卡</div>
109
+ <p className="text-caption text-fg-secondary">
110
+ rich 內容(可能含 fetch)門檻比 plain 高 200ms——必須「真的想看」才停留 700ms;
111
+ 移開後 200ms 內移回卡片不會關(close 緩衝)。
112
+ </p>
113
+ <p className="text-body leading-relaxed">
114
+ 這版 onboarding 流程的視覺稿請找
115
+ {/* defaultOpen:讓 visual snapshot 看得到卡片(M15 OpenSnapshot);移開再 hover 即體驗 700/200ms 時序 */}
116
+ <HoverCard defaultOpen>
117
+ <HoverCardTrigger asChild>
118
+ <a
119
+ href="#"
120
+ onClick={(e) => e.preventDefault()}
121
+ className="text-primary underline underline-offset-2 mx-1 cursor-pointer"
122
+ >
123
+ 陳美惠
124
+ </a>
125
+ </HoverCardTrigger>
126
+ <HoverCardContent
127
+ className="bg-surface-raised border border-border rounded-lg p-4"
128
+ style={{ boxShadow: 'var(--elevation-200)', width: 260 }}
129
+ >
130
+ <div className="flex flex-col gap-1">
131
+ <div className="text-body font-medium text-foreground">陳美惠</div>
132
+ <div className="text-caption text-fg-secondary">產品設計師 · Design Platform</div>
133
+ <div className="text-footnote text-fg-muted">台北 · GMT+8 · 上班時間 10:00–19:00</div>
134
+ </div>
135
+ </HoverCardContent>
136
+ </HoverCard>
137
+ 確認,她負責這一季的設計系統整合。
138
+ </p>
139
+ </section>
140
+ </div>
141
+ ),
142
+ }
@@ -64,7 +64,7 @@ Tailwind 提供 `opacity-{5/10/20/30/40/50/60/70/80/90/95}` 百分比 ladder,但
64
64
 
65
65
  ## 消費者
66
66
 
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`)。
67
+ 直接套用 `opacity-disabled` 的元件(grep 驗證 2026-07-05;Textarea 已全面 token-swap 化移除):Avatar(Field disabled context self-dim)、Button(`aria-disabled` 分支)、MenuItem、Rating(disabled / loading 整塊)、Steps、Switch、DataTable(drag source 半透 + 整表 refresh loading reuse,經 `lib/drag-visual.ts`)。
68
68
 
69
69
  非消費者(曾誤列):Slider / Sidebar 走灰階 token swap;Chip 無 opacity 用例;Field wrapper blanket 已移除(Avatar self-dim 取代,見 field-wrapper.tsx 註解)。
70
70
 
@@ -0,0 +1,103 @@
1
+ // @story-baseline: tokens/density/density.stories.tsx#UISize — token bar 展示慣例同源;本頁展示 size-tier 軸(xs/sm/md/lg + icon 兩 tier),density md/lg 軸在 Tokens/Density 不重複
2
+ import type { Meta, StoryObj } from '@storybook/react'
3
+ import { Download } from 'lucide-react'
4
+ import { ICON_SIZE } from './icon-size'
5
+
6
+ const meta: Meta = {
7
+ title: 'Design System/Tokens/UiSize',
8
+ parameters: {
9
+ layout: 'padded',
10
+ docs: {
11
+ description: {
12
+ component: `
13
+ 元件高度的語義 token(rem 單位,尊重使用者瀏覽器字體設定)。\`--field-height-*\` 是核心家族——Button / Input / Select 等互動元件共享 **default \`md\`**;另有 table-row / tab-height / chrome-header 等家族(見 spec)。
14
+
15
+ 完整規則:\`packages/design-system/src/tokens/uiSize/uiSize.spec.md\`(family 成員清單 / default md 硬規則 / icon 兩 tier / chrome header 選型)
16
+
17
+ **md ↔ lg density 軸**的對照展示在 \`Design System/Tokens/Density\`,本頁不重複;此處展示 **size tier 軸**(xs / sm / md / lg)與 icon 尺寸的離散配對。
18
+ `,
19
+ },
20
+ },
21
+ },
22
+ }
23
+
24
+ export default meta
25
+ type Story = StoryObj
26
+
27
+
28
+ function HeightRow({ token, px, usage, isDefault }: {
29
+ token: string; px: string; usage: string; isDefault?: boolean
30
+ }) {
31
+ return (
32
+ <div className="grid items-center gap-x-6 border-b border-border py-3 last:border-0"
33
+ style={{ gridTemplateColumns: '200px 160px 60px 1fr' }}>
34
+ <div>
35
+ <code className="block text-caption font-medium text-fg-secondary">{token}</code>
36
+ {isDefault && <span className="text-caption text-fg-muted">★ family default</span>}
37
+ </div>
38
+ <div
39
+ className="rounded-md bg-primary"
40
+ style={{ height: `var(${token})`, width: '100%' }}
41
+ />
42
+ <span className="text-caption font-mono text-fg-muted">{px}</span>
43
+ <span className="text-body text-foreground">{usage}</span>
44
+ </div>
45
+ )
46
+ }
47
+
48
+ function IconTierRow({ tier, iconPx, note }: { tier: string; iconPx: number; note: string }) {
49
+ return (
50
+ <div className="grid items-center gap-x-6 border-b border-border py-3 last:border-0"
51
+ style={{ gridTemplateColumns: '260px 120px 1fr' }}>
52
+ <code className="text-caption font-medium text-fg-secondary">{tier}</code>
53
+ <div className="flex items-center gap-2">
54
+ <Download size={iconPx} className="text-foreground" aria-hidden />
55
+ <span className="text-caption font-mono text-fg-muted">{iconPx}px</span>
56
+ </div>
57
+ <span className="text-body text-foreground">{note}</span>
58
+ </div>
59
+ )
60
+ }
61
+
62
+
63
+ export const Overview: Story = {
64
+ name: '總覽',
65
+ render: () => (
66
+ <div className="max-w-3xl">
67
+ <h2 className="text-h3 mb-2">Field Height</h2>
68
+ <p className="text-body text-fg-secondary mb-4">
69
+ Button / Input / Checkbox SelectionItem 等互動元件的高度。所有 field-height 消費者
70
+ <strong>不傳 size 時自動對齊 md</strong>——Form / Toolbar 並排多控件默認等高。
71
+ 下列為 md density 預設值(lg density 對照見 Tokens/Density)。
72
+ </p>
73
+
74
+ <HeightRow token="--field-height-xs" px="24px" usage="密集 UI 地板高度;固定不隨 density 縮放。獨立互動元件不得低於此高度" />
75
+ <HeightRow token="--field-height-sm" px="28px" usage="輕量浮層(Popover body / footer)內的控件尺寸" />
76
+ <HeightRow token="--field-height-md" px="32px" usage="Form / Dialog / 一般頁面的控件尺寸" isDefault />
77
+ <HeightRow token="--field-height-lg" px="36px" usage="需要更大點擊目標的場景;同時切換到大 icon tier(20px)" />
78
+
79
+ <h2 className="text-h3 mb-2 mt-10">Icon 尺寸兩 tier</h2>
80
+ <p className="text-body text-fg-secondary mb-4">
81
+ Icon 尺寸由元件引用的 field-height token 決定——離散兩組配對,無中間值、不需公式。
82
+ 程式化 SSOT 是 <code>ICON_SIZE</code> 常數(本表直接消費真值渲染)。
83
+ </p>
84
+
85
+ <IconTierRow
86
+ tier="field-height-xs / sm / md"
87
+ iconPx={ICON_SIZE.sm}
88
+ note="搭配 text-body(14px);Checkbox / Radio 控件同 16px"
89
+ />
90
+ <IconTierRow
91
+ tier="field-height-lg"
92
+ iconPx={ICON_SIZE.lg}
93
+ note="搭配 text-body-lg(16px);Checkbox / Radio 控件同 20px"
94
+ />
95
+
96
+ <p className="text-caption text-fg-muted mt-6">
97
+ Stroke icon 下限 12px(僅出現在 Checkbox 等指示器內部);Rating / Avatar 等 8 個 carve-out
98
+ 見 <code>uiSize.spec.md</code>「跨 regime pointer index」。table-row / tab-height /
99
+ chrome-header 等其餘 uiSize 家族與選型 decision tree 同見該 spec。
100
+ </p>
101
+ </div>
102
+ ),
103
+ }