@qijenchen/design-system 0.1.0-beta.10 → 0.1.0-beta.13

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 (307) hide show
  1. package/CLAUDE.md +201 -0
  2. package/README.md +7 -15
  3. package/cli-init.mjs +90 -0
  4. package/ds-canonical/commands/README.md +26 -0
  5. package/ds-canonical/commands/gov-status.md +79 -0
  6. package/ds-canonical/hooks/README.md +145 -0
  7. package/ds-canonical/hooks/_log-fire.sh +44 -0
  8. package/ds-canonical/hooks/block_prototype_imports.py +111 -0
  9. package/ds-canonical/hooks/check_app_shell_primary_header_consistency.sh +68 -0
  10. package/ds-canonical/hooks/check_audit_post_report_validator.sh +88 -0
  11. package/ds-canonical/hooks/check_audit_sample_escape.sh +73 -0
  12. package/ds-canonical/hooks/check_benchmark_citation.sh +106 -0
  13. package/ds-canonical/hooks/check_canonical_propagation.sh +189 -0
  14. package/ds-canonical/hooks/check_chrome_header_handcraft.sh +70 -0
  15. package/ds-canonical/hooks/check_codex_brief_invariants.sh +83 -0
  16. package/ds-canonical/hooks/check_codex_collab_5step.sh +108 -0
  17. package/ds-canonical/hooks/check_datatable_invariants.sh +117 -0
  18. package/ds-canonical/hooks/check_dim_count_drift.sh +72 -0
  19. package/ds-canonical/hooks/check_field_controls_contracts.sh +110 -0
  20. package/ds-canonical/hooks/check_field_family_invariants.sh +205 -0
  21. package/ds-canonical/hooks/check_file_size_budget.sh +60 -0
  22. package/ds-canonical/hooks/check_header_with_tabs_border.sh +87 -0
  23. package/ds-canonical/hooks/check_main_branch_workbench.sh +93 -0
  24. package/ds-canonical/hooks/check_naming_and_abstraction.sh +165 -0
  25. package/ds-canonical/hooks/check_opacity_token_usage.sh +149 -0
  26. package/ds-canonical/hooks/check_pattern_invariants.sh +194 -0
  27. package/ds-canonical/hooks/check_peoplepicker_ssot_drift.sh +56 -0
  28. package/ds-canonical/hooks/check_pixel_quantified_audit.sh +53 -0
  29. package/ds-canonical/hooks/check_propose_plain_chinese.sh +74 -0
  30. package/ds-canonical/hooks/check_propose_pre_grep_verify.sh +70 -0
  31. package/ds-canonical/hooks/check_select_all_canonical.sh +58 -0
  32. package/ds-canonical/hooks/check_solo_workflow.sh +258 -0
  33. package/ds-canonical/hooks/check_spec_class_drift.sh +88 -0
  34. package/ds-canonical/hooks/check_story_invariants.sh +612 -0
  35. package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +105 -0
  36. package/ds-canonical/hooks/check_tab_lg_chrome_header_equal.sh +66 -0
  37. package/ds-canonical/hooks/check_wrapper_primitive_schema_drift.sh +104 -0
  38. package/ds-canonical/hooks/enforce_home_charter.sh +44 -0
  39. package/ds-canonical/hooks/inject_pending_self_audit.sh +204 -0
  40. package/ds-canonical/hooks/lib/_approval_re.sh +33 -0
  41. package/ds-canonical/hooks/lib/_code_quality.sh +73 -0
  42. package/ds-canonical/hooks/lib/_cva_default_sync.sh +69 -0
  43. package/ds-canonical/hooks/lib/_governance_coverage_check.sh +49 -0
  44. package/ds-canonical/hooks/lib/_hardcoded_strings.sh +163 -0
  45. package/ds-canonical/hooks/lib/_layout_space_canonical.sh +56 -0
  46. package/ds-canonical/hooks/lib/_overlay_handcraft.sh +141 -0
  47. package/ds-canonical/hooks/lib/_person_data_richness.sh +42 -0
  48. package/ds-canonical/hooks/lib/_story_compile_drift.sh +48 -0
  49. package/ds-canonical/hooks/lib/_token_hygiene.sh +95 -0
  50. package/ds-canonical/hooks/log_governance_fires.sh +50 -0
  51. package/ds-canonical/hooks/log_skill_invokes.sh +41 -0
  52. package/ds-canonical/hooks/post_edit_dispatcher.sh +62 -0
  53. package/ds-canonical/hooks/retired/check_anatomy_section_numbering.sh +106 -0
  54. package/ds-canonical/hooks/retired/check_avatar_hovercard.sh +90 -0
  55. package/ds-canonical/hooks/retired/check_button_icon_literal.sh.retired-2026-04-28 +38 -0
  56. package/ds-canonical/hooks/retired/check_container_breathing.sh +142 -0
  57. package/ds-canonical/hooks/retired/check_governance_compliance.sh +61 -0
  58. package/ds-canonical/hooks/retired/check_icon_only_padding_formula.sh +104 -0
  59. package/ds-canonical/hooks/retired/check_item_content_primitive.sh +150 -0
  60. package/ds-canonical/hooks/retired/check_item_list_gap.sh +153 -0
  61. package/ds-canonical/hooks/retired/check_sideoffset_canonical.sh +65 -0
  62. package/ds-canonical/hooks/retired/check_spec_iteration_tag.sh +87 -0
  63. package/ds-canonical/hooks/retired/check_ssot_consultation.sh +88 -0
  64. package/ds-canonical/hooks/retired/check_sync_update.sh +20 -0
  65. package/ds-canonical/hooks/retired/check_third_party_dom_verified.sh +95 -0
  66. package/ds-canonical/hooks/retired/enforce_home_charter.sh +125 -0
  67. package/ds-canonical/hooks/retired/post_edit_canonical_interrogate.sh +109 -0
  68. package/ds-canonical/hooks/retired/pre_edit_spec_check.sh +68 -0
  69. package/ds-canonical/hooks/retired/pre_new_component_spec.sh +39 -0
  70. package/ds-canonical/hooks/retired/pre_write_subsumption_check.sh +112 -0
  71. package/ds-canonical/hooks/retired/stop_meta_self_audit.sh.retired-2026-05-13 +76 -0
  72. package/ds-canonical/hooks/retired/tests/test_check_anatomy_section_numbering.sh +14 -0
  73. package/ds-canonical/hooks/retired/tests/test_check_avatar_hovercard.sh +15 -0
  74. package/ds-canonical/hooks/retired/tests/test_check_container_breathing.sh +15 -0
  75. package/ds-canonical/hooks/retired/tests/test_check_governance_compliance.sh +15 -0
  76. package/ds-canonical/hooks/retired/tests/test_check_icon_only_padding_formula.sh +79 -0
  77. package/ds-canonical/hooks/retired/tests/test_check_item_content_primitive.sh +15 -0
  78. package/ds-canonical/hooks/retired/tests/test_check_item_list_gap.sh +163 -0
  79. package/ds-canonical/hooks/retired/tests/test_check_sideoffset_canonical.sh +15 -0
  80. package/ds-canonical/hooks/retired/tests/test_check_spec_iteration_tag.sh +15 -0
  81. package/ds-canonical/hooks/retired/tests/test_check_ssot_consultation.sh +15 -0
  82. package/ds-canonical/hooks/retired/tests/test_check_sync_update.sh +14 -0
  83. package/ds-canonical/hooks/retired/tests/test_check_third_party_dom_verified.sh +15 -0
  84. package/ds-canonical/hooks/retired/tests/test_enforce_home_charter.sh +15 -0
  85. package/ds-canonical/hooks/retired/tests/test_pre_edit_spec_check.sh +15 -0
  86. package/ds-canonical/hooks/retired/tests/test_pre_new_component_spec.sh +15 -0
  87. package/ds-canonical/hooks/retired/tests/test_pre_write_subsumption_check.sh +63 -0
  88. package/ds-canonical/hooks/session_start_governance_check.sh +263 -0
  89. package/ds-canonical/hooks/stop_passive_logging.sh +322 -0
  90. package/ds-canonical/hooks/stop_self_audit.sh +450 -0
  91. package/ds-canonical/hooks/tests/KNOWN-BROKEN.md +15 -0
  92. package/ds-canonical/hooks/tests/run-all.sh +76 -0
  93. package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +143 -0
  94. package/ds-canonical/hooks/tests/test_check_app_shell_primary_header_consistency.sh +140 -0
  95. package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +115 -0
  96. package/ds-canonical/hooks/tests/test_check_audit_sample_escape.sh +93 -0
  97. package/ds-canonical/hooks/tests/test_check_benchmark_citation.sh +115 -0
  98. package/ds-canonical/hooks/tests/test_check_canonical_propagation.sh +133 -0
  99. package/ds-canonical/hooks/tests/test_check_chrome_header_handcraft.sh +123 -0
  100. package/ds-canonical/hooks/tests/test_check_code_quality.sh +15 -0
  101. package/ds-canonical/hooks/tests/test_check_codex_collab_5step.sh +96 -0
  102. package/ds-canonical/hooks/tests/test_check_cva_default_sync.sh +15 -0
  103. package/ds-canonical/hooks/tests/test_check_datatable_invariants.sh +122 -0
  104. package/ds-canonical/hooks/tests/test_check_dim_count_drift.sh +98 -0
  105. package/ds-canonical/hooks/tests/test_check_field_controls_contracts.sh +126 -0
  106. package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +194 -0
  107. package/ds-canonical/hooks/tests/test_check_file_size_budget.sh +32 -0
  108. package/ds-canonical/hooks/tests/test_check_hardcoded_strings.sh +14 -0
  109. package/ds-canonical/hooks/tests/test_check_header_with_tabs_border.sh +110 -0
  110. package/ds-canonical/hooks/tests/test_check_layout_space_canonical.sh +73 -0
  111. package/ds-canonical/hooks/tests/test_check_main_branch_workbench.sh +147 -0
  112. package/ds-canonical/hooks/tests/test_check_naming_and_abstraction.sh +136 -0
  113. package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +110 -0
  114. package/ds-canonical/hooks/tests/test_check_overlay_handcraft.sh +126 -0
  115. package/ds-canonical/hooks/tests/test_check_pattern_invariants.sh +148 -0
  116. package/ds-canonical/hooks/tests/test_check_peoplepicker_ssot_drift.sh +108 -0
  117. package/ds-canonical/hooks/tests/test_check_person_data_richness.sh +58 -0
  118. package/ds-canonical/hooks/tests/test_check_pixel_quantified_audit.sh +142 -0
  119. package/ds-canonical/hooks/tests/test_check_propose_plain_chinese.sh +126 -0
  120. package/ds-canonical/hooks/tests/test_check_propose_pre_grep_verify.sh +117 -0
  121. package/ds-canonical/hooks/tests/test_check_select_all_canonical.sh +125 -0
  122. package/ds-canonical/hooks/tests/test_check_solo_workflow.sh +201 -0
  123. package/ds-canonical/hooks/tests/test_check_spec_class_drift.sh +135 -0
  124. package/ds-canonical/hooks/tests/test_check_story_anatomy.sh.broken +197 -0
  125. package/ds-canonical/hooks/tests/test_check_story_category.sh.broken +187 -0
  126. package/ds-canonical/hooks/tests/test_check_story_compile_drift.sh +15 -0
  127. package/ds-canonical/hooks/tests/test_check_story_invariants.sh +209 -0
  128. package/ds-canonical/hooks/tests/test_check_story_name_jargon.sh.broken +53 -0
  129. package/ds-canonical/hooks/tests/test_check_story_slot_split.sh +156 -0
  130. package/ds-canonical/hooks/tests/test_check_substantive_edit_approval_preflight.sh +176 -0
  131. package/ds-canonical/hooks/tests/test_check_tab_lg_chrome_header_equal.sh +138 -0
  132. package/ds-canonical/hooks/tests/test_check_token_hygiene.sh +21 -0
  133. package/ds-canonical/hooks/tests/test_check_wrapper_primitive_schema_drift.sh +169 -0
  134. package/ds-canonical/hooks/tests/test_enforce_home_charter.sh +77 -0
  135. package/ds-canonical/hooks/tests/test_inject_pending_self_audit.sh +125 -0
  136. package/ds-canonical/hooks/tests/test_log_governance_fires.sh +10 -0
  137. package/ds-canonical/hooks/tests/test_log_skill_invokes.sh +7 -0
  138. package/ds-canonical/hooks/tests/test_post_edit_dispatcher.sh +108 -0
  139. package/ds-canonical/hooks/tests/test_session_start_governance_check.sh +143 -0
  140. package/ds-canonical/hooks/tests/test_stop_capture_metrics.sh +95 -0
  141. package/ds-canonical/hooks/tests/test_stop_governance_drift_check.sh.broken +125 -0
  142. package/ds-canonical/hooks/tests/test_stop_harvest_corrections.sh +10 -0
  143. package/ds-canonical/hooks/tests/test_stop_passive_logging.sh +100 -0
  144. package/ds-canonical/hooks/tests/test_stop_self_audit.sh +76 -0
  145. package/ds-canonical/hooks/tests/test_stop_tsc_sanity.sh +10 -0
  146. package/ds-canonical/references/README.md +43 -0
  147. package/ds-canonical/references/audit-coverage-vs-24-checklist.md +74 -0
  148. package/ds-canonical/references/build-ui-canonicals.md +69 -0
  149. package/ds-canonical/references/cva-patterns.md +41 -0
  150. package/ds-canonical/references/drag-canonical.md +331 -0
  151. package/ds-canonical/references/item-anatomy-recipe.md +225 -0
  152. package/ds-canonical/references/naming-conventions.md +56 -0
  153. package/ds-canonical/references/principle-dim-map.json +515 -0
  154. package/ds-canonical/references/props-naming.md +45 -0
  155. package/ds-canonical/references/spec-rules.md +58 -0
  156. package/ds-canonical/references/ssot-consultation.md +63 -0
  157. package/ds-canonical/references/ssot-index.md +40 -0
  158. package/ds-canonical/references/story-baseline-registry.json +79 -0
  159. package/ds-canonical/references/structural-token-retention.md +42 -0
  160. package/ds-canonical/references/tailwind-gotchas.md +87 -0
  161. package/ds-canonical/references/ui-dev-rules.md +60 -0
  162. package/ds-canonical/rules/README.md +34 -0
  163. package/ds-canonical/rules/meta-patterns.md +87 -0
  164. package/ds-canonical/rules/self-verify.md +53 -0
  165. package/ds-canonical/rules/spec-rules.md +25 -0
  166. package/ds-canonical/rules/story-rules.md +56 -0
  167. package/ds-canonical/rules/ui-development.md +87 -0
  168. package/ds-canonical/skills/README.md +88 -0
  169. package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +181 -0
  170. package/ds-canonical/skills/code-quality-audit/SKILL.md +63 -0
  171. package/ds-canonical/skills/codex-collab/SKILL.md +249 -0
  172. package/ds-canonical/skills/codex-collab/references/brief-template.md +48 -0
  173. package/ds-canonical/skills/codex-collab/references/transport.md +58 -0
  174. package/ds-canonical/skills/codify-corrections/SKILL.md +184 -0
  175. package/ds-canonical/skills/codify-principle/SKILL.md +151 -0
  176. package/ds-canonical/skills/component-quality-gate/SKILL.md +102 -0
  177. package/ds-canonical/skills/component-quality-gate/references/checklist.md +79 -0
  178. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +247 -0
  179. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +123 -0
  180. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +165 -0
  181. package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +91 -0
  182. package/ds-canonical/skills/delivery-handoff/SKILL.md +229 -0
  183. package/ds-canonical/skills/delivery-handoff/references/flow-diagram.md +180 -0
  184. package/ds-canonical/skills/delivery-handoff/references/handoff-template.md +177 -0
  185. package/ds-canonical/skills/delivery-handoff/references/inventory-checklist.md +196 -0
  186. package/ds-canonical/skills/design-system-audit/SKILL.md +343 -0
  187. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +1260 -0
  188. package/ds-canonical/skills/design-system-audit/references/checkpoints.md +240 -0
  189. package/ds-canonical/skills/design-system-audit/references/historical-bugs.md +240 -0
  190. package/ds-canonical/skills/design-system-audit/references/principle-audit-protocol.md +364 -0
  191. package/ds-canonical/skills/design-system-audit/references/rule-placement.md +175 -0
  192. package/ds-canonical/skills/design-system-audit/references/spec-template.md +66 -0
  193. package/ds-canonical/skills/ensure-canonical/SKILL.md +196 -0
  194. package/ds-canonical/skills/governance-health/SKILL.md +146 -0
  195. package/ds-canonical/skills/knowledge-prune/SKILL.md +303 -0
  196. package/ds-canonical/skills/new-component/SKILL.md +170 -0
  197. package/ds-canonical/skills/new-component/references/new-component-checklist.md +85 -0
  198. package/ds-canonical/skills/performance-audit/SKILL.md +107 -0
  199. package/ds-canonical/skills/product-ui-audit/SKILL.md +230 -0
  200. package/ds-canonical/skills/product-ui-audit/references/audit-checks.md +246 -0
  201. package/ds-canonical/skills/product-ui-audit/references/common-misuses.md +329 -0
  202. package/ds-canonical/skills/product-ui-audit/references/report-template.md +159 -0
  203. package/ds-canonical/skills/propose-options/SKILL.md +177 -0
  204. package/ds-canonical/skills/prototype/SKILL.md +244 -0
  205. package/ds-canonical/skills/prototype/references/audit-checks.md +37 -0
  206. package/ds-canonical/skills/prototype/references/benchmark-sources.md +94 -0
  207. package/ds-canonical/skills/prototype/references/checkpoints.md +191 -0
  208. package/ds-canonical/skills/prototype/references/evaluation-matrix.md +141 -0
  209. package/ds-canonical/skills/prototype/references/ooux-template.md +198 -0
  210. package/ds-canonical/skills/prototype/references/proposal-template.md +229 -0
  211. package/ds-canonical/skills/scan-similar-bugs/SKILL.md +198 -0
  212. package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +159 -0
  213. package/ds-canonical/skills/story-writing/SKILL.md +122 -0
  214. package/ds-canonical/skills/story-writing/references/anatomy-standard.md +217 -0
  215. package/ds-canonical/skills/story-writing/references/category-templates.md +174 -0
  216. package/ds-canonical/skills/story-writing/references/example-selection.md +70 -0
  217. package/ds-canonical/skills/story-writing/references/self-check.md +20 -0
  218. package/ds-canonical/skills/ux-audit/SKILL.md +130 -0
  219. package/ds-canonical/skills/visual-audit/SKILL.md +245 -0
  220. package/ds-canonical/skills/visual-audit/output/.gitkeep +0 -0
  221. package/ds-canonical/skills/visual-audit/references/audit-architecture.md +100 -0
  222. package/ds-canonical/skills/visual-audit/references/visual-checklist.md +297 -0
  223. package/ds-canonical/skills/visual-audit/references/world-class-benchmarks.md +198 -0
  224. package/package.json +9 -5
  225. package/src/components/Accordion/accordion.spec.md +114 -0
  226. package/src/components/Alert/alert.spec.md +197 -0
  227. package/src/components/AppShell/app-shell.spec.md +331 -0
  228. package/src/components/AspectRatio/aspect-ratio.spec.md +134 -0
  229. package/src/components/Avatar/avatar.spec.md +329 -0
  230. package/src/components/Badge/badge.spec.md +380 -0
  231. package/src/components/Breadcrumb/breadcrumb.spec.md +257 -0
  232. package/src/components/BulkActionBar/bulk-action-bar.spec.md +210 -0
  233. package/src/components/Button/button.spec.md +460 -0
  234. package/src/components/Calendar/calendar.spec.md +242 -0
  235. package/src/components/Carousel/carousel.spec.md +253 -0
  236. package/src/components/Chart/chart.spec.md +155 -0
  237. package/src/components/Checkbox/checkbox.spec.md +344 -0
  238. package/src/components/Chip/chip.spec.md +237 -0
  239. package/src/components/CircularProgress/circular-progress.spec.md +268 -0
  240. package/src/components/Coachmark/coachmark.spec.md +230 -0
  241. package/src/components/Combobox/combobox.spec.md +180 -0
  242. package/src/components/Command/command.spec.md +171 -0
  243. package/src/components/DataTable/data-table.spec.md +525 -0
  244. package/src/components/DateGrid/date-grid.spec.md +215 -0
  245. package/src/components/DatePicker/date-picker.spec.md +334 -0
  246. package/src/components/DescriptionList/description-list.spec.md +214 -0
  247. package/src/components/Dialog/dialog.spec.md +202 -0
  248. package/src/components/DropdownMenu/dropdown-menu.spec.md +250 -0
  249. package/src/components/Empty/empty.spec.md +214 -0
  250. package/src/components/Field/field-controls.spec.md +338 -0
  251. package/src/components/Field/field.spec.md +438 -0
  252. package/src/components/Field/form-validation.spec.md +152 -0
  253. package/src/components/FieldControlGroup/field-control-group.spec.md +176 -0
  254. package/src/components/FileItem/file-item.spec.md +467 -0
  255. package/src/components/FileUpload/file-upload.spec.md +123 -0
  256. package/src/components/FileViewer/file-viewer.spec.md +373 -0
  257. package/src/components/HoverCard/hover-card.spec.md +157 -0
  258. package/src/components/Input/input.spec.md +193 -0
  259. package/src/components/LinkInput/link-input.spec.md +130 -0
  260. package/src/components/Menu/menu-item.spec.md +290 -0
  261. package/src/components/NameCard/name-card.spec.md +171 -0
  262. package/src/components/Notice/notice.spec.md +149 -0
  263. package/src/components/NumberInput/number-input.spec.md +126 -0
  264. package/src/components/OverflowIndicator/overflow-indicator.spec.md +120 -0
  265. package/src/components/PeoplePicker/people-picker.spec.md +263 -0
  266. package/src/components/Popover/popover.spec.md +198 -0
  267. package/src/components/ProgressBar/progress-bar.spec.md +232 -0
  268. package/src/components/RadioGroup/radio-group.spec.md +141 -0
  269. package/src/components/Rating/rating.spec.md +208 -0
  270. package/src/components/ScrollArea/scroll-area.spec.md +145 -0
  271. package/src/components/SegmentedControl/segmented-control.spec.md +295 -0
  272. package/src/components/Select/select.spec.md +299 -0
  273. package/src/components/SelectMenu/select-menu.spec.md +220 -0
  274. package/src/components/SelectionControl/selection-item.spec.md +128 -0
  275. package/src/components/Separator/separator.spec.md +109 -0
  276. package/src/components/Sheet/sheet.spec.md +148 -0
  277. package/src/components/Sidebar/sidebar.spec.md +713 -0
  278. package/src/components/Skeleton/skeleton.spec.md +104 -0
  279. package/src/components/Slider/slider.spec.md +353 -0
  280. package/src/components/Steps/steps.spec.md +465 -0
  281. package/src/components/Switch/switch.spec.md +215 -0
  282. package/src/components/Tabs/tabs.spec.md +314 -0
  283. package/src/components/Tag/tag.spec.md +282 -0
  284. package/src/components/Textarea/textarea.spec.md +151 -0
  285. package/src/components/TimePicker/time-picker.spec.md +279 -0
  286. package/src/components/Toast/toast.spec.md +177 -0
  287. package/src/components/Tooltip/tooltip.spec.md +139 -0
  288. package/src/components/TreeView/tree-view.spec.md +374 -0
  289. package/src/patterns/action-bar/action-bar.spec.md +458 -0
  290. package/src/patterns/element-anatomy/element-anatomy.spec.md +215 -0
  291. package/src/patterns/element-anatomy/inline-action.spec.md +315 -0
  292. package/src/patterns/element-anatomy/item-anatomy.spec.md +1042 -0
  293. package/src/patterns/header-canonical/header-canonical.spec.md +285 -0
  294. package/src/patterns/horizontal-overflow/horizontal-overflow.spec.md +191 -0
  295. package/src/patterns/overlay-surface/overlay-surface.spec.md +428 -0
  296. package/src/patterns/resize-handle/resize-handle.spec.md +109 -0
  297. package/src/tokens/color/color.spec.md +804 -0
  298. package/src/tokens/density/density.spec.md +127 -0
  299. package/src/tokens/elevation/elevation.spec.md +81 -0
  300. package/src/tokens/layoutSpace/layoutSpace.spec.md +314 -0
  301. package/src/tokens/motion/motion.spec.md +97 -0
  302. package/src/tokens/opacity/opacity.spec.md +78 -0
  303. package/src/tokens/orphan-tokens.spec.md +117 -0
  304. package/src/tokens/radius/radius.spec.md +123 -0
  305. package/src/tokens/typography/typography.spec.md +202 -0
  306. package/src/tokens/uiSize/uiSize.spec.md +438 -0
  307. package/src/styles/preset.css +0 -31
