@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,214 @@
1
+ ---
2
+ component: DescriptionList
3
+ family: composite
4
+ variants: {}
5
+ sizes: {}
6
+ traits:
7
+ - isStructural
8
+ benchmark:
9
+ - Ant Design Descriptions: github.com/ant-design/ant-design/tree/master/components/descriptions
10
+ - Polaris DescriptionList: github.com/Shopify/polaris/tree/main/polaris-react/src/components/DescriptionList
11
+ ---
12
+
13
+ <!-- @benchmark-cited: D5 retrofit 2026-05-18 — body claims marked per-claim @benchmark-unverified inline; canonical source URLs in frontmatter benchmark list. -->
14
+
15
+ # DescriptionList 設計原則
16
+
17
+ 唯讀 label + value 展示元件,用於呈現結構化的屬性資訊。HTML 語義為 `dl` + `dt` + `dd`,對齊 Atlassian、Shopify Polaris 慣例。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
18
+
19
+ ## 定位
20
+
21
+ - **是**:唯讀資訊展示(profile card 的欄位、detail panel 的屬性列表)
22
+ - **不是**:表單輸入——需要編輯的 label + value 用 Field 系統(Input / Select 等)
23
+
24
+ **Layout Family**:非上述 family — composite / multi-section(多區塊組合,自 own layout)。
25
+
26
+ ---
27
+
28
+ ## 何時用
29
+
30
+ - **Profile / detail panel 的屬性列表**:使用者資料(Email / Phone / Role / Created at)
31
+ - **NameCard 的 info fields**:HoverCard 內的次要資訊展示
32
+ - **固定資訊展示**:產品規格、訂單明細、設定值(唯讀)
33
+ - **HTML 語義為 `dl` + `dt` + `dd`**:對 screen reader 明確表達「屬性-值」關係
34
+
35
+ ## 何時不用
36
+
37
+ | 場景 | 改用 | 原因 |
38
+ |------|------|------|
39
+ | 需要編輯的 label + value | `Field` 系統(`Input` / `Select` / `DatePicker` 等)| DescriptionList 是唯讀,編輯用 Field |
40
+ | Table 式資料展示(多 row 相同結構)| `DataTable` | DescriptionList 是單實體屬性,Table 是多筆同結構 |
41
+ | 單一 label + value(只有一組)| 自訂 layout | DescriptionList 設計為多組屬性;單組殺雞用牛刀 |
42
+ | 需要 cell 編輯的表格 | `DataTable` + inline edit | DescriptionList 無 cell 編輯 |
43
+
44
+ ## 結構
45
+
46
+ - `DescriptionList`:外層 `dl`,vertical 模式為 CSS grid、horizontal 模式為 flex column
47
+ - `DescriptionItem`:一組 `dt`(label)+ `dd`(value),透過 context 知道當前 direction 自動切 layout
48
+
49
+ ## Direction(2026-04-20 新增)
50
+
51
+ | direction | Layout | 典型情境 | 世界級對照 |
52
+ |-----------|--------|---------|-----------|
53
+ | `vertical`(預設)| label 在上 / value 在下 | NameCard detail、sidebar 長 value(地址、bio) | Atlassian DescriptionList、Polaris DescriptionList |
54
+ | `horizontal` | label 左 / value 右對齊 | **file info panel / 訂單詳情 / settings summary**(短 value 的 metadata 列) | Google Drive file info、Notion file panel、iOS Settings | <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
55
+
56
+ **判斷法**:
57
+ - value 預期長(多字、可能換行)→ vertical(讓 value 佔滿寬)
58
+ - value 短(檔名、日期、大小、類型)+ 強調 label↔value 對應 → horizontal
59
+
60
+ ### divided(horizontal 專用)
61
+
62
+ 每個 item 下方加 `border-b border-divider`,rows 之間有視覺格線。**長列表 / key 長度不一**時建議開;短列表(< 4 rows)或單一相似長度 keys 不需要。
63
+
64
+ ```tsx
65
+ // 短 metadata 列,無需 divider
66
+ <DescriptionList direction="horizontal">
67
+ <DescriptionItem label="建立">2026-04-20</DescriptionItem>
68
+ <DescriptionItem label="修改">2026-04-20</DescriptionItem>
69
+ </DescriptionList>
70
+
71
+ // 檔案資訊 — 多 row + key 長度不一 → divided 對齊格線
72
+ <DescriptionList direction="horizontal" divided>
73
+ <DescriptionItem label="檔名">Q1 財報分析.xlsx</DescriptionItem>
74
+ <DescriptionItem label="類型">application/vnd.xlsx</DescriptionItem>
75
+ <DescriptionItem label="大小">1.2 MB</DescriptionItem>
76
+ </DescriptionList>
77
+ ```
78
+
79
+ ## Typography(閱讀模式)
80
+
81
+ 層級靠色彩區分,不靠字體大小:
82
+
83
+ - **label (dt)**:`text-body`(14px)`text-fg-secondary`(neutral-8)
84
+ - **value (dd)**:`text-body`(14px)`text-foreground`(neutral-9)
85
+ - 兩者行高均為 1.5(閱讀模式)
86
+
87
+ ## 間距
88
+
89
+ ### Vertical direction
90
+
91
+ - **label → value**(同 item 內):`--item-gap-label-desc-reading` token(2px)——極小間距,視覺上 label 與 value 緊密配對
92
+ - **items 之間垂直 gap**:`gap-y-[var(--layout-space-tight)]`——density-aware,跟隨系統密度設定
93
+ - **columns 之間水平 gap**:`gap-x-4`(16px)
94
+
95
+ ### Horizontal direction(divided=false)
96
+
97
+ - **items 之間垂直 gap**:`mb-[var(--layout-space-tight)]` per item(last:mb-0)——density-aware,等同 vertical 的 items gap
98
+ - label ↔ value 水平距離:`justify-between` + `gap-4`(最小 16px,content 之間拉開)
99
+
100
+ ### Horizontal direction(divided=true)
101
+
102
+ - 每個 item `py-[var(--layout-space-tight)]`(density-aware,形成 cell-like row 高度)
103
+ - 每個 item 底部 `border-b border-divider`,`last:border-b-0`——row 之間視覺格線,key 長度不一時易於對齊掃描
104
+ - **何時開 divided**:長列表(≥ 4 rows)/ key 長度差異大(短 vs 長 label 並排易顯亂) → divided 可對齊格線;短列表(< 4 rows)且 key 長度相近 → 不需 divided(border 反而噪音)
105
+ - **世界級對照**:Google Drive 詳細資訊面板 / Notion 檔案屬性 / iOS Settings list rows,divided 是 file info / settings 的 canonical 呈現 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
106
+
107
+ ## Props
108
+
109
+ ### `direction`:vertical / horizontal
110
+
111
+ 見上「Direction」段。
112
+
113
+ ### `divided`:horizontal 專用 row divider
114
+
115
+ 見上「divided」段。
116
+
117
+ ### `cols`:grid 欄數(vertical 才生效)
118
+
119
+ | 值 | 用途 |
120
+ |---|---|
121
+ | `1`(預設)| 垂直堆疊,適合窄容器(NameCard、sidebar detail)|
122
+ | `2` | 兩欄並排,適合中等寬度(NameCard info fields)|
123
+ | `3` | 三欄,適合寬容器(detail panel)|
124
+
125
+ Horizontal 模式永遠單欄(label + value 排列就是橫向,不再有欄概念)。
126
+
127
+ ## Section heading 模式(consumer pattern)
128
+
129
+ consumer 要在 DL 上方加 section heading(「基本資料」/「團隊資訊」等)時,**heading → first-item 的 gap 必須等於 item → item 的 gap**(都走 `var(--layout-space-tight)` density-aware token):
130
+
131
+ ```tsx
132
+ <div>
133
+ <div className="text-body font-medium mb-[var(--layout-space-tight)]">基本資料</div>
134
+ <DescriptionList>
135
+ <DescriptionItem label="姓名">Ada Chen</DescriptionItem>
136
+ <DescriptionItem label="Email">ada.chen@example.com</DescriptionItem>
137
+ </DescriptionList>
138
+ </div>
139
+ ```
140
+
141
+ **為什麼相等**(Gestalt proximity canonical):heading 與下方 items 的關係是「擁有 / 歸屬」—— 相同距離讓視覺上 heading 與 items 形成一個群組。若拉大 gap(例 `mb-4`),heading 看似與 items「分離」,失去歸屬感;若縮小 gap(例 `mb-0`),heading 與 items 黏在一起無呼吸。
142
+
143
+ **世界級對照**:iOS Settings / Notion properties / Ant Descriptions / Polaris Card.Section — heading 和 items 之間的 gap 皆與 item-item gap 相等(或近似)。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
144
+
145
+ **Heading typography 建議**:`text-body font-medium text-foreground`(同 item label size,靠 weight 區分層級),不用加粗 / 放大 / 換色——讓 heading 是「標籤」不是「標題」。
146
+
147
+ ---
148
+
149
+ ## vs Field 系統
150
+
151
+ | | DescriptionList | Field |
152
+ |---|---|---|
153
+ | 用途 | 唯讀展示 | 表單輸入(含 read-only mode) |
154
+ | 語義 | `dl/dt/dd` | `label` + input control |
155
+ | 互動 | 無 | 輸入、驗證、提交 |
156
+ | 密度感知 | 垂直 gap 跟隨 layout-space | 高度、padding 跟隨 ui-size |
157
+
158
+ ---
159
+
160
+ ## 禁止事項
161
+
162
+ - ❌ 不要把 DescriptionList 拿來做 Form field label——表單需要編輯的 label + control 對應關係由 `Field`(含 `FieldLabel`)承載;DL 是唯讀 `<dl>` 語意,沒有 `<label for>` 對 input 的綁定
163
+ - ❌ 不要在同一資料卡內混用 Field 和 DescriptionList——同一 section 的 label / value 語意必須一致,否則 screen reader 會讀出混淆的 term/description 對話。要編輯用全 Field,要唯讀全 DL
164
+ - ❌ 不要用 DescriptionList 展示多筆同結構資料(使用者清單、訂單清單)——DL 是單實體屬性列表,多筆用 `DataTable`
165
+ - ❌ 不要在 `<dt>` / `<dd>` 內嵌互動元件(Button / Input)——DL 是 `<dl>` 唯讀語意,塞互動會破壞 SR 敘事流;需要互動改用 Field 或 action row
166
+ - ❌ 不要覆寫 label / value typography token(例改 `<dt>` 成 `text-heading-sm`)——DL 層級靠色彩區分不靠 size,改 size 會破壞「屬性-值」對應感
167
+
168
+ ---
169
+
170
+ ## 無障礙
171
+
172
+ - **語意 HTML**:外層 `<dl>`,每組內 `<dt>` 為 term、`<dd>` 為 description——screen reader 會讀成「term X, description Y」對話,明確表達屬性-值關係
173
+ - **DT / DD 配對**:每個 `<dt>` 必須有對應的 `<dd>`(不可孤立),否則 SR 敘事會中斷;元件內建一組 `DescriptionItem` 強制配對,不分開暴露 `<dt>` / `<dd>` primitive
174
+ - **空值呈現**:value 空時以 `—` 占位(由 consumer 填入或於 DL 內 normalize),`text-fg-muted` 降低視覺重量;SR 會讀出「長破折號」,比空 `<dd>` 更明確
175
+ - **多欄 `cols > 1`**:視覺為 grid 欄位,但 DOM 順序為 item 順序——SR 仍依 DOM 敘事(term1 → desc1 → term2 → desc2),不依視覺欄位;設計時確保 DOM 順序符合語意分組
176
+ - **長值換行**:value 內長字串(URL / ID)以 `break-words` 處理,避免撐破 grid;不強制單行 truncate,長內容保留可讀完整性
177
+ - **列表識別**:預設 `<dl>` 有部分瀏覽器 SR 不視為 list,若需明確 list 語意,DL 根容器可搭配 `role="list"` + `<div role="listitem">`(目前預設不加,保留標準 `<dl>` 語意,consumer 可自行加 role 覆蓋)
178
+
179
+ ---
180
+
181
+ ## 為何無 Inspector / ColorMatrix / SizeMatrix
182
+
183
+ DescriptionList 是**唯讀 label / value 資料呈現**(非互動 / 非 variant 驅動):
184
+
185
+ - **無 Inspector**:DL 的決策維度是 columns(單欄 / 雙欄 / 多欄)已在 `ColsMatrix` 覆蓋。互動 Inspector 無進一步 prop(value 呈現由資料決定,非 prop 切換)。
186
+ - **無 ColorMatrix**:DL 固定 semantic token(label `text-fg-secondary` / value `text-foreground`),無自己的色彩變體,dark mode 由 semantic token 自動切換。加 color variant 不符語意(DL 是資訊展示,非狀態載體)。
187
+ - **無 SizeMatrix**:DL 無 size prop——垂直間距隨 `layout-space` token 感知 density(見「間距」段),但 label / value typography 走 reading mode 固定 tier,不提供 sm / md / lg 變體。不同 density 由 token 自動處理,非 prop 切換。
188
+
189
+ 對應 anatomy story:保留 `Overview` + `ColsMatrix`(元件特有 1 / 2 / auto 欄對照) + `StateBehavior`(空值 `—` / 長值 / 多行)。
190
+
191
+ ---
192
+
193
+ ## 邊界案例
194
+
195
+ - **Disabled(action cell)**:DescriptionList 主體為唯讀資料呈現,本身無 disabled state;若 `<dd>` 內 consumer 嵌入 inline action(Button / Link),該 action 自行 own disabled,DL 不干預(token 走 Button SSOT)。
196
+ - **Loading**:DL 非 async surface,無 loading prop。若 page-level data 載入中,consumer 應在 DL 外層用 `<Skeleton>`(每組 dt/dd 對應一條 skeleton line)取代;DL 本體不渲染 loading state。
197
+ - **Empty(no items / empty value)**:no items → consumer 應 conditional 渲 `<Empty>` 取代 DL,不渲空 `<dl>`(SR 會讀「empty list」造成混淆);individual value 空 → 渲 `—`(em dash,`text-fg-muted`,已在「無障礙」段 codify)。
198
+ - **Dark mode**:走 semantic token(`text-fg-secondary` / `text-foreground`)自動 adapt。
199
+ - **Density**:垂直 gap 隨 `layout-space` token density-aware(見「間距」段),typography fixed reading mode tier 不變。
200
+
201
+ ---
202
+
203
+ ## 相關
204
+
205
+ - `../Field/field.spec.md` — 表單輸入(需要編輯的對應元件)
206
+ - `../DataTable/data-table.spec.md` — 多筆同結構資料(table 對應)
207
+ - `../NameCard/name-card.spec.md` — NameCard info fields 的消費者
208
+ - `../../tokens/layoutSpace/layoutSpace.spec.md` — 垂直 gap 的 density 感知 token
209
+
210
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
211
+
212
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
213
+
214
+ - `item-anatomy.spec.md`
@@ -0,0 +1,202 @@
1
+ ---
2
+ component: Dialog
3
+ family: composite
4
+ variants: {}
5
+ sizes: {}
6
+ traits:
7
+ - isOverlay
8
+ benchmark:
9
+ - Radix Dialog primitive: github.com/radix-ui/primitives/tree/main/packages/react/dialog
10
+ - Ant Design Modal: github.com/ant-design/ant-design/tree/master/components/modal
11
+ - MUI Dialog: github.com/mui/material-ui/tree/master/packages/mui-material/src/Dialog
12
+ - Polaris Modal: github.com/Shopify/polaris/tree/main/polaris-react/src/components/Modal
13
+ ---
14
+
15
+ <!-- @benchmark-cited: D5 retrofit 2026-05-18 — body claims marked per-claim @benchmark-unverified inline; canonical source URLs in frontmatter benchmark list. -->
16
+
17
+ # Dialog 設計原則
18
+
19
+ ## 定位
20
+
21
+ Modal 對話框,基於 Radix Dialog。用於**需要使用者注意力、阻斷背景互動**的操作流程(建立、編輯、確認)。
22
+
23
+ **Layout Family**:非上述 family — composite / multi-section(多區塊組合,自 own layout)。
24
+
25
+ ---
26
+
27
+ ## 何時用
28
+
29
+ - **需要專注的操作流程**:建立 / 編輯複雜表單、多步驟精靈、付款結帳
30
+ - **破壞性動作確認**:刪除、離開不儲存、登出多個裝置
31
+ - **短暫但重要的資訊**:首次引導、重要公告必須被看到才能繼續
32
+ - **需要阻斷背景互動的脈絡**:使用者必須完成或取消此流程才能回到頁面
33
+
34
+ ## 何時不用
35
+
36
+ | 場景 | 改用 | 原因 |
37
+ |------|------|------|
38
+ | 短暫的操作回饋(成功 / 失敗訊息)| `Toast` | Dialog 會阻斷流程,Toast 非阻斷 |
39
+ | 持久的頁面內通知 | `Alert` | Alert 是 inline 嵌入,不浮起 |
40
+ | 側邊操作面板(不需完全阻斷)| `Sheet` | Sheet 從側邊滑入,視覺更輕、常搭配列表 detail |
41
+ | 浮動的精簡選單 | `DropdownMenu` / `Popover` | Dialog 是 modal,DropdownMenu/Popover 是輕量浮層 |
42
+ | Hover 才出現的輔助資訊 | `Tooltip` / `HoverCard` | Dialog 需要明確觸發,hover 不該是 modal 觸發 |
43
+ | 手機全屏編輯 | `Sheet` (bottom / fullscreen) | Dialog 預設 viewport inset,行動裝置用 Sheet 更自然 |
44
+
45
+ ---
46
+
47
+ ## 結構
48
+
49
+ ```
50
+ DialogContent (fixed, centered)
51
+ ├── DialogHeader (SurfaceHeader + Close X)
52
+ │ ├── DialogTitle
53
+ │ └── Close button (<Button iconOnly dismiss size="sm" startIcon={X} />)
54
+ ├── DialogBody (flex-1 ScrollArea wrap + inner padding div,pb-bottom)
55
+ └── DialogFooter (SurfaceFooter alias)
56
+ └── Action buttons
57
+ ```
58
+
59
+ **Padding SSOT**:Header / Body / Footer 的 padding + 分隔線由 `patterns/overlay-surface/overlay-surface.spec.md` own——Dialog 與 Popover 共用同一套 primitive,避免 token 漂移。Dialog 特有行為:Header 的 Close 按鈕;Body 用 `<ScrollArea>` wrap(viewport-fill 專用,SSOT 見 overlay-surface.spec.md 「Body overflow canonical」節 + `components/ScrollArea/scroll-area.spec.md`)。
60
+
61
+ ## Density(2026-04-22 v5 校準:繼承 page density,跟 Sheet 對齊)
62
+
63
+ Dialog **繼承 page `data-density`**,不自設密度 attribute。這是 overlay primitive 的 canonical(跟 `components/Sheet/sheet.tsx` 對齊 — Sheet 不自設 density,繼承 page 層級 `html[data-density]`,見 sheet.tsx line 111 canonical)。
64
+
65
+ **歷史備忘**:先前曾設 `data-layout-space="lg"` 給 header/body 寬鬆呼吸,但跟 `--chrome-header-height` canonical 衝突(md page dialog header 期望 48,強設 lg 會變 56)。**已於 2026-04-22 v5 撤回**,Dialog 全盤繼承 page density,header 高度 = `--chrome-header-height` 自動對齊(md=48 / lg=56)。
66
+
67
+ **世界級對照**:
68
+ - Polaris Modal:px 16(= md loose)
69
+ - Material M3 Dialog:px 24(= lg loose)
70
+ - Atlassian Dialog:px 24
71
+ - 我方:跟隨 page density,md=16 / lg=24,兩端都在世界級 range 內。
72
+
73
+ ## Layout
74
+
75
+ - **水平 padding**:`px-[var(--layout-space-loose)]`(header / body / footer 統一)
76
+ - **Header / Footer 垂直 padding**:`py-[var(--layout-space-tight)]`
77
+ - **Body 垂直 padding**:`pt-[var(--layout-space-tight)]` + `pb-[var(--layout-space-bottom)]`——底部留較大空間,視覺上不壓迫
78
+
79
+ ## Viewport Inset
80
+
81
+ Modal 與 viewport 四邊保持 `--layout-space-bottom`(48px)最小間距。maxWidth 也受此限制:`min(maxWidth, 100vw - inset*2)`。
82
+
83
+ ## 高度行為
84
+
85
+ | 模式 | 條件 | 行為 |
86
+ |---|---|---|
87
+ | **預設(填滿)** | 不傳 `autoHeight` | `height = 100vh - inset*2`,body 捲動。防止動態內容(載入資料、展開 section)造成 dialog 跳動 |
88
+ | **autoHeight** | `autoHeight={true}` | 高度隨內容,超過 viewport 時 `max-height` 安全帽。適合內容量已知且穩定的 dialog(確認框、短表單) |
89
+
90
+ ## maxWidth
91
+
92
+ 預設 512px,consumer 可透過 `maxWidth` prop 調整。型別 `string | number`(傳 number 視為 px)。
93
+
94
+ ## 關閉按鈕
95
+
96
+ > **跨家族 SSOT pointer**:DialogHeader 屬 **Padding-based overlay header 家族**;border / padding / dismiss size / withTabs(tabs 進 header 時 border auto-suppress)的跨家族視覺契約 SSOT 詳 `patterns/header-canonical/header-canonical.spec.md`。本節僅 codify Dialog 特有 close X size + chrome-unbounded rationale。
97
+
98
+ 永遠存在於 DialogHeader 右側。使用 `<Button data-dismiss iconOnly dismiss size="sm" startIcon={X} aria-label="關閉" />`,不可移除——使用者永遠需要明確的關閉手段。
99
+
100
+ **Size canonical(v5 chrome-unbounded)**:Button native size **sm**(28 md / 32 lg),touch target 亦同。SurfaceHeader 的 `[data-unbounded]` CSS rule 自動對 text variant / dismiss 套負 my `calc((xs-sm)/2)` → **layout 佔位 = 24**(xs 固定)。效果:
101
+ - Header 只有 title + close X → max layout = 24 → header = 24 + 2×tight = **48 md / 56 lg = `--chrome-header-height`** ✓
102
+ - Header 塞 bounded primary(無 `data-unbounded`)→ header 自然長高
103
+
104
+ **Canonical 來源**:Dialog 是 overlay chrome,corner close X 屬 action group region,必用 Button(非 Inline Action / 非自刻 button)。詳見 `patterns/element-anatomy/item-anatomy.spec.md`「Dismiss canonical」+ `patterns/overlay-surface/overlay-surface.spec.md`「Chrome dismiss size canonical」。
105
+
106
+ ## Title
107
+
108
+ `text-body-lg font-medium truncate`——單行截斷,不換行。
109
+
110
+ **Header 可成長**:Dialog 提供 `<DialogDescription>` primitive 作副標/補充說明(`mt-[var(--item-gap-label-desc-reading-lg)] text-body text-fg-secondary` — title body-lg 16 + desc body 14 → reading-lg token)。Consumer 傳 title + description 時 header 自然長高(這也是為何 Dialog / Sheet / Popover 的 SurfaceHeader 刻意 **padding-based 而非 fixed-h** — 宣告 chrome 可成長)。詳見 `patterns/overlay-surface/overlay-surface.spec.md`「為什麼 SurfaceHeader 是 padding-based」+ `tokens/uiSize/uiSize.spec.md`「消費 --chrome-header-height 的 2 種實作 pattern」。
111
+
112
+ ## Footer 按鈕
113
+
114
+ 預設 size `md`,與 Field 系統表單元件尺寸一致。按鈕靠右對齊(`justify-end`),間距 `gap-2`。
115
+
116
+ ## 視覺
117
+
118
+ - **Overlay**:`bg-overlay`
119
+ - **Shadow**:`elevation-200`(浮層級)
120
+ - **圓角**:`rounded-lg`
121
+ - **背景**:`bg-surface-raised`
122
+ - **邊框**:`border-border`
123
+ - **分隔線**(header / footer):`border-divider`
124
+
125
+ ## 動畫
126
+
127
+ - 進場:fade-in + zoom-in-95 + slide-in-from-center
128
+ - 離場:fade-out + zoom-out-95 + slide-out-to-center
129
+
130
+ ## 狀態處理的職責邊界
131
+
132
+ Dialog 是容器,無整體 disabled / loading / empty 狀態——這些屬於內容層的責任:
133
+
134
+ | 狀態 | 處理方式 |
135
+ |------|---------|
136
+ | **Loading**(內容載入中) | Consumer 在 `DialogContent` 內渲染 Skeleton / CircularProgress,不是讓 Dialog 本身等待開啟 |
137
+ | **Empty**(如步驟 dialog 還沒資料)| Consumer 在 content 區用 `Empty` primitive |
138
+ | **Error**(操作失敗)| Consumer 在 content 區用 `Alert` |
139
+ | **Disabled**(整個 dialog)| N/A——dialog 要麼開著(可互動)要麼關著(不存在)。要鎖操作請 disable 內部個別 Button / Field |
140
+
141
+ **Dark mode**:由 semantic token(`bg-surface-raised` / `border-border`)自動切換,無自訂 palette。
142
+
143
+ **Density**:Dialog **繼承 page density**(v5 校準,跟 Sheet 對齊),見上「Density」段。
144
+
145
+ ---
146
+
147
+ ## 禁止事項
148
+
149
+ - ❌ **不在 Dialog 內 nested Dialog**:modal 疊 modal 會形成焦點陷阱地獄(使用者無法預測 Esc 關哪一層),複雜多步驟流程改用單一 Dialog + 內部步驟切換
150
+ - ❌ **不用 Dialog 顯示非阻斷訊息**:成功 / 失敗的短暫回饋用 Toast;持續性系統狀態用 Alert。Dialog 的阻斷成本過高
151
+ - ❌ **不把長 form wizard 塞 Dialog**:超過 3 步驟或表單高度接近全螢幕的流程改用獨立頁面或 Sheet,Dialog 不適合長時間停留
152
+ - ❌ **不在 Dialog footer 把 primary action 放左側**:CTA 靠右(`justify-end`)是跨平台使用者期待(macOS / Windows / Web 主流皆如此),反向放置會降低可用性
153
+
154
+ ---
155
+
156
+ ## A11y 預設
157
+
158
+ Radix Dialog 自動處理:
159
+
160
+ - **Modal 語意**:`role="dialog"` + `aria-modal="true"`
161
+ - **標題綁定**:`<DialogTitle>` 自動成為 `aria-labelledby` 指向對象,screen reader 開啟時讀出標題
162
+ - **Focus trap**:焦點鎖在 Dialog 內,Tab 循環不逃出
163
+ - **Esc 關閉**:按 Esc 自動關閉
164
+ - **Focus return**:關閉時焦點返回 trigger 元素
165
+ - **Overlay click**:點擊 overlay 關閉(可透過 `onPointerDownOutside` 阻止)
166
+
167
+ Consumer 必須保留 `<DialogTitle>`——即使視覺不顯示,也要用 `VisuallyHidden` 包裹提供給 screen reader。
168
+
169
+ ---
170
+
171
+ ## 為何無 Inspector
172
+
173
+ Dialog 是 modal 浮層元件,關鍵決策維度是 `maxWidth`(400/480/560/720)× `autoHeight` × `destructive` × open/close 行為——已由 `SizeMatrix`(maxWidth 4 檔) / `HeightBehavior`(viewport-fill vs autoHeight) / `DestructiveMatrix` / `StateBehavior`(open / close / ESC / overlay click) 四張矩陣 + `ColorMatrix`(layout + 視覺 token)完整覆蓋。互動 Inspector 切單一 open/close 不如結構性矩陣對照——Dialog 的正確用法是「照情境選 size / 選 autoHeight」,需要 side-by-side 比對決策。
174
+
175
+ 對應 anatomy story:保留 `Overview` + 元件特有 `HeightBehavior` / `DestructiveMatrix` + `SizeMatrix` + `StateBehavior` + `ColorMatrix`。
176
+
177
+ ---
178
+
179
+ ## 相關
180
+
181
+ - `../Sheet/sheet.spec.md` — 側邊滑入的輕量替代(共用 Radix Dialog base)
182
+ - `../Toast/toast.spec.md` — 非阻斷的短暫回饋
183
+ - `../Alert/alert.spec.md` — 頁面內持久通知
184
+ - `../Popover/popover.spec.md` — 輕量浮層(non-modal)
185
+ - `../DropdownMenu/dropdown-menu.spec.md` — 浮動選單
186
+ - `../Tooltip/tooltip.spec.md` — hover 輔助資訊
187
+ - `../../patterns/overlay-surface/overlay-surface.spec.md` — Header / Body / Footer padding SSOT(Dialog + Popover 共用)
188
+
189
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
190
+
191
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
192
+
193
+ - `accordion.spec.md`
194
+ - `coachmark.spec.md`
195
+ - `file-viewer.spec.md`
196
+ - `layoutSpace.spec.md`
197
+
198
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
199
+
200
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
201
+
202
+ - `density.spec.md`
@@ -0,0 +1,250 @@
1
+ ---
2
+ component: DropdownMenu
3
+ family: 1
4
+ variants: {}
5
+ sizes: {}
6
+ traits:
7
+ - hasInteractiveStates
8
+ - isOverlay
9
+ benchmark:
10
+ - Radix DropdownMenu primitive: github.com/radix-ui/primitives/tree/main/packages/react/dropdown-menu
11
+ - Ant Design Dropdown: github.com/ant-design/ant-design/tree/master/components/dropdown
12
+ - Polaris ActionList: github.com/Shopify/polaris/tree/main/polaris-react/src/components/ActionList
13
+ ---
14
+
15
+ # DropdownMenu 設計原則
16
+
17
+ ## 定位
18
+
19
+ DropdownMenu 是按鈕觸發的**動作選單**——使用者從中選擇一個動作並立即執行。
20
+ 基於 Radix DropdownMenu(shadcn 包裝),item 佈局消費 MenuItem primitive。
21
+
22
+ **Layout Family**:CLAUDE.md 4-Family Model **Family 1(Menu item layout)** 消費者。結構繼承 `patterns/element-anatomy/item-anatomy.spec.md`「Menu item layout」章節的 scanning-mode 規格。
23
+
24
+ ### 與 SelectMenu 的區別
25
+
26
+ SelectMenu 是**選值**(選完後值留在 field 裡),DropdownMenu 是**執行**(選完後觸發動作,選單關閉)。判斷標準:「選完之後,畫面上是否需要保留選中狀態?」需要 → SelectMenu;不需要 → DropdownMenu。
27
+
28
+ ---
29
+
30
+ ## 何時用
31
+
32
+ - **次要動作集合**:卡片右上角 `⋮` 三點選單(複製、刪除、分享、匯出)
33
+ - **工具列的溢出動作**:ToolBar 放不下的次要操作集中在 more menu
34
+ - **即時生效的設定 toggle**:顯示 / 隱藏欄位、排序方式、主題切換
35
+ - **需要分群或子選單的動作清單**:export as PDF / CSV / JSON 這類多層結構
36
+
37
+ ## 何時不用
38
+
39
+ | 場景 | 改用 | 原因 |
40
+ |------|------|------|
41
+ | 選值(選項留在 field 裡)| `Select` / `SelectMenu` | DropdownMenu 點完即關閉,不保留選中狀態 |
42
+ | 主要 CTA(儲存、送出)| `Button` | 主要動作應該直接可見,不該隱藏在選單裡 |
43
+ | 切換平行視圖 | `Tabs` / `SegmentedControl` | view 切換應該持續可見,不是 one-shot |
44
+ | 少於 3 個動作 | 直接放 Button | 2 個動作用 menu 是多餘的藏匿 |
45
+ | 複雜表單 / 多步驟流程 | `Dialog` / `Sheet` | menu item 是單次點擊動作,不承載流程 |
46
+
47
+ ---
48
+
49
+ ## 結構
50
+
51
+ ```
52
+ DropdownMenu ← Radix Root,管理開關狀態
53
+ DropdownMenuTrigger ← 觸發按鈕(通常是 Button)
54
+ DropdownMenuContent ← 浮層容器,提供 size context
55
+ DropdownMenuGroup ← 邏輯群組容器(自動分隔相鄰 Group,見下)
56
+ DropdownMenuItem ← 基本動作項目
57
+ DropdownMenuCheckboxItem ← 可勾選的切換項目(如顯示/隱藏欄位)
58
+ DropdownMenuRadioGroup ← 單選群組容器
59
+ DropdownMenuRadioItem ← 單選項目(如排序方式)
60
+ DropdownMenuSub ← 子選單容器
61
+ DropdownMenuSubTrigger ← 子選單觸發項目(自動附加 ChevronRight)
62
+ DropdownMenuSubContent ← 子選單浮層
63
+ DropdownMenuLabel ← 群組標題(不可互動)
64
+ DropdownMenuSeparator ← 明確分隔線(consumer 手動放置)
65
+ DropdownMenuShortcut ← 鍵盤快捷鍵提示(ml-auto 靠右)
66
+ ```
67
+
68
+ ### DropdownMenuGroup 的自動分隔
69
+
70
+ `DropdownMenuGroup` 對齊 `MenuGroup` 的 group separation 設計語言——相鄰的 Group 自動透過 `border-divider` 分隔,**consumer 不需要自己加 `DropdownMenuSeparator`**。
71
+
72
+ **設計語言**(跨 Menu-like 元件統一,SSOT 見 `../../patterns/element-anatomy/item-anatomy.spec.md`「Group auto-separation」):
73
+ - 每個 group 上下各 **8px padding**
74
+ - 相鄰 group 之間用 **border-divider** 分隔
75
+ - 兩個 group 之間視覺 gap = 8(上一 bottom)+ 8(下一 top)= **16px + border**
76
+
77
+ **MenuGroup vs DropdownMenuGroup CSS 實作對照**(視覺結果 100% 等價,差別只是 padding 住在哪層):
78
+
79
+ | | MenuGroup | DropdownMenuGroup |
80
+ |---|---|---|
81
+ | CSS | `py-2 [&+&]:border-t [&+&]:border-divider` | `[&+&]:mt-2 [&+&]:pt-2 [&+&]:border-t [&+&]:border-divider` |
82
+ | 邊界 padding 來源 | 每個 Group 自己的 py-2(Command.List 無 py) | Content 的 py-2(Group 不套 py-2 避免 double) |
83
+ | Group 間 gap | 8 + 8 = 16 + border | 0 + 8 + 8 = 16 + border |
84
+
85
+ **為什麼不直接套 `py-2`**:`DropdownMenuContent` 已有 `py-2` 提供 Content 邊界 padding(Radix 預期行為,移除會影響 trigger focus offset)。若 Group 再套 `py-2` 會 double padding。改用 `mt-2 pt-2` 只加在第二個 Group 起,視覺等價但不 double。
86
+
87
+ 兩種分隔機制的選擇:
88
+ - **用 `DropdownMenuGroup` 包裝同類 items** → 自動分隔(零手動,跟 MenuGroup 理念一致)
89
+ - **用 `DropdownMenuSeparator` 明確插入** → 明確控制分隔位置(如群組內部的子分組、破壞性動作前的強調分隔)
90
+
91
+ ---
92
+
93
+ ## Item 類型
94
+
95
+ | 類型 | 用途 | 選中行為 |
96
+ |---|---|---|
97
+ | **Item** | 執行一次性動作(複製、刪除、開啟連結) | 執行後關閉選單 |
98
+ | **CheckboxItem** | 切換開關狀態(顯示/隱藏欄位) | 勾選/取消,選單保持開啟 |
99
+ | **RadioItem** | 從互斥選項中選一(排序方式) | 選中後關閉選單 |
100
+ | **SubTrigger** | 展開下一層選單 | 不執行動作,展開子選單 |
101
+ | **Label** | 群組標題,提供語義分類 | 不可互動 |
102
+ | **Separator** | 視覺分隔,劃分邏輯群組 | 不可互動 |
103
+
104
+ CheckboxItem 和 RadioItem 雖然涉及「選擇」,但它們控制的是**即時生效的設定**(toggle),不是「選一個值填回 field」。
105
+
106
+ ---
107
+
108
+ ## Item 佈局
109
+
110
+ 遵循 item-layout 設計原則:
111
+
112
+ ```
113
+ [prefix] [label] [suffix]
114
+ ```
115
+
116
+ - prefix:`DropdownMenuItemIcon` 包裹 startIcon,`h-[1lh]` 對齊第一行 label。icon 跟 label 同色(foreground)
117
+ - label:文字內容,`flex-1`
118
+ - suffix:`DropdownMenuShortcut` 或自行組合的後綴容器,`ml-auto` 靠右。指示型 icon 用 `fg-muted`
119
+
120
+ padding 公式:`py = (field-height - 1lh) / 2`,單行時總高度等於同 size 的 Button / Input。
121
+
122
+ ---
123
+
124
+ ## Suffix 模式
125
+
126
+ | Pattern | 內部 gap | 內容 | 用途 |
127
+ |---|---|---|---|
128
+ | **獨立後綴** | `gap-2` (8px) | `[badge?] [endIcon?]` | 狀態指示(未讀數)、導覽提示(ExternalLink) |
129
+ | **子選單指示** | `gap-1` (4px) | `[value?] [badge?] [ChevronRight]` | 展開下一層,value 顯示目前狀態(如 "深色") |
130
+
131
+ SubTrigger 的 ChevronRight 由元件自動渲染,不需手動加。子選單指示中的 value 和 badge 是可選的——讓使用者不用展開就能看到下一層的目前狀態。
132
+
133
+ ---
134
+
135
+ ## 浮層規格
136
+
137
+ 所有 elevation-200 浮層共用同一套視覺規格:
138
+
139
+ | 屬性 | Token |
140
+ |---|---|
141
+ | 背景 | `bg-surface-raised` |
142
+ | 陰影 | `--elevation-200` |
143
+ | 圓角 | `rounded-lg` (8px) |
144
+ | 邊框 | `border border-border` |
145
+ | 間距 | `sideOffset={8}`(見 `../Popover/popover.spec.md` SSOT) |
146
+ | Align | **跟隨 trigger 位置:左 → `start` / 中 → `center` / 右 → `end`**,見 `../Popover/popover.spec.md`「Align 對齊 canonical(跨浮層 SSOT)」|
147
+ | 最小寬度 | 跟隨觸發元件寬度 |
148
+
149
+ SubContent 使用相同規格,包括 sideOffset。
150
+
151
+ ---
152
+
153
+ ## Size
154
+
155
+ 透過 `DropdownMenuContent` 的 `size` prop 設定,經 SizeContext 向下傳遞,所有子項目自動套用。
156
+
157
+ | Size | Label | Icon | Checkbox/Radio 控件 |
158
+ |---|---|---|---|
159
+ | sm | `text-body leading-compact` (14px, 1.3) | 16px | 16px |
160
+ | md | `text-body leading-compact` (14px, 1.3) | 16px | 16px |
161
+ | lg | `text-body-lg leading-compact` (16px, 1.3) | 20px | 20px |
162
+
163
+ DropdownMenu 是掃描模式——使用者快速瀏覽選項,所有尺寸使用 `leading-compact`。
164
+
165
+ ---
166
+
167
+ ## 鍵盤操作
168
+
169
+ 由 Radix DropdownMenu 提供:
170
+
171
+ | 按鍵 | 行為 |
172
+ |---|---|
173
+ | `↑` `↓` | 移動焦點 |
174
+ | `Enter` / `Space` | 執行目前焦點的動作 |
175
+ | `Escape` | 關閉選單(子選單先關子層) |
176
+ | `→` | 展開子選單 |
177
+ | `←` | 收合子選單,焦點回到 SubTrigger |
178
+
179
+ ---
180
+
181
+ ## 破壞性動作
182
+
183
+ 刪除等不可逆動作的 **prefix icon 和 label 都使用 `text-error`**——prefix icon 是 label 的視覺延伸,與 label 同色。Suffix shortcut 維持 `fg-muted`。
184
+
185
+ ---
186
+
187
+ ## 禁止事項
188
+
189
+ - ❌ 不要用 DropdownMenu 做選值——「選一個值填回 field」用 SelectMenu
190
+ - ❌ 不要在 item 內放獨立互動元素(如 Button、Switch)——item 本身就是互動單位
191
+ - ❌ disabled item 不可有 hover 效果
192
+ - ❌ Label 不可被點擊或取得焦點
193
+ - ❌ 不要手動在 SubTrigger 內加 ChevronRight——元件自動渲染
194
+ - ❌ 不要混用 Shortcut 和自訂後綴——同一個 item 只用一種後綴
195
+
196
+ ---
197
+
198
+ ## StateBehavior(DropdownMenu 層級特有)
199
+
200
+ Item-level default / hover / focused / selected / disabled **色彩**由 MenuItem primitive SSOT 擁有(`patterns/element-anatomy/item-anatomy.spec.md`「選擇 / 狀態視覺規則」),在本元件 `ColorMatrix` story 承載並直接引用 MenuItem token。DropdownMenu 的 `StateBehavior` story 展示**浮層層級特有的動態行為**:open / close 動畫(Radix `data-state` 驅動)、Submenu 展開 / 收起、CheckboxItem toggle(多選不 close)——這些是 item primitive 沒有的維度。
201
+
202
+ ---
203
+
204
+ ## 邊界案例
205
+
206
+ - **Disabled trigger**:由 trigger Button 的 `disabled` prop 控,該 Button 自動繼承 disabled token(M24 state precedence);click trigger 不開 menu。
207
+ - **Disabled item**:`<DropdownMenuItem disabled>`(Radix 內建支援),視覺繼承 MenuItem SSOT(`text-fg-disabled` + `aria-disabled=true` + 鍵盤導覽 skip + 不觸發 onSelect)。
208
+ - **Loading(async submenu / async items)**:DropdownMenu primitive 不獨立 own loading prop。async submenu 場景應由 consumer 在 `<DropdownMenuSub>` 內條件性渲 `<DropdownMenuItem disabled>` + spinner label(如「載入中...」);或 fetch options 前先 disable 整個 menu trigger。完整 loading body 替換 pattern 屬 SelectMenu scope,不在 DropdownMenu scope。
209
+ - **Empty(no items / async fetch result empty)**:consumer 應條件性渲 `<DropdownMenuItem disabled>` 顯示「無可用動作」字樣;不渲空 menu。
210
+ - **Dark mode / density**:走 MenuItem + Popover SSOT 自動 adapt;density 預設 lock `md`(M3 portal subtree convention)。
211
+
212
+ ---
213
+
214
+ ## 相關
215
+
216
+ - `../Menu/menu-item.spec.md` — 共用的 MenuItem primitive(prefix 對齊、尺寸、狀態)
217
+ - `../SelectMenu/select-menu.spec.md` — 選值(選完留在 field 裡)的對應元件
218
+ - `../Button/button.spec.md` — 通常作為 DropdownMenuTrigger
219
+ - `../Dialog/dialog.spec.md` — 複雜流程時的改用選擇
220
+
221
+ ## A11y 預設
222
+
223
+ **ARIA / Pattern**:繼承 Radix `dropdown-menu` primitive a11y 預設(role / aria-* / 鍵盤導覽)。詳 [Radix Accessibility docs](https://www.radix-ui.com/primitives/docs/components/dropdown-menu#accessibility)。
224
+
225
+ **Keyboard 行為**:
226
+
227
+ - Tab — focus trigger
228
+ - Enter / Space / ↓ — 開啟
229
+ - ↑/↓ — 導覽 items
230
+ - Enter — 選擇
231
+ - Esc — 關閉
232
+
233
+ **Focus**:Radix primitive 自管 focus trap / restoration / visible ring(`outline: 2px solid var(--ring)` per design-system focus-visible canonical)。
234
+
235
+ **驗證**:Storybook a11y addon panel 應 0 critical violation;鍵盤完整可操作(無需滑鼠)。WCAG AA contrast ≥ 4.5:1(text)/ 3:1(UI)。
236
+
237
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
238
+
239
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
240
+
241
+ - `command.spec.md`
242
+ - `sheet.spec.md`
243
+ - `sidebar.spec.md`
244
+ - `tree-view.spec.md`
245
+
246
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
247
+
248
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
249
+
250
+ - `density.spec.md`