@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,215 @@
1
+ ---
2
+ component: Switch
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
+ - hasSizes
14
+ - hasInteractiveStates
15
+ - isSelectionSingle
16
+ benchmark:
17
+ - Radix Switch primitive: github.com/radix-ui/primitives/tree/main/packages/react/switch
18
+ - MUI Switch: github.com/mui/material-ui/tree/master/packages/mui-material/src/Switch
19
+ - Carbon Toggle: github.com/carbon-design-system/carbon/tree/main/packages/react/src/components/Toggle
20
+ - Ant Design Switch: github.com/ant-design/ant-design/tree/master/components/switch
21
+ ---
22
+
23
+ <!-- @benchmark-cited: D5 retrofit 2026-05-18 — body claims marked per-claim @benchmark-unverified inline; canonical source URLs in frontmatter benchmark list. -->
24
+
25
+ # Switch 設計原則
26
+
27
+ ## 定位
28
+
29
+ Switch 是**即時套用的布林開關**——切換即生效,心智模型是「實體開關」(牆上 light switch、iPhone settings 開關)。
30
+
31
+ **Layout Family**:非上述 family — self-contained primitive(獨立視覺,無 slot 結構)。
32
+
33
+ **實作基礎**:基於 Radix Switch(shadcn 包裝)+ 橋接 DS token。
34
+
35
+ ---
36
+
37
+ ## 何時用
38
+
39
+ - **系統設定類 toggle**:Bluetooth / Wi-Fi / 飛航模式 / Dark mode / Push 通知
40
+ - **即時功能開關**:is_public / is_featured(admin 即時切換)、自動儲存 on/off
41
+ - **獨立 inline control**:切換即生效,旁邊沒有 submit / cancel button 流程
42
+ - **物理開關類比**:使用者心智模型是「我現在要打開 / 關閉這個功能」
43
+
44
+ ## 何時不用
45
+
46
+ | 場景 | 改用 | 原因 |
47
+ |------|------|------|
48
+ | Form 內的布林欄位(隨 submit 生效)| `Checkbox` | 見下「與 Checkbox 的分界」 |
49
+ | 同意條款 / 隱私政策 | `Checkbox` | 條款是「勾選送出才成立」的書面行為,不是物理開關 |
50
+ | 多選(複選多個選項)| `Checkbox` stack | Switch 是單一布林,多選用 Checkbox |
51
+ | 三態或更多(enum)| `RadioGroup` / `SegmentedControl` | Switch 只有 on/off |
52
+ | 有進度的動作(「正在開啟中」)| `Button` with loading state | Switch 是瞬時切換,不承載進度 |
53
+
54
+ ---
55
+
56
+ ## 與 Checkbox 的分界
57
+
58
+ **兩者都是布林 on/off,判斷核心是「套用時機」與「心智模型」**。
59
+
60
+ **完整對照 SSOT 在 `../Checkbox/checkbox.spec.md`「與 Switch 的分界」段落**——Checkbox 是此比較的 owner(包含三個判斷角度 + 9 項情境對照表)。
61
+
62
+ 簡言:
63
+ - **Form 內、有 submit 流程、使用者可反悔** → `Checkbox`
64
+ - **獨立 inline、切換即生效、無 submit** → `Switch`
65
+
66
+ ---
67
+
68
+ ## 結構
69
+
70
+ ```
71
+ Track(pill 形,rounded-full)
72
+ └─ Thumb(白色圓 + 2px border + check icon when ON)
73
+ ```
74
+
75
+ - Track 寬 = 2 × 高(pill 比例)
76
+ - Thumb 直徑 = track 高度
77
+ - ON 狀態 thumb 右滑 `translateX(trackHeight)`
78
+
79
+ ---
80
+
81
+ ## 尺寸
82
+
83
+ | Size | Track | Thumb | 白色圓 | Check icon | 配對 field |
84
+ |------|-------|-------|-------|-----------|-----------|
85
+ | sm / md(預設)| 20 × 40 | 20 | 16 | 12 | field sm / md |
86
+ | lg | 24 × 48 | 24 | 20 | 16 | field lg |
87
+
88
+ sm 和 md 視覺相同(純粹命名 mapping,讓消費者可直接傳同一個 size 對齊 Field family)。
89
+
90
+ ### 為什麼不完全對齊 `--field-height-*`
91
+
92
+ - **現況**:track 高 sm/md=20px / lg=24px(不等於 `--field-height-sm/md/lg` = 28/32/36px);track 寬固定 2× 高(pill 比例);thumb 直徑 = track 高
93
+ - **Rationale**:Switch 是**實體開關類比**(iOS / macOS 系統開關),track 是 pill 形不是 field-like 容器;高度**小於 field-height** 才符合「嵌在一列中的小控件」的語意。放大到 field-height(28/32/36)會破壞 pill 比例(canonical 2:1),視覺語意從 toggle 降級為 generic action button,且失去「可滑動凹槽」的空間 affordance。行高對齊透過 `<Field>` 容器的 `flex items-center` 垂直置中達成 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
94
+ - **世界級對照**:iOS `UISwitch` = 32×20pt(獨立 pill 比例,不跟 form field 成比例)/ Material 3 Switch = 52×32dp / GitHub Primer ToggleSwitch = 40×24——全部 pill 比例 2:1、獨立於 field-height <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
95
+
96
+ ---
97
+
98
+ ## 視覺狀態
99
+
100
+ | 狀態 | Track | Thumb | Check icon |
101
+ |------|-------|-------|-----------|
102
+ | OFF | `bg-border`(neutral-5) | 白色無 border | 無 |
103
+ | ON | `bg-primary` | 白色 + 2px primary border | primary check |
104
+ | Disabled | 套 `opacity-disabled`(整體透明度降級) | 同 ON/OFF | 同 ON/OFF |
105
+ | Readonly | 視覺同一般態 | 但 `pointer-events-none` + `aria-readonly` | — |
106
+
107
+ ### Disabled 用 `opacity`
108
+
109
+ **不用灰階 swap**——這是 Switch 的**特例**,跟 Checkbox / Button / Slider 的灰階策略不同。
110
+
111
+ **理由**:Switch 的 on/off 視覺差異**唯一載體是顏色**(track `bg-primary` vs `bg-border`)——track 和 thumb 在 on/off 之間形狀完全相同,只有顏色變。若用灰階 swap(把 primary 換成 border),disabled 的 ON 跟 OFF 會合併成同一視覺態,使用者無法分辨當前狀態(螢幕閱讀器只能靠 `aria-checked` 區分)。
112
+
113
+ **對照**:
114
+ - Checkbox disabled 可以灰階 swap——checkmark 形狀承載 state,顏色只是裝飾
115
+ - Slider disabled 可以灰階 swap——thumb 位置和 range 長度承載 state
116
+ - Switch disabled **必須保留顏色**——沒有形狀差異,灰階後 state 失傳
117
+
118
+ 詳細對照見 `../Slider/slider.spec.md`「Disabled 策略」節。
119
+
120
+ ### Readonly vs Disabled
121
+
122
+ | | Readonly | Disabled |
123
+ |---|---|---|
124
+ | 視覺 | 正常顏色(可讀) | 降透明度(弱化) |
125
+ | 互動 | 不可切換(pointer-events-none) | 不可切換(cursor-not-allowed) |
126
+ | aria | `aria-readonly` | `disabled` |
127
+ | Tab 焦點 | 不在 tab order | 不在 tab order |
128
+ | 用途 | 表單 readonly 呈現、DataTable cell 非編輯態 | 外部條件造成不可操作 |
129
+
130
+ ---
131
+
132
+ ## label / description 整合
133
+
134
+ Switch 可透過 `label` / `description` props 內部直接渲染緊鄰文字:
135
+
136
+ ```tsx
137
+ <Switch label="啟用通知" description="收到新訊息時提醒" />
138
+ ```
139
+
140
+ 在 `<Field>` context 內時 label / description prop 自動忽略(由 FieldLabel / FieldDescription 接管),避免雙層 label。
141
+
142
+ ### Horizontal Field 自動齊右(2026-04-20)
143
+
144
+ 在 `<Field orientation="horizontal">` 內 Switch 自動 `ml-auto`(control area 是 `flex items-center`,Switch 被推到最右邊),**不需要 consumer 傳 className**。這對齊 iOS Settings / macOS System Settings / GitHub Settings / Figma preferences 的 canonical:**toggle 永遠齊右,label 左對齊、固定寬度**——視覺掃描快、列與列對齊一致。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
145
+
146
+ 視覺上等同於 horizontal `<DescriptionItem>`(label 左 / value 右 `justify-between`)——同一個心智模型:**label 描述、trailing slot 呈現狀態**(value 或 toggle)。
147
+
148
+ **同一畫面多個 horizontal Switch Field → 必搭配 `FieldGroup horizontalLabelWidth={...}`**:否則每個 label 會被內容撐到不同寬度,Switch 左邊緣不對齊,整排參差不齊(世界級 UI 通病,Settings 類型畫面特別明顯)。見 `../Field/field.spec.md`「FieldGroup horizontalLabelWidth cascade」。
149
+
150
+ ### 對齊情境:Settings list vs Form edit(2026-04-20)
151
+
152
+ 世界級對照 Switch 在 horizontal layout 有**兩種**對齊慣例,由 **context 決定**:
153
+
154
+ | Context | 對齊 | 世界級對照 |
155
+ |---------|------|-----------|
156
+ | **Settings list**(獨立每項 row,一項一個偏好,即時生效,無 submit) | **齊右** | macOS System Settings / iOS Settings / GitHub Settings / Linear Settings |
157
+ | **Form edit**(多欄位混合 control,使用者 submit 才生效) | **緊跟 label / 與其他 control 對齊** | Ant Design Form layout=horizontal / Material Form / Polaris Form | <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
158
+
159
+ **判斷法**:這個頁面有 submit button 嗎?
160
+ - **有** → form → Switch 本來就不是 canonical(該用 Checkbox,見上「與 Checkbox 的分界」)—— 若硬要用 Switch 代替 submit-flow Checkbox,需 consumer 明確不 ml-auto。
161
+ - **無** → settings list → **auto ml-auto 齊右 canonical**(本元件 2026-04-20 行為)
162
+
163
+ 本 DS 的 `auto ml-auto` 邏輯是**為 settings list 最佳化**。若 consumer 把 Switch 放 submit form 並想「緊跟 label」,需自行在 `<Switch className="ml-0">` 覆寫——但更推薦重新考慮是不是該用 Checkbox。
164
+
165
+ > **記住**:在 form 內 + Switch 緊跟 label 的覆寫寫法是 **`<Switch className="ml-0" />`**。這是**目前唯一**需要 consumer 明示 override 的 Switch 行為(其他 layout 都 auto)。但 99% 情境使用者應該先問「是不是該用 Checkbox」——Switch 即時生效的心智模型跟 submit form 本來就衝突。
166
+
167
+ ---
168
+
169
+ ## 禁止事項
170
+
171
+ - ❌ 用 Switch 做 form 內的同意 / 勾選——「我同意條款」是書面成立行為,用 Checkbox
172
+ - ❌ 把 Switch 當三態使用(例:「on / off / auto」)——用 RadioGroup / SegmentedControl
173
+ - ❌ 對 disabled 狀態用灰階 swap 而非 opacity——會讓 on/off 視覺無法區分(見「Disabled 用 opacity」段)
174
+ - ❌ Switch 的 on/off 顯示「正在處理中」進度——用 Button + loading state
175
+ - ❌ 直接改動 track 顏色承載額外語意(例如 error 時改紅)——Switch 是單純布林,錯誤訊息放外部 help text
176
+
177
+ ---
178
+
179
+ ## 為何無 Inspector / ColorMatrix
180
+
181
+ - **無 Inspector**:Switch 決策維度只有 `size`(sm / md / lg)× `checked`(ON / OFF)× `disabled` / `readonly`——已由 `SizeMatrix` / `StateBehavior`(四 state + disabled 策略 + readonly) / `LabelIntegration`(Field 整合)三張 story 完整覆蓋。互動 Inspector 切 checked 只是重複 StateBehavior 的 ON / OFF 對照——Switch 是二元元件,互動試玩對教學價值低。
182
+ - **無 ColorMatrix**:Switch 只有一套色彩——ON 用 `bg-primary`(track) + `bg-surface`(thumb),OFF 用 `bg-muted`(track) + `bg-surface`(thumb),無 variant / hue 變體。狀態色完全內嵌在 `StateBehavior` story(ON / OFF / disabled 的 track bg + thumb 綁定)。重寫 ColorMatrix = 複製 StateBehavior 內容。
183
+
184
+ 對應 anatomy story:保留 `Overview` + `SizeMatrix` + `StateBehavior` + 元件特有 `LabelIntegration`(Field 包裝後的 label/description 管理)。
185
+
186
+ ---
187
+
188
+ ## 相關
189
+
190
+ - `../Checkbox/checkbox.spec.md` — **與 Switch 的分界 SSOT owner**(套用時機、心智模型、情境對照)
191
+ - `../Slider/slider.spec.md` — Disabled 策略對照(為什麼 Switch 用 opacity 而 Slider 用灰階)
192
+ - `../Field/field.spec.md` — Switch 作為 Field control 的整合(label/description 由 Field 接管)
193
+ - `../Field/field-controls.spec.md` — Field Control 共用規則
194
+ - `../Button/button.spec.md` — `pressed` 狀態的 toggle button(非單純布林,有 label/icon 的情況改用 pressed Button)
195
+
196
+ ## A11y 預設
197
+
198
+ **ARIA / Pattern**:繼承 Radix `switch` primitive a11y 預設(role / aria-* / 鍵盤導覽)。詳 [Radix Accessibility docs](https://www.radix-ui.com/primitives/docs/components/switch#accessibility)。
199
+
200
+ **Keyboard 行為**:
201
+
202
+ - Tab — focus
203
+ - Space / Enter — toggle on/off
204
+
205
+ **Focus**:Radix primitive 自管 focus trap / restoration / visible ring(`outline: 2px solid var(--ring)` per design-system focus-visible canonical)。
206
+
207
+ **驗證**:Storybook a11y addon panel 應 0 critical violation;鍵盤完整可操作(無需滑鼠)。WCAG AA contrast ≥ 4.5:1(text)/ 3:1(UI)。
208
+
209
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
210
+
211
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
212
+
213
+ - `combobox.spec.md`
214
+ - `radio-group.spec.md`
215
+ - `select.spec.md`
@@ -0,0 +1,314 @@
1
+ ---
2
+ component: Tabs
3
+ family: composite
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
+ - hasSizes
14
+ - hasInteractiveStates
15
+ - isStructural
16
+ benchmark:
17
+ - Radix Tabs primitive: github.com/radix-ui/primitives/tree/main/packages/react/tabs
18
+ - Ant Design Tabs: github.com/ant-design/ant-design/tree/master/components/tabs
19
+ - Carbon Tabs: github.com/carbon-design-system/carbon/tree/main/packages/react/src/components/Tabs
20
+ - Polaris Tabs: github.com/Shopify/polaris/tree/main/polaris-react/src/components/Tabs
21
+ ---
22
+
23
+ <!-- @benchmark-cited: D5 retrofit 2026-05-18 — body claims marked per-claim @benchmark-unverified inline; canonical source URLs in frontmatter benchmark list. -->
24
+
25
+ # Tabs 設計原則
26
+
27
+ ## 定位
28
+
29
+ Tabs 用於在**同一個上下文底下切換平行的視圖**——每個 tab 對應一塊獨立內容區,同時只顯示一塊。
30
+ 基於 shadcn/ui Tabs(Radix Tabs),橋接設計系統 token。
31
+
32
+ **Layout Family**:非上述 family — composite / multi-section(多區塊組合,自 own layout)。
33
+
34
+ ---
35
+
36
+ ## 何時用
37
+
38
+ - **頁面內切換** 同上下文的平行視圖:專案的「總覽 / 成員 / 設定」
39
+ - **Dialog 內切換** 複雜設定:「一般 / 進階 / 整合」
40
+ - **Sidebar 面板內切換** 次分類:團隊、頻道、標籤
41
+ - 每塊 content 可以有自己的 header / toolbar / layout(container 規模的切換)
42
+
43
+ ## 何時不用
44
+
45
+ | 場景 | 改用 | 原因 |
46
+ |------|------|------|
47
+ | 切換的是**整個頁面**(路由層級)| navigation / breadcrumb | Tabs 是同上下文,路由是跨頁 |
48
+ | 只有兩個狀態的開關 | `Switch` / `Button pressed` | 兩態用 toggle 直接,不需要 tab 視覺 |
49
+ | 規模較小的局部內容變體切換 | `SegmentedControl` | compact control 更適合,見下「Tabs 與 SegmentedControl 的分界」 |
50
+
51
+ ---
52
+
53
+ ## Tabs 與 SegmentedControl 的分界
54
+
55
+ 兩者都能「切換下方顯示的內容」,**「切 view vs 切 value」是過度簡化**——SegmentedControl 切表單欄位 / chart 維度 / list 排序都正當。三角度判斷(任何一個明確傾向就選):
56
+
57
+ 1. **規模**:Tabs 切一整塊 container(含自己的 header / toolbar / 多 section,子頁規模);SegmentedControl 切局部變體(單一 chart 維度 / list 排序 / form 條件欄位,單 control 承載量)
58
+ 2. **角色**:Tabs 是 **container 結構元件**(跨父容器寬度、頂部 underline、與 header border 對齊,section 導覽 anchor);SegmentedControl 是 **control 元件**(pill 尺寸、可塞 toolbar / Field / form row、與 Button / Input 並排)
59
+ 3. **生命週期**:Tabs 切換不進表單狀態(頂多 URL hash);SegmentedControl 值常綁 form state / URL param / 持久化
60
+
61
+ **Fallback**:跟 Input / Button / Checkbox 並排不違和 → SegmentedControl;必須佔一整行作 section header → Tabs。
62
+
63
+ ### 常見灰色地帶
64
+
65
+ | 情境 | 選擇 | 理由 |
66
+ |------|------|------|
67
+ | 付款方式(信用卡 / 銀行轉帳 / 現金)+ 下方跟著變欄位 | **SegmentedControl** | 它是 form field,值會送出,視覺上跟其他 form field 並排 |
68
+ | 行事曆 Day / Week / Month 視圖切換 | **SegmentedControl** | Toolbar 尺度,跟日期 picker 並排,選值可綁 URL |
69
+ | 電商後台「訂單 / 顧客 / 產品」 | **Tabs** | 每個 view 有自己的 toolbar、filters、table,規模完全獨立 |
70
+ | Dashboard「本週 / 本月 / 本季」切換 KPI | **SegmentedControl** | 切的是 chart 的時間維度,不是結構 |
71
+ | Dialog 內「一般 / 進階」設定 | **Tabs** | 每個 view 是一整組表單,Tabs 是 dialog 內容的結構切分 |
72
+ | Filter bar「全部 / 進行中 / 已完成」 | **SegmentedControl** | Toolbar 尺度、值會進 URL param、跟其他 filter 並排 |
73
+
74
+ ---
75
+
76
+ ## 內部結構
77
+
78
+ ```
79
+ TabsList ─┬─ TabsTrigger [startIcon?] [label] [suffix?: badge? + endIcon?]
80
+ ├─ TabsTrigger ...
81
+ └─ TabsTrigger ...
82
+ TabsContent ← 對應被選中的 trigger
83
+ ```
84
+
85
+ **單個 Trigger 內部**:
86
+
87
+ ```
88
+ [startIcon?] [label] [suffix?]
89
+ ↑ ↑ ↑
90
+ 16/20px plain span(gap-1): [badge?] [endIcon?]
91
+ span
92
+ │─── gap-2 ────│─── gap-2 ──│
93
+ ```
94
+
95
+ - **Trigger 三層 slot 間 gap-2**(8px),對標 **item-layout pattern** 的橫向 inline 變體
96
+ - **suffix 內 gap-1**(4px),對標 **Button** suffix wrapper(`button.tsx:288`)
97
+ - `startIcon` 描述 tab 的內容性質(人像 icon 配「成員」、齒輪 icon 配「設定」)
98
+ - `badge` 傳達該 tab 底下的待處理計數(「通知 3」「成員 12」)
99
+ - `endIcon` **純視覺 indicator only**(方向 / 狀態 — ChevronDown 暗示「展開後看到子內容」、Pin / Star 狀態徽記)。**不拼 click 行為** — 點到 endIcon 跟點到 tab body 同效果(切 tab)
100
+ - `inlineAction`(2026-05-21 加)拆分 click target:點到 inlineAction 走它自己的 handler 不切 tab;典型如「『更多 ▾』tab 後綴點開 overflow dropdown 不切 tab」(split-click pattern,對齊 GitHub「Code ▾」/ Linear "Triage..." menu / Atlassian split-tab 共識)
101
+
102
+ ### 對標對象與故意的偏離
103
+
104
+ Tabs trigger = **item-layout 橫向變體 + Button 高度系統**。對標 item-layout 的:slot gap-2 / startIcon-label-suffix 三格固定 / suffix 可組合容器。對標 Button 的:固定高度 token(`--tab-height-*`)/ icon size 查表 / suffix wrapper gap-1。
105
+
106
+ 三處刻意偏離 item-layout:
107
+ - **固定高度** `h-[var(--tab-height-*)]` + `items-center`(非 `h-[1lh]`)— Tabs 是 Button 樣的固定容器,非內容撐高 row
108
+ - **無 `<ItemIcon>` / `<ItemLabel>` helper**,直接吃 `LucideIcon` prop + 裸 `<span>` label — slot 固定三格,無複雜 prefix mixing
109
+ - **label 不包 `<span>` padding wrapper**(對比 Button 設計) — selected underline 必須 fit content,label 有橫向 padding 會讓 underline 多 8px 鬆散
110
+
111
+ **漂移歸屬**:row primitive 漂移以 `item-anatomy.spec.md` 為主;inline 高度 / icon size / suffix 結構漂移以 `button.tsx` 為主。
112
+
113
+ ---
114
+
115
+ ## Variant
116
+
117
+ **Tabs 目前只有一種視覺**:底線標示型(underline indicator)。
118
+
119
+ 選中 trigger 底部有 2px 的 `bg-primary` 底線,未選 trigger 僅文字色變化。未來若需要「填色型」或「pill 型」tabs,應先評估是否真的是 Tabs 的語意(通常是 SegmentedControl 或 Button group 的偽裝)再考慮擴充。
120
+
121
+ ---
122
+
123
+ ## Size
124
+
125
+ Tabs 有三種尺寸,**高度由 `--tab-height-*` token 控制**,隨 `data-density` 自動縮放。
126
+
127
+ | Size | md density | lg density | 字體 | 何時用 | 世界級對照 |
128
+ |------|-----------|-----------|------|--------|-----------|
129
+ | `sm` ★ cva default(2026-05-17 從 md 改 sm)| 32 | 40 | `text-body` (14) | **預設 use case**:所有 header 內 tabs(overlay header / chrome header / Dialog / Sidebar / dense toolbar)| Ant Design verbatim:「**small size could be used in Modal**」(`ant.design/components/tabs`)|
130
+ | `md` | 40 | 48 | `text-body` (14) | **Future tier — 目前無 recommended use case**;新 consumer 必先諮詢 DS owner | 多家世界級 DS(Material / MUI / Primer / Polaris)只有 1 個 default size,無中間階梯 | <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
131
+ | `lg` | 48 | 56 | `text-body-lg` (16) | **獨立 tabs 直接取代 chrome header 用**(tab 高度 = `--chrome-header-height` 像素相等,48/56)— page-level workspace 主導覽 | Ant verbatim:「**Large size tabs are usually used in page header**」(`ant.design/components/tabs`)|
132
+
133
+ **Token alignment + size 階梯 rationale SSOT**:`--tab-height-lg` (48/56) = `--chrome-header-height` (48/56) 像素相等 + md future tier + sm default 遷移 — **完整 cross-family canonical 詳** `patterns/header-canonical/header-canonical.spec.md` W3/W5/W6(per Rule-of-3 SSOT 集中此處,本元件 spec.md 不重複論述,只列上表 size table)。
134
+
135
+ ### 為什麼 Tabs 不複用 `--field-height-*`
136
+
137
+ Tabs 是 navigation container,不是 form control。field-height 的 scale(24–36)是為 input / button 設計,套在 tabs 上高度 < 32px 時底線距 baseline < 8px,違反 navigation breathing 最小值。世界級設計系統(Atlassian 32 / Polaris 44 / Material 48)的 tabs 高度都在 32 起跳。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
138
+
139
+ ### 為什麼獨立於 `--table-row-*`
140
+
141
+ 目前 `--tab-height-*` 的數值(32/40/48,lg density 40/48/56)**碰巧與 `--table-row-*` 相同**,但兩者**語意獨立**——tab 是 navigation container,table row 是 tabular data container,未來任何一方需要調整都不應牽動另一方。Token 獨立宣告,不 alias。
142
+
143
+ ---
144
+
145
+ ## Overflow 模式
146
+
147
+ Tabs 支援三種 overflow 策略,透過 `TabsList` 的 `overflow` prop 選擇:
148
+
149
+ | Mode | 行為 | 何時用 |
150
+ |---|---|---|
151
+ | `none` ★default | 不處理,triggers 溢出父容器 | Tabs 數量可控、一定塞得下 |
152
+ | `scroll` | 單行橫向滾動 + 邊緣 fade mask 指示 | 動態 tabs 但不希望中斷視覺順序 |
153
+ | `menu` | 塞不下收進 `⋯` dropdown,所有 triggers 仍在 DOM | 工具列 tabs、需要完整選項可見 |
154
+
155
+ ### scroll 模式
156
+
157
+ 外層 overflow-x scroll(scrollbar 隱藏)+ 邊緣 mask-image gradient 依滾動位置動態 fade(不可滾無 mask / 可右→右 fade / 可左→左 fade / 雙向→兩側)。`useScrollEdges()` hook 追蹤狀態。**Mask 不用 gradient overlay**:mask 淡化內容本身 alpha,自動融合任何背景(dark / card / surface);overlay 需寫死背景色會漂移。
158
+
159
+ **Scroll arrow buttons**(`atStart/atEnd === false` 時顯示 `<ChevronLeft/Right>`,點擊捲 80% 容器寬,smooth scroll):三輸入方式都要顧——鍵盤(Radix 原生方向鍵 + scroll-into-view) / trackpad(兩指橫滑) / 滑鼠滾輪(需 `Shift+wheel`,一般使用者不知道,**必須補 arrow buttons**)。Arrow 容器 `pointer-events-none` + 內層 Button `pointer-events-auto`,不阻擋下方 trigger hit test。對齊 Material 3 / Ant / Carbon / Mantine。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
160
+
161
+ ### menu 模式
162
+
163
+ 所有 TabsTrigger 仍在 DOM(保 Radix roving tabindex),溢出者套 `invisible`(visibility hidden,不接 hit test 但保 layout)。`useOverflowIndices()` 偵測溢出。右側 `<Button variant="text" iconOnly startIcon={MoreVertical} />`(overflow canonical icon)開 DropdownMenu 顯示對應 labels;點 menu item 經 Tabs context `onValueChange` 觸發,Radix 自然更新 `data-state`。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
164
+
165
+ **a11y**:溢出 trigger 只視覺隱藏仍可 focus;鍵盤使用者方向鍵導覽 / Tab 到 ⋯ 用 dropdown,兩路徑並存。對齊 Ant `moreIcon` / Atlassian Navigation Tabs。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
166
+
167
+ ### 跨元件共用
168
+
169
+ `useOverflowIndices` / `useScrollEdges` 在 `packages/design-system/src/hooks/use-overflow-items.ts`,`ChipGroup` 的 `layout="scroll" | "menu"` 消費同一組 hook,確保 Tabs / Chip overflow 行為一致。
170
+
171
+ ---
172
+
173
+ ## 寬度行為
174
+
175
+ **Trigger 寬度永遠由內容決定(hug content)**——Tabs 沒有 `fullWidth` / 等分模式。
176
+
177
+ Tabs 是 **navigation anchor**,不是 compact control:
178
+ - 它在視覺階層上是 section header 等級,用「文字流」的節奏左對齊排列,trigger 間以 `--layout-space-loose` 分隔,接近閱讀動線
179
+ - 「各 segment 同寬」是 SegmentedControl 的身份特徵(對齊 Apple HIG / Material 3 等定義),Tabs 沒有這層視覺契約 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
180
+ - 需要 compact 的等寬互斥切換器 → 用 `SegmentedControl`;需要 section-level 的視圖導覽 → 用 Tabs
181
+
182
+ **Triggers 之間 gap**:使用 `--layout-space-loose`(md density 16px / lg density 24px),與其他「pattern 層級的鬆散留白」共用同一 token。Tabs 的 gap 不是裝飾性空白,而是告訴使用者「每個 tab 是獨立的視圖入口」的視覺分隔。
183
+
184
+ ---
185
+
186
+ ## Underline 與 TabsList border 的視覺關係
187
+
188
+ TabsList 底部有 1px gray border(`border-divider`,neutral-4),selected trigger 有 2px primary-hover 底線。**這兩條線視覺上必須是同一條**——selected 底線從 TabsList 的 gray border 位置「長出來」,不得出現雙線。
189
+
190
+ **原則**:selected 底線必須覆蓋並延伸 TabsList 的 gray border,避免疊線。實作手法(pseudo-element 定位)見 `.tsx`。
191
+
192
+ **色 token = `--divider`(neutral-4)而非 `--border`(neutral-5)**(2026-05-18 改 per user verbatim「我認為應該把 tabs 的下底線統一改成是 divider 色吧?」+「做」approval):
193
+ - 跟 Dialog / Sheet / Popover / Sidebar header `border-b border-divider` 同色 — chrome separator 一致
194
+ - withTabs scenario 下 tabs underline = chrome separator,色不同會視覺斷裂
195
+ - Selected trigger 2px primary indicator overlay underlying 1px divider 對比仍清楚(primary 比 neutral-4 強得多)
196
+ - 對齊 `color.spec.md:706-708` outer-vs-divider 判準的「T-junction seamless」直覺(tabs underline 跟 header separator T 字交接)
197
+
198
+ 在 Dialog / Sidebar header 內特別重要——header 的 `border-b` 和 Tabs 的 `border-b` 必須感知為同一條水平線。
199
+
200
+ ---
201
+
202
+ ## 出現在 Dialog / Sidebar / 任何 header
203
+
204
+ Tabs 常與容器 header 的底邊 border 合併——**視覺上只有一條線**,不是 header border + tabs border 疊兩條。
205
+
206
+ **做法**:Tabs 的 `TabsList` 底部 border 與 header 的 `border-b` 實際上是**同一條線**(設計上重疊、實作上不重複渲染)。**Header 退讓**(移除自己 `border-b`),**Tabs 接管**(自身 `border-b border-divider` per `TABS_LIST_BASE`,2026-05-18 fd843c25 統一 chrome separator 色)。none overflow mode → TabsList block-level full-width 延展;scroll / menu overflow mode → TabsList `inline-flex w-fit`(2026-05-19 c359c711 border owner 升 list 內部 + `overflow-y-hidden` 阻 y auto-promote)。
207
+
208
+ **世界級對照(verbatim cite)**:
209
+ - **GitHub Primer PageHeader**:「`hasBorder` defaults true,**but border NOT rendered if Navigation child contains UnderlineNav**;UnderlineNav itself provides bottom border」(`primer.style/components/page-header/react`)
210
+ - **Ant Design Tabs**:line type 自帶 bottom border(`ant.design/components/tabs`)
211
+ - **Mantine Tabs**:default variant 自包 bottom border(`mantine.dev/core/tabs/`)
212
+ - **Counter-pattern(reject)**:Material UI 走「container 畫 border + tabs 不畫」(`<Box sx={{ borderBottom: 1 }}><Tabs>...</Tabs></Box>` 從 `mui.com/material-ui/react-tabs/`)— 本 DS reject,理由:tabs underline 需 1px gray base line(`tabs.spec.md:185-187`),tabs 不畫 border 會讓 2px primary indicator 浮空失去 base
213
+
214
+ **Auto-suppress 機制(Phase 2 production code 提案)**:header primitive 加 `withTabs?: boolean` prop → true 時自動移除自身 `border-b`,免 consumer 手動忘記。對齊 GitHub Primer 的 auto-suppress 模式(免 consumer 手動 prop)。完整 cross-header canonical 詳 `patterns/header-canonical/header-canonical.spec.md` W1。
215
+
216
+ Size 建議:overlay / chrome header 內用 `sm`(32/40)— 對應 close X 也是 sm,視覺一致;**獨立取代 chrome header** 的 page-level workspace tabs 用 `lg`(48/56,= chrome-header-height)。
217
+
218
+ ---
219
+
220
+ ## 狀態
221
+
222
+ ### active
223
+
224
+ 選中的 trigger:
225
+ - 文字色 `text-foreground`、`font-medium`
226
+ - 底部 2px 底線 `bg-primary-hover`(對齊 semantic.css:選中狀態的邊框/文字統一用 `--primary-hover`)
227
+
228
+ 未選的 trigger:
229
+ - 文字色 `text-fg-secondary`、一般 weight
230
+ - 無底線
231
+ - hover 時文字色轉 `text-foreground`
232
+
233
+ ### disabled
234
+
235
+ - 文字色 `text-fg-disabled`
236
+ - 無 hover 色變化、無底線
237
+ - Cursor 變為 `not-allowed`(滑鼠移過明確告知不可點)
238
+ - 不接受鍵盤 focus
239
+
240
+ ### focus-visible
241
+
242
+ `ring-2 ring-ring ring-offset-1`,與 Button 一致。鍵盤導覽(Radix Tabs 原生支援左右箭頭)由 Radix 處理。
243
+
244
+ ---
245
+
246
+ ## Badge 與 loading 的邊界
247
+
248
+ - **Badge 在 tab 上**傳達「這個 view 底下有待處理」,未選中時仍應顯示(否則使用者不知道該切過去)
249
+ - Tab **沒有 loading 狀態**——載入的是 content 區,不是 tab 本身
250
+ - Disabled tab **不應**同時有 badge(語意矛盾:「有待處理但你不能看」)
251
+
252
+ ### 補充邊界案例
253
+
254
+ - **Empty(no tabs)**:單 tab 已禁用(見「禁止事項」),0 tab 同理 — consumer 應條件性不渲 `<Tabs>`,不渲空 TabsList。
255
+ - **Empty content panel**:tab 切到沒內容的 view 時,content panel 應渲 `<Empty>` 引導 user(對齊 empty 元件的 page-empty pattern)— 由 consumer 決定,Tabs primitive 不獨立處理。
256
+ - **Disabled tab 鍵盤行為**:Radix Tabs 自動 skip disabled tab(`←/→` 不停留),focus 跳到下一個可用 tab。
257
+ - **Dark mode / density**:走 chrome-header / Field 對應 token 自動 adapt;`size` × `variant` matrix 已在 anatomy 完整呈現,density 由 size prop 表達不獨立 own 維度。
258
+
259
+ ---
260
+
261
+ ## 禁止事項
262
+
263
+ - ❌ 一組 Tabs 不得只有一個 trigger——單一 tab 無切換語意,應直接顯示內容
264
+ - ❌ 不得用 Tabs 做表單單選(選 view ≠ 選 value)——改用 SegmentedControl
265
+ - ❌ 不得用 Tabs 做頁面層級導覽(切路由)——改用 navigation
266
+ - ❌ Trigger `startIcon` 不得超過一個
267
+ - ❌ **同一組 Tabs 內 `startIcon` 全有或全無**(2026-05-18 加 per user 抓「圖一 tabs 圖示混用」)——禁止「總覽無 icon / 成員 + 通知 + 設定 有 icon」這種視覺重心散亂的混用。對齊 Material UI Tabs「Tab labels may be either all icons or all text」+ Carbon「Do not mix dismissible tabs without icons with dismissible tabs with icons」。Scope **限縮 `startIcon`** — `endIcon`(badge / chevron-down 等狀態 indicator)可獨立判斷,因屬狀態 affordance 非語意 label icon <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
268
+ - ❌ `endIcon` 不得放動詞性 icon(Download、Trash2)——tab 是視圖切換,不是觸發動作
269
+ - ❌ Dialog / Sidebar header 內不得同時有 header `border-b` 和 TabsList `border-b`——會出現雙線
270
+ - ❌ 不得把 trigger 改成等分 / fullWidth——等寬互斥切換是 SegmentedControl 的身份特徵,Tabs 是 navigation anchor,兩者不同層級。需要等寬改用 SegmentedControl
271
+ - ❌ Trigger 不得使用 `border-b-2` 實作 selected underline——會與 TabsList 的 `border-b` 形成上下雙線;selected underline 必須與 TabsList border 同層渲染(見 `tabs.tsx`)
272
+ - ❌ 不得自行改寫 Radix Tabs 的 `role` / `aria-*` 屬性
273
+
274
+ ---
275
+
276
+ ## 為何無 Inspector
277
+
278
+ Tabs 決策維度是 `size` × `variant` × overflow 模式 × 寬度行為——已由 `SizeMatrix` / `ColorMatrix` / `StateBehavior`(selected / hover / disabled) / 元件特有 `OverflowMatrix`(scroll / menu / fade 三模式) / `SpacingTokens` 五張結構 story 完整覆蓋。
279
+
280
+ 互動 Inspector 切單一 tab 不如 `OverflowMatrix` 的三種 overflow 模式 side-by-side 比較有效——「tabs 放不下時怎麼處理」是設計決策題,需要同時看三個方案。同樣 `SizeMatrix` / `StateBehavior` 是結構性對照,單 tab 互動無法呈現 underline / selected border 與 TabsList border 的視覺關係(見「Underline 與 TabsList border 的視覺關係」段)。
281
+
282
+ 對應 anatomy story:保留 `Overview` + `SizeMatrix` + `ColorMatrix` + `StateBehavior` + 元件特有 `OverflowMatrix` + `SpacingTokens`。
283
+
284
+ ---
285
+
286
+ ## 相關
287
+
288
+ - SegmentedControl(`segmented-control.spec.md`)——切 value 的 radio 群組
289
+ - Button `pressed`(`button.spec.md`)——單一按鈕的 on/off toggle
290
+ - item-layout pattern(`item-anatomy.spec.md`)——gap-2 slot 間距的來源
291
+ - Accordion(`../Accordion/accordion.spec.md`)——多段獨立收合(非互斥切換)
292
+
293
+ ## A11y 預設
294
+
295
+ **ARIA / Pattern**:繼承 Radix `tabs` primitive a11y 預設(role / aria-* / 鍵盤導覽)。詳 [Radix Accessibility docs](https://www.radix-ui.com/primitives/docs/components/tabs#accessibility)。
296
+
297
+ **Keyboard 行為**:
298
+
299
+ - Tab — 進入 TabList
300
+ - ←/→ — 切 tab
301
+ - Home/End — 第一 / 最後 tab
302
+ - Enter / Space — activate
303
+
304
+ **Focus**:Radix primitive 自管 focus trap / restoration / visible ring(`outline: 2px solid var(--ring)` per design-system focus-visible canonical)。
305
+
306
+ **驗證**:Storybook a11y addon panel 應 0 critical violation;鍵盤完整可操作(無需滑鼠)。WCAG AA contrast ≥ 4.5:1(text)/ 3:1(UI)。
307
+
308
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
309
+
310
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
311
+
312
+ - `carousel.spec.md`
313
+ - `sidebar.spec.md`
314
+ - `steps.spec.md`