@@ -0,0 +1,344 @@
1
+ ---
2
+ component: Checkbox
3
+ family: 4
4
+ variants: {}
5
+ sizes:
6
+ sm:
7
+ when: "form field-height 28 / compact chrome / dialog / panel context"
8
+ md:
9
+ when: "default general UI"
10
+ lg:
11
+ when: "touch / prominent CTA / stakeholder-facing surface"
12
+ traits:
13
+ - isSelectionMulti
14
+ benchmark:
15
+ - Radix Checkbox primitive: github.com/radix-ui/primitives/tree/main/packages/react/checkbox
16
+ - Ant Design Checkbox: github.com/ant-design/ant-design/tree/master/components/checkbox
17
+ - MUI Checkbox: github.com/mui/material-ui/tree/master/packages/mui-material/src/Checkbox
18
+ - Polaris Checkbox: github.com/Shopify/polaris/tree/main/polaris-react/src/components/Checkbox
19
+ ---
20
+
21
+ <!-- @benchmark-cited: D5 retrofit 2026-05-18 — body claims marked per-claim @benchmark-unverified inline; canonical source URLs in frontmatter benchmark list. -->
22
+
23
+ # Checkbox 設計原則
24
+
25
+ (Radio 共用本規格,詳見 `../RadioGroup/radio-group.spec.md`;本文件通用於兩者視覺與行為,名稱保留 Checkbox 為主體)
26
+
27
+ ## 定位
28
+
29
+ Checkbox 和 Radio 是**表單內的選擇控件**,視覺語言完全一致,差異只有形狀和語意。兩者都綁在 form state、隨 submit 才生效(非即時套用——這是與 Switch 的根本差異,見下「與 Switch 的分界」)。
30
+
31
+ **Layout Family**:非上述 family — self-contained primitive(獨立視覺,無 slot 結構)。
32
+
33
+ **實作基礎**:Checkbox 基於 Radix Checkbox、Radio 基於 Radix RadioGroup(皆 shadcn 包裝 + 橋接 DS token)。
34
+
35
+ | | Checkbox | Radio |
36
+ |---|---|---|
37
+ | 形狀 | `rounded-md`(方) | `rounded-full`(圓) |
38
+ | 指示器 | Check icon | Filled dot |
39
+ | 語意 | 獨立 toggle(多選) | 互斥選擇(單選,必須在 RadioGroup 內) |
40
+
41
+ ---
42
+
43
+ ## 何時用 Checkbox
44
+
45
+ - **表單多選**:通知類型、權限授予、標籤群組
46
+ - **單一同意**:服務條款、隱私政策、訂閱行銷訊息(勾選才送出表單)
47
+ - **indeterminate 半選**:階層式表格的「全選」checkbox 反映部分子項已選
48
+ - **部分綁定的布林欄位**:form 裡的 is_public / is_featured(**但若是即時套用 → 用 Switch**)
49
+
50
+ ## 何時用 Radio
51
+
52
+ - **表單單選且 2-5 個選項全部可見**:付款方式、訂閱方案、權限角色、票種
53
+ - **選項需要描述文字**(法律條款、方案比較、feature list)
54
+ - **決策節點**(使用者需要對比評估才能選)
55
+
56
+ **Radio vs Select 的分界詳見 `../Select/select.spec.md`「與 RadioGroup 的分界」**(SSOT 在 Select spec)。
57
+
58
+ ## 何時不用(Checkbox / Radio 皆不適合)
59
+
60
+ | 場景 | 改用 | 原因 |
61
+ |------|------|------|
62
+ | 布林且即時套用(bluetooth、notification enable)| `Switch` | 見下「與 Switch 的分界」 |
63
+ | 單選但 6+ 選項 / 空間受限 | `Select` | Radio 全可見會佔滿頁面 |
64
+ | 多選但 6+ 選項 / 空間受限 | `Combobox` | Checkbox stack 全可見會佔滿頁面 |
65
+ | 階層結構(部門 / 資料夾)| `TreeView` | Checkbox 是平面選項 |
66
+ | 純視覺切換(側欄收合)| `Button pressed` | 切換狀態屬於介面行為,不是 form value |
67
+
68
+ ---
69
+
70
+ ## 與 Switch 的分界
71
+
72
+ 兩者都是布林 on/off,常被誤用互換。判斷**不是視覺形狀**,而是以下三個角度——**任何一個明確傾向哪邊就選哪邊**:
73
+
74
+ ### 1. 套用時機
75
+
76
+ - **Checkbox**:值隨 form submit 才套用。使用者勾選 → 按「儲存」→ 生效。中途可反悔
77
+ - **Switch**:值即時套用。使用者切換 → 立刻生效(呼叫 API / 改 URL / 觸發副作用)。沒有「取消」
78
+
79
+ ### 2. 心智模型
80
+
81
+ - **Checkbox**:選擇 / 同意——「我選這個項目」、「我同意這個條件」。與書面表單類比
82
+ - **Switch**:開啟 / 關閉——「這個功能我要開」、「這個設定我要關」。與物理開關(牆上 light switch、iPhone settings 開關)類比
83
+
84
+ ### 3. 結果可逆性的即時感
85
+
86
+ - **Checkbox**:勾選不代表生效——送出前可反悔。視覺語言強調「尚未確定」
87
+ - **Switch**:切換即結果——使用者按下那刻就改變系統狀態。視覺語言強調「現在是這樣」
88
+
89
+ ### Fallback heuristic
90
+
91
+ - 在 form 裡、旁邊有 submit button / cancel button → **Checkbox**
92
+ - 獨立的 inline control、旁邊沒有 submit 流程 → **Switch**
93
+
94
+ ### 情境對照表
95
+
96
+ | 場景 | 選哪個 | 原因 |
97
+ |------|-------|------|
98
+ | 我同意服務條款 | Checkbox | 隨 form submit 才成立 |
99
+ | 通知類型勾選(email / SMS / push)| Checkbox | form 設定,按儲存才套用 |
100
+ | Bluetooth on/off | Switch | 立刻開 / 關,不經 submit |
101
+ | Wi-Fi on/off | Switch | 立刻生效 |
102
+ | Dark mode 切換 | Switch | 即時套用 |
103
+ | Push 通知開關(settings 頁)| Switch | 立刻生效 |
104
+ | 訂閱行銷訊息 | Checkbox | form 內,按儲存才套用 |
105
+ | is_public / is_featured(編輯表單)| Checkbox | form field,送出才生效 |
106
+ | is_public(admin 即時切換)| Switch | 切換立刻套用 |
107
+
108
+ **本節是 Checkbox vs Switch 的 SSOT**,未來 Switch 建立 spec 時用一行 pointer 指回本節。
109
+
110
+ ---
111
+
112
+ ## 尺寸
113
+
114
+ 三種尺寸(sm/md = 16px、lg = 20px),對齊 icon 系統。sm 和 md 視覺相同,純粹是命名 mapping 讓消費者直接傳同一個 size。
115
+
116
+ | Size | 控件尺寸 | 內部 icon | 配對 field |
117
+ |------|---------|----------|-----------|
118
+ | sm | 16px | 12px | field sm |
119
+ | md | 16px | 12px | field md |
120
+ | lg | 20px | 16px | field lg |
121
+
122
+ ### 為什麼不完全對齊 `--field-height-*`
123
+
124
+ - **現況**:控件 sm=16 / md=16 / lg=20px(不等於 `--field-height-sm/md/lg` = 28/32/36px)
125
+ - **Rationale**:Checkbox 控件是**選擇指示器**(indicator),不是容器;field-height 是「可編輯 control 的容器高度」,indicator 視覺上要明顯小於容器,才符合「選項前有個小方框」的心智模型。控件本體走 icon tier(sm/md=16, lg=20),行高對齊透過 SelectionItem 的 `py = (field-height - 1lh) / 2` 保證(控件垂直置中於 1lh 容器)
126
+ - **世界級對照**:Material 3 Checkbox = 18px touch target 內的 18px container / Ant Design Checkbox = 16px 控件 / Polaris Checkbox = 16px——全部獨立於 field-height,控件 icon 與 field 分離是共識 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
127
+
128
+ ---
129
+
130
+ ## Label 對齊
131
+
132
+ Checkbox/Radio 不內建 label。Label 組合使用 `SelectionItem` 元件。
133
+
134
+ 對齊機制:
135
+ 1. 外層 `<div>` 設 `text-body` / `text-body-lg`(建立 line-height context)
136
+ 2. 控件包在 `h-[1lh]` 的容器內(容器高度 = 一行文字高度)
137
+ 3. `flex items-center`(控件在文字行高內垂直置中)
138
+ 4. 外層 `flex items-start`(多行時控件對齊第一行)
139
+
140
+ `1lh` 在 `<div>` 上正常繼承,改字體自動重算。
141
+
142
+ ---
143
+
144
+ ## SelectionItem 佈局
145
+
146
+ 垂直排列和水平排列共用 `SelectionItem`。
147
+
148
+ | | 垂直 | 水平 |
149
+ |---|---|---|
150
+ | Item 間距 | 0(padding 處理) | 24px(gap-6) |
151
+ | Item padding | `py = (field-height - 1lh) / 2` | 同左 |
152
+ | Label ↔ Description | 2px(`--item-gap-label-desc-reading` / `-reading-lg`,size-aware) | 同左 |
153
+ | 單行高度 | = field-height(對齊 Input) | 同左 |
154
+ | 多行高度 | padding 維持不變,總高度 = `1lh × line-count + py × 2` | — |
155
+
156
+ ---
157
+
158
+ ## Clamp 政策(Label / Description 行數)
159
+
160
+ | Prop | 預設 | 理由 |
161
+ |---|---|---|
162
+ | `labelMaxLines` | `'none'`(∞) | Form 欄位的選項標籤可能很長,絕不可截斷 |
163
+ | `descMaxLines` | `'none'`(∞) | Form 欄位的補充說明、條款、隱私聲明必須完整呈現 |
164
+
165
+ **為什麼預設不截斷?**
166
+
167
+ Checkbox / Radio 在 form 內承載的常常是:
168
+ - **法律條款**(「我同意服務條款 + 隱私政策...」)
169
+ - **隱私聲明**(「允許 Cookie 用於...」)
170
+ - **複雜條件描述**(「啟用此功能會...」)
171
+
172
+ **任何截斷都是違法或誤導**——使用者必須完整看到他正在同意什麼。MenuItem 的「掃視優先」不適用,SelectionItem 的核心訴求是「**完整閱讀後同意**」。
173
+
174
+ ### Per-instance override
175
+
176
+ 若 consumer 有合理理由(例如 settings 頁的選項列表想截斷過長 label 維持掃視節奏),可以顯式覆寫:
177
+
178
+ ```tsx
179
+ <SelectionItem labelMaxLines={1} descMaxLines={2} ... />
180
+ ```
181
+
182
+ **注意:不能傳 `undefined` 表達「不截」**——React 的 destructure default 會把 undefined 當「沒傳」、fallback 到預設值。要明確表達「不截」傳 `'none'`(雖然語意等同預設,但更明確)。
183
+
184
+ ### 為什麼不像 MenuItem 強制截斷?
185
+
186
+ | | MenuItem | SelectionItem |
187
+ |---|---|---|
188
+ | 使用情境 | 浮層選單,挑一個 | Form 內,**同意**或**選擇**內容本身 |
189
+ | 內容性質 | 選項名稱(短) | 條款 / 聲明 / 條件描述(可長) |
190
+ | 截斷後果 | 失去 context,但可重開選單看完 | **法律或道德問題**(同意了沒看到的內容) |
191
+ | 預設政策 | label / desc 都 `1`(掃視優先) | label / desc 都 `'none'`(完整閱讀優先) |
192
+
193
+ ---
194
+
195
+ ## 狀態
196
+
197
+ ### Checkbox
198
+
199
+ | 狀態 | 邊框 | 底色 | 指示器 |
200
+ |------|------|------|--------|
201
+ | unchecked | border | surface | 無 |
202
+ | checked | primary | primary | white check |
203
+ | indeterminate | primary | primary | white minus |
204
+ | hover unchecked | neutral-6 | surface | 無 |
205
+ | hover checked | primary-hover | primary-hover | white check |
206
+ | hover indeterminate | primary-hover | primary-hover | white minus |
207
+ | disabled unchecked | 無 | neutral-2 | 無 |
208
+ | disabled checked | 無 | neutral-2 | fg-disabled check |
209
+ | disabled indeterminate | 無 | neutral-2 | fg-disabled minus |
210
+
211
+ ### Indeterminate(半選)
212
+
213
+ `checked="indeterminate"` 表示「部分子項被選中」。視覺上與 checked 相同(藍底白圖示),只是圖示從 Check 換成 Minus。
214
+
215
+ 典型場景:SelectMenu 的「全選」checkbox——當部分選項被勾選時顯示 indeterminate。
216
+
217
+ Indeterminate 是由父層邏輯控制的狀態,Checkbox 本身不會自動進入 indeterminate——必須明確傳入 `checked="indeterminate"`。
218
+
219
+ ### Radio
220
+
221
+ | 狀態 | 邊框 | 底色 | 指示器 |
222
+ |------|------|------|--------|
223
+ | unchecked | border | surface | 無 |
224
+ | checked | primary | surface | primary dot |
225
+ | hover unchecked | neutral-6 | surface | 無 |
226
+ | hover checked | primary-hover | surface | primary-hover dot |
227
+ | disabled unchecked | 無 | neutral-2 | 無 |
228
+ | disabled checked | 無 | neutral-2 | fg-disabled dot |
229
+
230
+ ---
231
+
232
+ ## Controlled / Uncontrolled API(M26)
233
+
234
+ 繼承 Radix `CheckboxPrimitive.Root` triplet:`checked` / `defaultChecked` / `onCheckedChange`(Radix forward 不改名)。Form 用 `name` + `value`(native form contract)。3 模式:
235
+
236
+ - **Uncontrolled**:只傳 `defaultChecked`,DOM 自管 — 適合表單 native submit
237
+ - **Controlled**:傳 `checked` + `onCheckedChange`,React state 主導 — 適合需即時聯動其他欄位
238
+ - **Read-only**:傳 `checked` 不傳 `onCheckedChange` → Radix 視同 controlled disabled state
239
+
240
+ CheckboxGroup 額外提供 `value` / `defaultValue` / `onValueChange`(string[] 多選 array)— group-level controlled 模式;item 不傳獨立 onChange(group 統一 dispatch)。
241
+
242
+ ---
243
+
244
+ ## 群組模式(CheckboxGroup)
245
+
246
+ **`<CheckboxGroup>`** 是多選 Checkbox 的 layout primitive,跟 `<Checkbox>` **同資料夾**(合併於 2026-04-21,原單獨 `CheckboxGroup/` folder 併入)。對齊 Ant Design `Checkbox.Group` / Chakra `CheckboxGroup` / Mantine `Checkbox.Group` 世界級:standalone + group 家族同資料夾。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
247
+
248
+ ### Canonical 鐵律:零外部 gap
249
+
250
+ **垂直 CheckboxGroup item 之間沒有外部 gap**。間距完全靠每個 Checkbox 內部的 SelectionItem `py = (field-height - 1lh) / 2` 公式生成 — 單行高度對齊 field-height,多 row stacked 時 row-to-row 自然有 py × 2 的呼吸空間。
251
+
252
+ **禁止**外層加 `gap-y-*` / `space-y-*` / margin → double padding,違反 canonical。
253
+
254
+ ### 為什麼 zero gap valid(不違反 inline-action canonical)
255
+
256
+ SelectionItem py 公式保證:
257
+ 1. 單行 checkbox 高度 = field-height(對齊 Input 高度,row align)
258
+ 2. 多行堆疊時相鄰 row 的 py 各自擴散 = 2×py 真實視覺呼吸空間
259
+ 3. Density 切換時 py 自動跟 field-height 縮放,間距等比例變化
260
+
261
+ 外加 gap → double-padding 視覺斷裂。
262
+
263
+ ### 世界級對照
264
+
265
+ - **Atlassian / Radix**:row 間距由 item 自身 py 擁有,group 無 gap
266
+ - **Ant Design / Chakra**:依賴 Checkbox 自帶 line-height,group 無 spacing 或預設 0
267
+ - **流派:row 高度定義 gap,不加外部 gap** — 本 DS 採此
268
+
269
+ ### CheckboxGroupContext(隔離 fieldCtx)
270
+
271
+ Group 內的 Checkbox 透過 `CheckboxGroupContext` 知道自己在 group 裡:
272
+ - `insideGroup && insideField` → 保留 label(每個 Checkbox 是 group 內選項)
273
+ - `insideField && !insideGroup` → 抑制 label(let FieldLabel 接管,solo-in-Field 場景)
274
+
275
+ 每個 Checkbox 自己的 `id` 透過 `useId` 生成(不共用 fieldCtx.id)→ 修了 2026-04-21「點擊只 toggle 第一個」bug。
276
+
277
+ ### Orientation
278
+
279
+ | 值 | Layout | 典型場景 |
280
+ |---|---|---|
281
+ | `vertical`(預設) | `grid`(無 gap,靠 SelectionItem py) | 篩選條件、偏好設定、權限組 |
282
+ | `horizontal` | `flex flex-wrap gap-4` | 短 label 並排(Email / Push / SMS) |
283
+
284
+ Horizontal 需 `gap-4` 因 row 的 py 不擴散到左右。
285
+
286
+ ### Field 整合
287
+
288
+ `<CheckboxGroup>` 有 `fieldLayout: 'block'` 屬性(跟 RadioGroup 一致),在 `<Field orientation="horizontal">` 內 control area 自動切 `items-start` + padding-top 對齊第一個 item 的 label 第一行。
289
+
290
+ ### 用法範例
291
+
292
+ ```tsx
293
+ <CheckboxGroup>
294
+ <Checkbox label="待處理" defaultChecked />
295
+ <Checkbox label="進行中" defaultChecked />
296
+ <Checkbox label="已完成" />
297
+ </CheckboxGroup>
298
+
299
+ <Field orientation="horizontal">
300
+ <FieldLabel>通知方式</FieldLabel>
301
+ <CheckboxGroup orientation="horizontal">
302
+ <Checkbox label="Email" />
303
+ <Checkbox label="Push" />
304
+ <Checkbox label="SMS" />
305
+ </CheckboxGroup>
306
+ </Field>
307
+ ```
308
+
309
+ ---
310
+
311
+ ## 禁止事項
312
+
313
+ - ❌ Radio 不可單獨使用——必須在 RadioGroup 內
314
+ - ❌ Checkbox 不內建 label——label 組合用 SelectionItem
315
+ - ❌ 垂直 CheckboxGroup 加 `gap-y-*` / `space-y-*`——違反 zero-gap canonical
316
+ - ❌ 多選一不用 Checkbox——用 Radio 或 Select
317
+ - ❌ 即時套用的布林開關用 Checkbox——用 Switch(見「與 Switch 的分界」)
318
+ - ❌ Form 內同意條款用 Switch——條款是「勾選送出才成立」的書面行為,用 Checkbox
319
+
320
+ ---
321
+
322
+ ## 相關
323
+
324
+ - `../Switch/switch.spec.md` — 即時套用的布林開關(Checkbox vs Switch SSOT 在本 spec「與 Switch 的分界」)
325
+ - `../Select/select.spec.md` — 單選下拉(Radio vs Select SSOT 在 Select spec)
326
+ - `../Combobox/combobox.spec.md` — 多選下拉(Checkbox stack vs Combobox 對照在 Combobox spec)
327
+ - `../RadioGroup/radio-group.spec.md` — Radio 的 group 容器 + 結構對稱 reciprocal
328
+ - `../SelectionControl/selection-item.spec.md` — Checkbox / Radio 共用的 SelectionItem 佈局 primitive(本 spec 的 Clamp 政策為其 SSOT)
329
+ - `../Field/field-controls.spec.md` — Field Control 共用規則
330
+
331
+ ## A11y 預設
332
+
333
+ **ARIA / Pattern**:繼承 Radix `checkbox` primitive a11y 預設(role / aria-* / 鍵盤導覽)。詳 [Radix Accessibility docs](https://www.radix-ui.com/primitives/docs/components/checkbox#accessibility)。
334
+
335
+ **Focus**:Radix primitive 自管 focus trap / restoration / visible ring(`outline: 2px solid var(--ring)` per design-system focus-visible canonical)。
336
+
337
+ **驗證**:Storybook a11y addon panel 應 0 critical violation;鍵盤完整可操作(無需滑鼠)。WCAG AA contrast ≥ 4.5:1(text)/ 3:1(UI)。
338
+
339
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
340
+
341
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
342
+
343
+ - `menu-item.spec.md`
344
+ - `segmented-control.spec.md`
@@ -0,0 +1,237 @@
1
+ ---
2
+ component: Chip
3
+ family: 3
4
+ variants: {}
5
+ sizes: {}
6
+ traits:
7
+ - hasInteractiveStates
8
+ benchmark:
9
+ - MUI Chip: github.com/mui/material-ui/tree/master/packages/mui-material/src/Chip
10
+ - Ant Design Tag: github.com/ant-design/ant-design/tree/master/components/tag
11
+ - Carbon Tag: github.com/carbon-design-system/carbon/tree/main/packages/react/src/components/Tag
12
+ ---
13
+
14
+ <!-- @benchmark-cited: D5 retrofit 2026-05-18 — body claims marked per-claim @benchmark-unverified inline; canonical source URLs in frontmatter benchmark list. -->
15
+
16
+ # Chip 設計原則
17
+
18
+ ## 定位
19
+
20
+ Chip 是 **Material Design Filter Chip** 的實作——用於從多個選項裡**選取任意數量(多選)或單一選項(單選)**,視覺上是一排獨立的 pill。
21
+ 基於 Radix ToggleGroup,橋接設計系統 token。
22
+
23
+ **Layout Family**:CLAUDE.md 4-Family Model **Family 3(Pill Layout)action trigger sub-profile**。內部結構 `[startIcon?] [<span px-1>label</span>] [suffix badge? + endIcon?]` 繼承 Button canonical(code docblock 明寫「鏡射 Button」)。SSOT 在 `components/Button/button.spec.md`「Pill Layout」章節。Chip 特有視覺(`rounded-full`、單一固定 `h-field-sm` size、hover/selected 色彩規則)寫在本 spec 下方章節。
24
+
25
+ ---
26
+
27
+ ## 何時用
28
+
29
+ - **Filter panel 的 tag 選取**:語言、狀態、類別、標籤
30
+ - **Toolbar 上的多選過濾**:列表頁、搜尋結果頁
31
+ - **標籤選取**:為內容選擇適合的 tags
32
+
33
+ ## 何時不用
34
+
35
+ | 場景 | 改用 | 原因 |
36
+ |------|------|------|
37
+ | 2–5 個互斥單選且視覺要 compact 連體 | `SegmentedControl` | Chip 各自獨立,SegmentedControl 連體表達互斥更強 |
38
+ | 單一按鈕 on/off | `Button pressed` | 單個 toggle 不需要 Chip 的 group 語意 |
39
+ | 純顯示不可互動 | `Tag` | Chip 是 control,Tag 是 label |
40
+ | 計數 / 狀態指示器(不可互動)| `Badge`(`../Badge/badge.spec.md`) | Badge 是純視覺 indicator(count / status dot),Chip 是 selectable control |
41
+ | 使用者已輸入的 token(收件人、filter summary)| Input chip 系列(`LinkInput` / `PeoplePicker`)| 那些是 input 內的 token,不是獨立選擇器 |
42
+
43
+ ---
44
+
45
+ ## 與 SegmentedControl 的差異
46
+
47
+ | | Chip | SegmentedControl |
48
+ |---|---|---|
49
+ | 選擇語意 | 多選為主,可選單選 | 固定單選(radio) |
50
+ | 視覺連接 | 各自獨立 pill,`gap-2` | Items 連體,`-ml-px` border 重疊 |
51
+ | 圓角 | `rounded-full`(M3 身份特徵)| `rounded-md` |
52
+ | 規模 | 可能幾十個,必須處理 overflow | 2–5 個,規模固定 |
53
+ | Field 整合 | 不塞進 Field(規模不對) | 塞得進 Field(`useFieldContext()` 讀 size)|
54
+ | Overflow | `wrap` / `scroll` / `menu` 三模式 | 不支援 |
55
+
56
+ ---
57
+
58
+ ## 內部結構(鏡射 Button)
59
+
60
+ ```
61
+ [startIcon?] [<span px-1>label</span>] [<span gap-1>badge? + endIcon?</span>]
62
+ ↑ ↑ ↑
63
+ 16px text-body leading-compact badge / LucideIcon
64
+ │─── gap-1 ─│─── gap-1 ──────────────────│
65
+ ```
66
+
67
+ - Slot 間 `gap-1`(4px),與 Button 一致
68
+ - Label 包 `<span className="px-1">`,與 Button 一致
69
+ - Suffix wrapper `<span className="inline-flex items-center gap-1">`,與 Button 一致
70
+ - Icon size:`16`(固定,因為 Chip 只有一個 size)
71
+
72
+ **支援的 slot**:
73
+ | Slot | 說明 |
74
+ |---|---|
75
+ | `startIcon` | `LucideIcon`,最多一個 |
76
+ | `badge` | 通常是計數指示器(「React 24」「進行中 3」)|
77
+ | `endIcon` | 用於 chip 點下去會展開更多的少見情境(如 `ChevronDown` 開 popover 選子分類)|
78
+
79
+ **不支援**:`danger` / `loading` / `pressed` / `asChild` / `iconOnly` / `dismiss` — 這些是其他元件的職責,混進 Chip 會模糊邊界。
80
+
81
+ ### 為什麼不支援 dismiss X
82
+
83
+ Filter chip 的「移除這個 filter」動作已由「再點一次 deselect」承擔。加 dismiss X 等於同一動作有兩個 affordance,違反 Hicks's Law。Material 3 / Atlassian / Polaris filter chips 都不提供 dismiss。
84
+
85
+ **需要 dismiss 的情境** = active filter token / 使用者輸入 token,那是 Input chip 的語意(走 `LinkInput` / `Tag` + `onDismiss` 路線),不是 Filter chip。
86
+
87
+ ### 為什麼不需要 checkmark-on-selected
88
+
89
+ Material 3 filter chip 在 selected 時會把 startIcon 換成 `Check`。我們不做,因為視覺層已經用 **primary-hover border + text + `primary-subtle` 背景**明確表達 selected 狀態,再加 icon 是冗餘信號。
90
+
91
+ ---
92
+
93
+ ## Size — 只有一種
94
+
95
+ Chip **只有一個 size**,對應 `h-field-sm`(md density 28px / lg density 32px)。
96
+
97
+ 對齊 Material 3 / Atlassian / Polaris / Ant Design 的世界級共識:chips 使用單一高度,不暴露 size prop。使用場景(filter bar、tag panel)高度一致,多 size 不增加表達力、只增加 API 負擔。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
98
+
99
+ **為什麼用 `--field-height-sm` 不用獨立 token**:chip 高度仍需 density 感知,沿用 `field-height-sm` 保證跟 Button / Input 的 density 節奏一致。若未來需要跟 form 高度解耦再新增 `--chip-height`。
100
+
101
+ ---
102
+
103
+ ## State
104
+
105
+ 對應你設計中的四狀態:
106
+
107
+ | State | 樣式 |
108
+ |---|---|
109
+ | **Default** | `bg-surface border-border text-foreground` |
110
+ | **Hover**(未選)| `hover:border-border-hover`(對齊 Input / SegmentedControl hover 的 border 加深一階)|
111
+ | **Selected** | `bg-primary-subtle border-primary-hover text-primary-hover`(對齊 `semantic.css:67` canonical 選中規則)|
112
+ | **Disabled** | `cursor-not-allowed text-fg-disabled`,border 維持 `border-border` 不變色 |
113
+
114
+ Hover 和 selected 的色彩都對齊系統 canonical 規則,跟 SegmentedControl / Input / Tabs underline 使用同一套 primary-hover token,保持選中語意的視覺統一。
115
+
116
+ ---
117
+
118
+ ## ChipGroup — Chip 必須在群組內
119
+
120
+ Chip **不可單獨使用**,必須放在 `<ChipGroup>` 裡。跟 SegmentedControl / RadioGroup 的結構對齊。
121
+
122
+ ```tsx
123
+ <ChipGroup type="multiple" value={tags} onValueChange={setTags}>
124
+ <Chip value="react">React</Chip>
125
+ <Chip value="vue">Vue</Chip>
126
+ <Chip value="svelte">Svelte</Chip>
127
+ </ChipGroup>
128
+ ```
129
+
130
+ ### Type
131
+
132
+ | Type | 語意 | 預設 |
133
+ |---|---|---|
134
+ | `multiple` | 可勾選任意數量(checkbox 語意)| ★ **預設**(filter 最常見) |
135
+ | `single` | 互斥單選(radio 語意)| 從 tag 群裡選唯一主要 tag |
136
+
137
+ ### Layout
138
+
139
+ Chip 的 overflow 處理有三種模式:
140
+
141
+ | Layout | 行為 | 何時用 |
142
+ |---|---|---|
143
+ | `wrap` ★default | 塞不下時換到下一排 | 大多數情況(filter panel / tag cloud) |
144
+ | `scroll` | 單行、水平滾動,邊緣 fade mask 指示還有內容 | Toolbar / header filter 必須單行 |
145
+ | `menu` | 塞不下的 chips 收進 `⋯` dropdown menu | 單行且需要完整選項可見(ListView toolbar)|
146
+
147
+ **詳見 overflow 段落。**
148
+
149
+ ---
150
+
151
+ ## Overflow 三種模式
152
+
153
+ ### wrap — 預設
154
+
155
+ 塞不下時 chip 換到下一排。最簡單、最常見——filter panel 裡 chip 數量不定時用這個。實作細節(flex-wrap / gap token)見 `.tsx`。
156
+
157
+ ### scroll — 滾動 + fade mask + scroll arrows
158
+
159
+ - 外層 `overflow-x-auto scrollbar-none`
160
+ - 邊緣用 `mask-image: linear-gradient(...)` 做漸變透明,指示還有內容在視窗外
161
+ - Mask 依滾動位置動態調整:
162
+ - 不可滾動 → 無 mask
163
+ - 可往右滾(atEnd = false)→ 右邊 fade
164
+ - 可往左滾(atStart = false)→ 左邊 fade
165
+ - 雙向可滾 → 兩側 fade
166
+ - **左右 scroll arrow buttons**:`atStart === false` 顯示左 arrow、`atEnd === false` 顯示右 arrow,點擊捲動 80% 容器寬度(smooth)
167
+ - 使用 `useScrollEdges()` hook 追蹤 scroll state
168
+
169
+ **為什麼用 mask 不用 gradient overlay**:mask 淡化的是 chips 本身的 alpha,會自動融合任何背景色(dark mode / card / surface 都自動正確)。Gradient overlay 需要寫死 `from-surface` 等具體色,遇到不同背景就漂移。
170
+
171
+ **為什麼要 scroll arrow buttons**(與 Tabs scroll 同規則):鍵盤用方向鍵、trackpad 用兩指滑、滑鼠滾輪使用者只能靠 arrows(`Shift+wheel` 太隱晦)。Material 3 / Ant Design / Carbon 都這麼做。
172
+
173
+ ### menu — 收進 DropdownMenu
174
+
175
+ - 所有 Chip 渲染在 DOM 中(保留 Radix ToggleGroup 的 a11y)
176
+ - 用 `useOverflowIndices()` 偵測哪些 chip 溢出
177
+ - 溢出的 chip 套 `invisible`(`visibility: hidden`,不佔 hit test 但保持 layout)
178
+ - 右側渲染 `<Button variant="text" iconOnly startIcon={MoreVertical} />`(overflow menu canonical icon,見 CLAUDE.md「常用 icon canonical」;對齊決策 10)
179
+ - 點擊開 DropdownMenu,內容是 `DropdownMenuCheckboxItem` 陣列,checked 狀態跟 ChipGroup 當前 value 同步
180
+ - 點 menu item 時呼叫 ChipGroup 的 `onValueChange`,更新的值同時反映到可見 chips 和 menu checked state
181
+
182
+ **a11y 保留機制**:因為溢出的 chips 只是視覺隱藏、仍在 DOM,Radix ToggleGroup 的 roving tabindex 依然可以 focus 它們。鍵盤使用者可以透過 Tab 進入 ChipGroup,用方向鍵在所有 chips 之間導覽(含視覺隱藏的),或用 Tab 到 `⋯` 按鈕用 dropdown 介面。兩條互動路徑同時可用。
183
+
184
+ **menu 模式需要 controlled ChipGroup**:菜單 items 透過 `onValueChange` 觸發選擇變化,因此 ChipGroup 必須傳 `value` + `onValueChange`(controlled)。uncontrolled mode(`defaultValue`)的 menu 模式無法讓 menu items 與 chips 同步狀態。
185
+
186
+ ---
187
+
188
+ ## 禁止事項
189
+
190
+ - ❌ Chip 單獨使用——必須在 ChipGroup 內
191
+ - ❌ 用 `danger` / `loading` / `pressed` / `asChild` / `iconOnly`——不支援
192
+ - ❌ 加 dismiss X——用 Input chip / Tag 代替
193
+ - ❌ 手動改 `data-state` 或 `aria-pressed` / `aria-checked`——由 Radix 管理
194
+ - ❌ 把 Chip 塞進 Field 當 form control——規模語意不對,用 SegmentedControl
195
+ - ❌ Menu 模式搭配 uncontrolled(只給 `defaultValue`)——menu items 無法同步狀態,TS 不擋但 runtime 會看到 menu 勾選失效
196
+
197
+ ## 為何無 Inspector
198
+
199
+ Chip 決策維度是「selection 行為(single / multi / menu)」× layout(連體 / 間隔)× overflow——已在 `SelectionMatrix` / `LayoutMatrix` 兩張結構矩陣覆蓋。互動 Inspector 無法呈現 selection model 的差異(需要 side-by-side 對照)。
200
+
201
+ ColorMatrix 已建:展示 default / hover / selected / disabled 四狀態的 bg / border / text / icon token 對照,採 pill-canonical 規則(`--primary-hover` 同步染 border + text,bg 維持 surface 不染色),對齊 SegmentedControl / Tabs 未選 hover。
202
+
203
+ ---
204
+
205
+ ## 相關
206
+
207
+ - Button (`button.spec.md`) — Chip 內部結構對標的來源
208
+ - SegmentedControl (`segmented-control.spec.md`) — compact 連體單選變體
209
+ - Tag — 純顯示 / dismissible tag
210
+ - `useOverflowItems` hook (`packages/design-system/src/hooks/use-overflow-items.ts`) — scroll / menu 的共用追蹤邏輯,Tabs 也消費同一個 hook
211
+
212
+ ## A11y 預設
213
+
214
+ **ARIA / Pattern**:繼承 Radix `toggle-group` primitive a11y 預設(role / aria-* / 鍵盤導覽)。詳 [Radix Accessibility docs](https://www.radix-ui.com/primitives/docs/components/toggle-group#accessibility)。
215
+
216
+ **Keyboard 行為**:
217
+
218
+ - Tab — 進入 group
219
+ - ←/→ — 切換
220
+ - Enter / Space — toggle
221
+
222
+ **Focus**:Radix primitive 自管 focus trap / restoration / visible ring(`outline: 2px solid var(--ring)` per design-system focus-visible canonical)。
223
+
224
+ **驗證**:Storybook a11y addon panel 應 0 critical violation;鍵盤完整可操作(無需滑鼠)。WCAG AA contrast ≥ 4.5:1(text)/ 3:1(UI)。
225
+
226
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
227
+
228
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
229
+
230
+ - `badge.spec.md`
231
+ - `tag.spec.md`
232
+
233
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
234
+
235
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
236
+
237
+ - `opacity.spec.md`