@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,193 @@
1
+ ---
2
+ component: Input
3
+ family: 4
4
+ variants: {}
5
+ sizes: {}
6
+ traits:
7
+ - hasInteractiveStates
8
+ - isInputLike
9
+ benchmark:
10
+ - Ant Design Input: github.com/ant-design/ant-design/tree/master/components/input
11
+ - MUI TextField: github.com/mui/material-ui/tree/master/packages/mui-material/src/TextField
12
+ - Polaris TextField: github.com/Shopify/polaris/tree/main/polaris-react/src/components/TextField
13
+ - Carbon TextInput: github.com/carbon-design-system/carbon/tree/main/packages/react/src/components/TextInput
14
+ ---
15
+
16
+ <!-- @benchmark-cited: D5 retrofit 2026-05-18 — body claims marked per-claim @benchmark-unverified inline; canonical source URLs in frontmatter benchmark list. -->
17
+
18
+ # Input 設計原則
19
+
20
+ ## 定位
21
+
22
+ Input 是**純文字**的輸入與顯示元件。格式化邏輯為 identity(value → value)——使用者打什麼就存什麼、顯示什麼。
23
+
24
+ 共用規則見 `../Field/field-controls.spec.md`。本文件只記錄 Input 特有的原則。
25
+
26
+ **Layout Family**:CLAUDE.md 4-Family Model **Family 4(Field control layout)** 消費者。結構繼承 `components/Field/field-controls.spec.md` 的 `fieldWrapperStyles + [startIcon?] [<editable>] [endAction?]` 規格,視覺對齊 Family 1(Menu item)讓 SelectMenu trigger + options 連續一致。
27
+
28
+ ---
29
+
30
+ ## 何時用
31
+
32
+ - **純文字資料**:姓名、標題、搜尋字串、slug、ID、隨意 label
33
+ - **email / URL / password** 等特殊但仍屬「文字」的資料(搭配 `type="email" / "url" / "password"` + 適合的 `startIcon`)
34
+ - **格式化邏輯是 identity** 的場景——value → value,不需要千分位、不需要 locale、不需要 picker
35
+ - **單行** 輸入(多行用 Textarea)
36
+
37
+ ## 何時不用
38
+
39
+ | 場景 | 改用 | 原因 |
40
+ |------|------|------|
41
+ | 數字 / 金額 / 百分比 | `NumberInput` | 需要千分位、prefix/suffix、locale、precision |
42
+ | 日期 / 日期時間 | `DatePicker` | 需要原生 picker、`Intl.DateTimeFormat` 顯示 |
43
+ | URL + 預覽 / open in new tab | `LinkInput` | 需要 URL 解析、favicon、外開按鈕 |
44
+ | 多行文字(description、note、備註)| `Textarea` | Input 是單行 |
45
+ | 密碼且需複雜性檢查 | `Input` + 外掛驗證 | Input 本身只負責輸入,驗證是 form 層 |
46
+
47
+ ---
48
+
49
+ ## startIcon 的使用場景
50
+
51
+ startIcon 用於輔助使用者理解「這個 input 是做什麼的」,不是描述 value 的類型。
52
+
53
+ | 適合 | 範例 |
54
+ |------|------|
55
+ | 搜尋 | `Search` |
56
+ | Email | `Mail` |
57
+ | 密碼 | `Lock` |
58
+ | URL | `Globe` |
59
+
60
+ startIcon 不隨 value 變化——它描述的是 input 的用途,不是 value 的狀態。
61
+
62
+ ---
63
+
64
+ ## endAction 的常見模式
65
+
66
+ 使用宣告式 API(`InlineActionConfig`),Field 自動根據 size 渲染:
67
+
68
+ ```tsx
69
+ // 顯示/隱藏密碼
70
+ <Input
71
+ endAction={{ icon: showPwd ? EyeOff : Eye, label: showPwd ? '隱藏密碼' : '顯示密碼', onClick: () => setShowPwd(!showPwd) }}
72
+ />
73
+
74
+ // 清除內容(有值時才顯示)
75
+ <Input
76
+ endAction={query ? { icon: X, label: '清除搜尋', onClick: () => setQuery('') } : undefined}
77
+ />
78
+ ```
79
+
80
+ | 模式 | Icon | 行為 |
81
+ |------|------|------|
82
+ | 顯示/隱藏密碼 | `Eye` / `EyeOff` | toggle `type="password"` ↔ `type="text"` |
83
+ | 清除內容 | `X` | 清空 value,有值時出現、清空後消失 |
84
+
85
+ 清除按鈕消失後不佔位——input 自然擴展。
86
+
87
+ ---
88
+
89
+ ## Display
90
+
91
+ `<Input mode="display">` 是 identity 顯示:
92
+ - 有值:原樣輸出
93
+ - null / undefined / 空字串:`—`(em dash),`text-fg-muted`
94
+
95
+ ---
96
+
97
+ ## Loading
98
+
99
+ `loading?: boolean`(Field SSOT,詳 `Field/field-controls.spec.md` L70-115):右側 endAction 自動顯 `<CircularProgress/>` + `aria-busy="true"`;input 維持可編輯(Ant Input.Search editable 派,反 Material readonly 派,適合 search debounce)。
100
+
101
+ ## 禁止事項
102
+
103
+ - ❌ startIcon 不可隨 value 變化——它描述用途,不是狀態
104
+ - ❌ 不可用 Input 顯示需要格式化的資料(數字、日期、貨幣)——用對應的 Field 元件
105
+
106
+ ---
107
+
108
+ ## 邊界案例
109
+
110
+ - **Disabled**:`disabled` prop 由 Field SSOT own(`Field/field-controls.spec.md` State machine 段)。視覺 token:wrapper bg → `bg-fg-disabled-subtle`、text → `text-fg-disabled`(neutral-6,M24 state>emphasis canonical)、startIcon → `text-fg-disabled`、endAction button 自動 disabled、cursor → `cursor-not-allowed`、border 弱化、無 hover/focus ring。`readOnly` 與 `disabled` 視覺分離:readOnly 維持 default text color(可選取複製)、disabled 全面弱化(不可選)。
111
+ - **Loading**:已 codify(見「Loading」段)。`loading=true` 時 endAction slot 自動切 `<CircularProgress/>`,input 仍可編輯(Ant Search 派 idiom)。
112
+ - **Empty(no value)**:placeholder 走 `text-fg-muted`(neutral-7);`disabled + empty` 時 placeholder 切 `text-fg-disabled`(M24 state precedence)。
113
+ - **Dark mode**:走 semantic token 自動 adapt,無 per-component override。
114
+ - **Density**:`size` 由 Field SSOT(sm/md/lg)決定 height + padding;Input 不獨立 own density。
115
+
116
+ ---
117
+
118
+ ## Mode / Validation / a11y
119
+
120
+ 詳見 `../Field/field-controls.spec.md`(Mode / Validation)+ `../Field/form-validation.spec.md`(驗證時機)。
121
+
122
+ ---
123
+
124
+ ## Variant(visual chrome,正交於 mode)
125
+
126
+ Input 有兩個 visual chrome variant,**獨立於 mode**(mode 是 state,variant 是 chrome look):
127
+
128
+ | Variant | 視覺 | 適用場景 | 世界級對照 |
129
+ |---------|------|---------|-----------|
130
+ | `'default'`(預設) | bg-surface + 明顯 border + hover/focus 回饋 | 表單 / Field 內嵌 / 標準 edit UI | Material Input / Ant Input default |
131
+ | `'bare'` | 透明 chrome,hover / focus 才出現 border;保留 padding / typography / height | **Toolbar inline editing**(FileViewer zoom input / chart config / rich text toolbar number input / Sidebar inline rename) | VS Code settings input / Figma toolbar number / Notion prop input |
132
+
133
+ **判斷法**:Input 放在表單或 Field 內 → `default`;放在 Toolbar chrome 或 page-body inline → `bare`。
134
+
135
+ **`bare` 使用情境的 canonical 要求**:
136
+ - 外層 chrome 必須已提供「這是可編輯」的 affordance(Toolbar 的 icon / prop label / row structure);否則 user 看不到 input chrome 找不到可編輯位置
137
+ - 保留 DS field-height(`h-field-sm/md/lg`)、typography、icon tier、error 視覺——**bare 只動 chrome 不動 sizing**
138
+
139
+ **禁止**:
140
+ - ❌ 在**表單** context 用 `bare`——表單需要明確的 field chrome 邀請輸入,bare 會失去 affordance
141
+ - ❌ 拿 `bare` 來當「空白 div 替代品」——variant 不是拿掉視覺的工具,而是特定 chrome context 的 canonical
142
+
143
+ ---
144
+
145
+ ## Auto-width(AR46,2026-04-21)
146
+
147
+ `autoWidth` prop:Input 寬度自動等於「內容寬(value / placeholder)+ startIcon + endAction + padding」,基於 CSS `field-sizing: content`(Chrome 123+ / Safari 17.4+)。
148
+
149
+ | 屬性 | 行為 |
150
+ |------|------|
151
+ | `autoWidth={false}`(預設)| 走 Field canonical(w-full 或 Field wrapper 規則),寬度固定、跟欄位對齊 |
152
+ | `autoWidth={true}` | wrapper 改 `inline-flex w-auto`;input 改 `field-sizing:content w-auto min-w-0`,寬度隨 value 文字變化 |
153
+
154
+ **使用情境**:
155
+ - **Inline edit**:FileViewer `ZoomInput`(輸入「100%」縮到三位數寬)、Figma toolbar number input、VS Code setting row
156
+ - **Tag / Chip rename**:選中 chip 進入 inline edit,寬度跟 chip 內容保持視覺一致
157
+ - **Spreadsheet-like cells**:內容寬度自動跟字數走
158
+
159
+ **禁止**:
160
+ - ❌ **表單 Field 內**——Field 欄位必須欄寬對齊,寬度隨值跳動會破壞 grid layout
161
+ - ❌ **搭配 `variant="default"` 放在主表單區**——auto-width 預設搭 `variant="bare"`(toolbar inline 語意),default chrome 自動對齊 Field canonical
162
+
163
+ **世界級對照**:VS Code settings inline input 用同 pattern;Notion property field、Airtable cell edit 皆 auto-size。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
164
+
165
+ ---
166
+
167
+ ## 相關
168
+
169
+ - `../NumberInput/number-input.spec.md` — 數值資料
170
+ - `../DatePicker/date-picker.spec.md` — 日期
171
+ - `../LinkInput/link-input.spec.md` — URL + 預覽 / 外開
172
+ - `../Textarea/textarea.spec.md` — 多行文字
173
+ - `../Field/field-controls.spec.md` — Field Control 共用規則(mode / size / endAction / error)
174
+
175
+ ## A11y 預設
176
+
177
+ **ARIA / Pattern**:native `<input>` element 預設 a11y;Field wrapper 補 `aria-labelledby` / `aria-invalid` / `aria-describedby`。
178
+
179
+ **Keyboard 行為**:
180
+
181
+ - Tab — focus
182
+ - 字母鍵 — 輸入
183
+ - Esc — 清空(若 clearable + 有值)
184
+
185
+ **Focus**:native input focus ring;DS focus-visible ring(`focus-visible:!border-primary`)由 Field wrapper 提供。
186
+
187
+ **驗證**:Storybook a11y addon panel 應 0 critical violation;鍵盤完整可操作(無需滑鼠)。WCAG AA contrast ≥ 4.5:1(text)/ 3:1(UI)。
188
+
189
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
190
+
191
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
192
+
193
+ - `time-picker.spec.md`
@@ -0,0 +1,130 @@
1
+ ---
2
+ component: LinkInput
3
+ family: 4
4
+ variants: {}
5
+ sizes: {}
6
+ traits:
7
+ - hasInteractiveStates
8
+ - isInputLike
9
+ benchmark:
10
+ - Ant Design Input: github.com/ant-design/ant-design/tree/master/components/input
11
+ - MUI TextField: github.com/mui/material-ui/tree/master/packages/mui-material/src/TextField
12
+ ---
13
+
14
+ # LinkInput 設計原則
15
+
16
+ ## 定位
17
+
18
+ LinkInput 是 **URL 的**輸入與顯示元件。外觀基於 Input,但 value 以藍色連結樣式呈現,可直接點擊開啟。核心互動差異:**點擊 value 是開啟連結,不是進入編輯**。
19
+
20
+ 共用規則見 `../Field/field-controls.spec.md`。本文件只記錄 LinkInput 特有的原則。
21
+
22
+ **Layout Family**:CLAUDE.md 4-Family Model **Family 4(Field control layout)** 消費者。結構繼承 `components/Field/field-controls.spec.md` 的 `fieldWrapperStyles + [startIcon?] [<editable>] [endAction?]` 規格,視覺對齊 Family 1(Menu item)讓 SelectMenu trigger + options 連續一致。
23
+
24
+ ---
25
+
26
+ ## 何時用
27
+
28
+ - **需要儲存的外部 URL**:網站連結、文件 URL、repo 地址、社群連結
29
+ - **顯示時使用者希望直接點開**:在 readonly / table cell / 設定頁可點擊開啟
30
+ - **需要 URL 格式驗證**(blur 時驗證 protocol + 結構)
31
+
32
+ ## 何時不用
33
+
34
+ | 場景 | 改用 | 原因 |
35
+ |------|------|------|
36
+ | 純字串 slug(`my-project-name`)| `Input` | 不是完整 URL,不需驗證 protocol 與點擊開啟 |
37
+ | Email 地址 | `Input` + `type="email"` | Email 不是 URL,`mailto:` 點擊體驗取決於 OS 設定,非核心需求 |
38
+ | 內部 React Router 路徑 | `Input`(或自訂元件)| Router 路徑不是絕對 URL,LinkInput 的 protocol 驗證會 false reject |
39
+ | Markdown 連結(顯示文字 + URL)| 自訂編輯器 | LinkInput 只處理 URL value,不處理 display text 搭配 |
40
+ | URL 清單(多個 URL)| 多個 LinkInput 或自訂清單元件 | 單一 LinkInput 一次一個 URL |
41
+
42
+ ---
43
+
44
+ ## 兩種顯示狀態(edit mode 內)
45
+
46
+ ### Link 狀態
47
+
48
+ 有合法 URL 且未在編輯中時:
49
+ - value 以 `text-primary` 藍色顯示,hover 加底線,點擊開啟連結
50
+ - 右側 Pencil inline action 觸發編輯模式
51
+ - 點擊 value 是開啟連結,不是編輯——這是 LinkInput 與 Input 的核心互動差異
52
+
53
+ ### Input 狀態
54
+
55
+ 正在編輯、無值、或 URL 格式不合法時:
56
+ - 外觀與 Input 一模一樣(bareInput + placeholder)
57
+ - blur 時驗證格式,合法則自動切回 link 狀態
58
+ - 格式不合法維持 input 狀態 + error 邊框,直到格式正確
59
+
60
+ ---
61
+
62
+ ## 驗證
63
+
64
+ 遵循 Field 共用驗證標準(blur validation):
65
+
66
+ 1. **blur 時驗證**——使用者離開 field 時才檢查格式
67
+ 2. **開始編輯時清除 error**——重新 focus 或開始打字時移除錯誤狀態
68
+ 3. **Enter 觸發 blur**——等同離開 field
69
+ 4. **Escape 取消編輯**——回復原值,不觸發驗證
70
+
71
+ URL 格式要求:必須包含 `http://` 或 `https://` protocol。
72
+
73
+ ---
74
+
75
+ ## 空值
76
+
77
+ 沒有 URL 時直接顯示 placeholder 並允許輸入,不需要先按 Pencil——因為沒有連結可以開。
78
+
79
+ ---
80
+
81
+ ## readonly / disabled
82
+
83
+ 與其他 Field 一致:
84
+ - readonly:顯示藍色連結(可點擊),無 Pencil action
85
+ - disabled:連結灰化,不可點擊
86
+
87
+ ---
88
+
89
+ ## 禁止事項
90
+
91
+ - ❌ 不在 link 狀態下讓點擊 value 進入編輯——點擊連結必須開啟連結
92
+ - ❌ 不在打字過程中即時驗證格式——等 blur
93
+ - ❌ 不省略 protocol(http/https)驗證——裸 domain 不是合法 URL
94
+
95
+ ---
96
+
97
+ ## 為何無 StateBehavior
98
+
99
+ LinkInput 是 **Field Controls family 成員**——互動狀態(focus / invalid / disabled / readonly)完全繼承 `../Field/field-controls.spec.md` SSOT「Mode 狀態」。LinkInput 特有的狀態(edit 輸入 vs display link-chip)已在 `Overview` 中說明。重寫 StateBehavior = 與 field-controls SSOT 漂移。
100
+
101
+ 對應 anatomy story:保留 `Overview` + `Inspector` + `ColorMatrix` + `SizeMatrix`。互動 state 見 Input 的 `StateBehavior` + field-controls.spec.md。
102
+
103
+ ---
104
+
105
+ ## 相關
106
+
107
+ - `../Input/input.spec.md` — 純文字 / slug / email 等非 URL 場景
108
+ - `../Field/field-controls.spec.md` — Field Control 共用規則(mode / size / endAction / error)
109
+ - `../Field/form-validation.spec.md` — blur 驗證標準
110
+
111
+ ## A11y 預設
112
+
113
+ **ARIA / Pattern**:native `<input>` element 預設 a11y;Field wrapper 補 `aria-labelledby` / `aria-invalid` / `aria-describedby`。
114
+
115
+ **Keyboard 行為**:
116
+
117
+ - Tab — focus
118
+ - 字母鍵 — 輸入
119
+ - Esc — 清空(若 clearable + 有值)
120
+
121
+ **Focus**:native input focus ring;DS focus-visible ring(`focus-visible:!border-primary`)由 Field wrapper 提供。
122
+
123
+ **驗證**:Storybook a11y addon panel 應 0 critical violation;鍵盤完整可操作(無需滑鼠)。WCAG AA contrast ≥ 4.5:1(text)/ 3:1(UI)。
124
+
125
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
126
+
127
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
128
+
129
+ - `file-item.spec.md`
130
+ - `textarea.spec.md`
@@ -0,0 +1,290 @@
1
+ ---
2
+ component: MenuItem
3
+ family: 1
4
+ variants: {}
5
+ sizes:
6
+ sm: {}
7
+ md: {}
8
+ lg: {}
9
+ traits:
10
+ - hasInteractiveStates
11
+ - isInternal
12
+ benchmark:
13
+ - Radix Menu primitive: github.com/radix-ui/primitives/tree/main/packages/react/menu
14
+ - Ant Design Menu: github.com/ant-design/ant-design/tree/master/components/menu
15
+ - Polaris ActionList: github.com/Shopify/polaris/tree/main/polaris-react/src/components/ActionList
16
+ ---
17
+
18
+ # MenuItem 設計原則
19
+
20
+ ## 定位
21
+
22
+ MenuItem 是所有 menu 類元件的**共用視覺佈局層**——處理 prefix 對齊、尺寸、狀態。SelectMenu、DropdownMenu、未來的 ContextMenu 等都消費它。它只負責 layout(padding、gap、prefix alignment、typography),互動行為由各 menu 的 Radix primitive 外層控制。
23
+
24
+ **Layout Family**:CLAUDE.md 4-Family Model **Family 1(Menu item layout)** 消費者。結構繼承 `patterns/element-anatomy/item-anatomy.spec.md`「Menu item layout」章節的 scanning-mode 規格。
25
+
26
+ ---
27
+
28
+ ## 結構
29
+
30
+ ```
31
+ prefix content suffix
32
+ [checkbox?] [icon? | avatar?] [label + description?] [tag?]
33
+ ```
34
+
35
+ - **Prefix**:checkbox(多選,由父層注入)+ startIcon 或 avatar(互斥)
36
+ - **Content**:label + 可選 description
37
+ - **Suffix**:tag(ml-auto 靠右)
38
+
39
+ prefix icon 跟 label 同色(foreground),不是 fg-muted。詳見 item-anatomy.spec.md 的 Icon 色彩原則。
40
+
41
+ ---
42
+
43
+ ## Prefix 對齊——24px 閾值
44
+
45
+ 所有 prefix 元素(checkbox、icon、avatar)共享同一個對齊容器。容器高度決定對齊行為:
46
+
47
+ | prefix 最大高度 | 容器 | 對齊目標 |
48
+ |---|---|---|
49
+ | ≤ 24px | `h-[1lh]` | 第一行 label 的垂直中心 |
50
+ | > 24px | `h-[calc(1lh+var(--item-gap-label-desc)+desc_1lh)]` | label + gap + description 文字塊的垂直中心 |
51
+
52
+ **SSOT**:對齊公式封裝於 `patterns/element-anatomy/item-anatomy.tsx` 的 `itemPrefixAlignVariants`(2026-04-23 重構)。MenuItem 消費此 primitive,不自建對齊邏輯;改 gap token(`--item-gap-label-desc`)或 font-size token 一處 → MenuItem 自動同步。
53
+
54
+ **24px 是物理限制**——16px icon 在 24px 圓內仍可辨識(內部 icon 下限 12px),但在更小的容器中 icon 會低於可讀閾值。
55
+
56
+ **無 description 時 prefix 上限 24px**——沒有文字塊可對齊,強制 inline。
57
+
58
+ 多行文字超過參考高度時,外層 `items-start` 讓 prefix Y 不隨文字下移。
59
+
60
+ ---
61
+
62
+ ## startIcon vs avatar
63
+
64
+ | | `startIcon` | `avatar` |
65
+ |---|---|---|
66
+ | 型別 | `LucideIcon` | `AvatarData` |
67
+ | 角色 | **描述**選項的性質(形容詞) | **代表**選項的身份(名詞) |
68
+ | 尺寸 | 16/20px(icon tier,元件控制) | 由 description 決定:無 desc → 20/24/24px,有 desc → 32/32/40px |
69
+ | 對齊 | 永遠 inline(≤ 24px) | 無 desc → inline;有 desc → block |
70
+
71
+ ### avatar 尺寸推導
72
+
73
+ inline(無 description)= 對應 size 的 Tag 高度:
74
+
75
+ | sm | md | lg |
76
+ |---|---|---|
77
+ | 20px | 24px | 24px |
78
+
79
+ block(有 description)= `floor₈(1lh + 2px + desc_1lh)`:
80
+
81
+ | sm | md | lg |
82
+ |---|---|---|
83
+ | 32px | 32px | 40px |
84
+
85
+ ---
86
+
87
+ ## Size
88
+
89
+ 單行高度對齊 field-height token,與 Button、Input 等互動元件等高。
90
+
91
+ | Size | 高度 | Label | Description | Icon | Checkbox |
92
+ |---|---|---|---|---|---|
93
+ | sm | `h-field-sm` | `text-body leading-compact` | `text-caption` | 16px | 16px (sm) |
94
+ | md | `h-field-md` | `text-body leading-compact` | `text-caption` | 16px | 16px (md) |
95
+ | lg | `h-field-lg` | `text-body-lg leading-compact` | `text-body leading-compact` | 20px | 20px (lg) |
96
+
97
+ 所有文字使用 `leading-compact` (1.3)——選單選項是短文字,不需要閱讀行距。
98
+
99
+ description 降一級:sm/md 的 label 14px → description 12px;lg 的 label 16px → description 14px。
100
+
101
+ ---
102
+
103
+ ## Suffix 對齊(實作限制)
104
+
105
+ 依 `item-anatomy.spec.md` 的對齊規則,suffix 應該套用 24px 閾值公式(跟 prefix 同公式但獨立判斷)。但 **MenuItem 的實作把 suffix 寫死成 `h-[1lh]` inline 對齊**——只支援 ≤24px 的小 suffix(Tag、ChevronRight、Badge、計數)。
106
+
107
+ ### 為什麼 hardcode
108
+
109
+ 選單選項的 suffix 99% 是小元素,不會超過 24px。為了避免每個 consumer 都要思考 suffix 對齊規則,MenuItem 直接套用最常見的 inline 對齊。
110
+
111
+ ### 限制
112
+
113
+ 如果你要塞大塊 suffix(thumbnail 40px、stacked badge、multi-line text),**MenuItem 會把它對齊到 label 第一行而不是文字塊中心**,視覺上會跟它修飾的對象失聯。
114
+
115
+ ### 解法
116
+
117
+ 需要大塊 suffix 的場景應該:
118
+
119
+ 1. **重新評估這個東西是不是 menu item**——如果 suffix 是大塊內容,可能需要 ListItem(列表行)而非 menu item
120
+ 2. **包一個 wrapper 元件**——consumer 自己組合 prefix + content + 大塊 suffix,套用 item-anatomy.spec.md 的完整 4-slot 規則
121
+ 3. 不要 hack `endContent` 塞大東西進去——layout 會壞
122
+
123
+ ---
124
+
125
+ ## Clamp 政策(Label / Description 行數)
126
+
127
+ | Prop | 預設 | 理由 |
128
+ |---|---|---|
129
+ | `labelMaxLines` | `1` | 選項是供快速掃視的短文字,必須在一行內辨識完 |
130
+ | `descMaxLines` | `1` | 與 label 對稱,維持掃視節奏;description 是補充說明,不是閱讀內容 |
131
+
132
+ **為什麼 description 也預設 1 行?**
133
+
134
+ Menu 的設計目的是「**快速掃視多個選項挑一個**」。垂直空間是寶貴的——選單通常要塞 5–20 個選項。如果 description 沒有 clamp,一個過長的 description 會把 item 撐高,破壞 row rhythm,使用者眼睛要重新校準。
135
+
136
+ 整個選單應該只有「**兩種 row 高度**」:
137
+ - 無 description → `field-height`(單行 label)
138
+ - 有 description → `field-height` + 2px + 一行 desc 高度
139
+
140
+ 不能讓 row 高度變成「label 1 行 + desc 1~N 行」這種不可預測的範圍。
141
+
142
+ **Per-instance override**:consumer 若有合理理由(例如 settings 選單想顯示 2 行說明),可以顯式 `<MenuItem descMaxLines={2} ...>` 覆寫。要顯示完整不截,傳 `descMaxLines="none"`(不能傳 `undefined`,React props 的 destructure default 在 undefined 時會接管,fallback 到預設 `1`)。
143
+
144
+ ---
145
+
146
+ ## 狀態
147
+
148
+ | 狀態 | 背景 | 文字 | 觸發方式 |
149
+ |---|---|---|---|
150
+ | default | transparent | foreground | — |
151
+ | hover | `--neutral-hover` | foreground | 滑鼠 hover |
152
+ | selected(單選) | `--neutral-selected` | foreground | bg 高亮(不用 ✓ 勾號,避免影響 prefix 對齊) |
153
+ | selected(多選) | transparent | foreground | checkbox 勾選 |
154
+ | disabled | transparent | `--fg-disabled` | disabled prop |
155
+
156
+ ### 選中指示器
157
+
158
+ | 模式 | 選中指示器 |
159
+ |---|---|
160
+ | 單選 | `bg-neutral-selected` 背景高亮 |
161
+ | 多選 | Checkbox 勾選 |
162
+
163
+ 單選和 DropdownMenu RadioItem 統一用 `bg-neutral-selected`。不用 ✓ 勾號——勾號在 prefix 會影響群組內對齊。
164
+
165
+ disabled 時所有元素(icon、checkbox、文字)統一 `fg-disabled`。
166
+
167
+ ### 浮層關閉行為
168
+
169
+ | 模式 | 選了之後 | 原因 |
170
+ |---|---|---|
171
+ | 單選 | **關閉浮層** | 選完就結束 |
172
+ | 多選 | **不關閉** | 需要繼續勾選 |
173
+ | DropdownMenu CheckboxItem | **不關閉** | 同多選邏輯 |
174
+ | DropdownMenu 一般 Item | **關閉** | 執行動作後結束 |
175
+
176
+ ### Prefix icon 色彩
177
+
178
+ Menu item 的 prefix icon 跟 label 同色(foreground),不是 fg-muted。Prefix icon 是 label 的視覺延伸。
179
+
180
+ 詳見 `item-anatomy.spec.md` 的 Icon 色彩原則。
181
+
182
+ ---
183
+
184
+ ## Group
185
+
186
+ 群組由 `MenuGroup` 包裹,`py-2`(8px)上下內距。群組緊鄰群組,無額外間距。
187
+
188
+ ### Group Header
189
+
190
+ `header` prop 讓 item 變為群組標題:
191
+ - `font-medium` (500)
192
+ - `text-fg-muted` (neutral-7)
193
+ - 不可選、不可 hover
194
+ - 尺寸與一般 item 相同
195
+
196
+ ---
197
+
198
+ ## Footer(多選)
199
+
200
+ `MenuFooter` 提供固定底部區域(`border-t` + `py-2`)。
201
+
202
+ 典型用途:「全選」checkbox item,使用 `checked="indeterminate"` 在部分選中時顯示 minus 圖示。
203
+
204
+ ---
205
+
206
+ ## 禁止事項
207
+
208
+ - ❌ `startIcon` 和 `avatar` 不可同時使用
209
+ - ❌ 無 `description` 時不可使用 > 24px 的 avatar
210
+ - ❌ disabled item 不可有 hover 效果
211
+ - ❌ disabled item 內的所有子元件(icon、checkbox、文字)都必須呈現 disabled 狀態——fg-disabled 統一,checkbox 用 disabled 樣式
212
+ - ❌ header item 不可被選中
213
+ - ❌ 不在 item 內放獨立互動元素(如 Button)——item 本身就是互動單位
214
+
215
+ ---
216
+
217
+ ## 何時用 / 何時不用
218
+
219
+ **MenuItem 是 internal primitive**——不直接使用,透過 `SelectMenu` / `DropdownMenu` 等外層 menu 元件消費。
220
+
221
+ | 場景 | 正確做法 |
222
+ |------|---------|
223
+ | 建立操作選單(複製 / 刪除 / 分享)| 用 `DropdownMenu` + `DropdownMenuItem`(內部消費 MenuItem)|
224
+ | 建立選值下拉(選項 + 搜尋)| 用 `SelectMenu`(內部消費 MenuItem)|
225
+ | 建立右鍵選單 | 用未來的 `ContextMenu`(待開發)|
226
+ | 直接在 JSX 中用 `<MenuItem>` | ❌ **禁止**——會失去 menu 外層的 Radix 無障礙 / 鍵盤 / 焦點管理 |
227
+
228
+ ### 消費者
229
+
230
+ - `../SelectMenu/select-menu.tsx` — 下拉選單浮層
231
+ - `../DropdownMenu/dropdown-menu.tsx` — 操作選單
232
+ - 未來:ContextMenu、CommandPalette
233
+
234
+ ---
235
+
236
+ ## 為何無獨立 StateBehavior story
237
+
238
+ MenuItem 的狀態色(default / hover / selected / disabled)是**結構性的**——透過 variant(single / multi)× state 的二維矩陣呈現比時序互動更清楚。已在 `ColorMatrix` 用 TOKEN_MAP 完整矩陣覆蓋(單選 multi / 多選 single 各自的 4 state × bg / text / icon / desc token 對照)。
239
+
240
+ 獨立 StateBehavior story 會複製 ColorMatrix 內容——MenuItem 的 state 本身就是色彩表達,無額外「時序 / 動畫」可獨立呈現(不像 Accordion 有 expand/collapse 行為)。Inspector 已互動式展示 selected / disabled 單一 variant 的切換。
241
+
242
+ 對應 anatomy story:保留 `Overview` + `Inspector` + `ColorMatrix`(含完整狀態色矩陣) + `SizeMatrix`。
243
+
244
+ ---
245
+
246
+ ## 邊界案例
247
+
248
+ - **Disabled**:`disabled` prop 由 MenuItem primitive own;視覺 `text-fg-disabled`(neutral-6,M24 state>emphasis)、無 hover bg、`aria-disabled="true"`、Enter / click 不觸發 onSelect、鍵盤導覽自動 skip(由 consumer SelectMenu / DropdownMenu / cmdk 處理)。已在「選擇 / 狀態視覺規則」段 codify。
249
+ - **Loading**:MenuItem 為單一 row primitive 非 async surface,本身不擁有 loading prop。Async option list 的 loading 由 consumer(SelectMenu / Combobox / DropdownMenu)在 list body 替換為 `<Empty icon={<CircularProgress/>}/>`(SelectMenu SSOT)。
250
+ - **Empty(label-only / icon-only)**:label 為必傳;若無 prefix icon / avatar / checkbox,layout 自動收斂為 `[label] [suffix?]`;若無 suffix(shortcut / endAction / chevron),收斂為純 `[label]`。
251
+ - **Dark mode**:走 semantic token 自動 adapt。
252
+ - **Density**:`size` 由 consumer menu(`Menu` block-tier `compact` / `reading`)決定 row height + padding,MenuItem 自身不持 density state。
253
+
254
+ ---
255
+
256
+ ## 相關
257
+
258
+ - `../../patterns/element-anatomy/item-anatomy.spec.md` — MenuItem 的 row primitive 繼承規則(prefix / label / suffix 對齊)
259
+ - `../Avatar/avatar.spec.md` — Prefix 的 Avatar 尺寸
260
+ - `../Checkbox/checkbox.spec.md` — CheckboxItem 的視覺規則(DropdownMenu 使用)
261
+ - `../SelectMenu/select-menu.spec.md` — 主要消費者之一
262
+ - `../DropdownMenu/dropdown-menu.spec.md` — 另一個主要消費者
263
+
264
+ ## A11y 預設
265
+
266
+ **ARIA / Pattern**:對齊 [W3C ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/patterns/) 對應 pattern。
267
+
268
+ **Keyboard 行為**:
269
+
270
+ - Tab — focus container
271
+ - ↑/↓ — 導覽 items
272
+ - Enter — activate
273
+ - Esc — 關閉(若在 menu context)
274
+
275
+ **Focus**:focus-visible ring 對齊 DS canonical(`outline: 2px solid var(--ring)`);focus management 由元件 own。
276
+
277
+ **驗證**:Storybook a11y addon panel 應 0 critical violation;鍵盤完整可操作(無需滑鼠)。WCAG AA contrast ≥ 4.5:1(text)/ 3:1(UI)。
278
+
279
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
280
+
281
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
282
+
283
+ - `selection-item.spec.md`
284
+ - `sidebar.spec.md`
285
+
286
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
287
+
288
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
289
+
290
+ - `opacity.spec.md`