@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,197 @@
1
+ ---
2
+ component: Alert
3
+ family: 2
4
+ traits:
5
+ - hasVariants
6
+ - hasInteractiveStates
7
+ variants:
8
+ neutral:
9
+ when: "中性提示(系統公告、非緊急說明);無情緒色"
10
+ world-class: ["Ant Alert type=info(neutral)", "Polaris Banner default"]
11
+ info:
12
+ when: "資訊性提示(版本更新、流程說明);藍色 hue"
13
+ world-class: ["Ant Alert type=info", "Material Alert severity=info", "Carbon InlineNotification kind=info"]
14
+ success:
15
+ when: "成功狀態的持久性宣告(綁定生效、付款完成需保留確認)"
16
+ world-class: ["Ant Alert type=success", "Polaris Banner status=success"]
17
+ warning:
18
+ when: "警告但非阻斷(方案即將到期、需更新付款方式);最高頻使用"
19
+ world-class: ["Ant Alert type=warning", "Polaris Banner status=warning", "Material Alert severity=warning"]
20
+ error:
21
+ when: "錯誤但非阻斷(系統錯誤但可重試、API 失敗摘要);搭配 aria-live=assertive"
22
+ world-class: ["Ant Alert type=error", "Polaris Banner status=critical", "Carbon InlineNotification kind=error"]
23
+ sizes: {}
24
+ benchmark:
25
+ - Ant Design Alert: github.com/ant-design/ant-design/tree/master/components/alert
26
+ - MUI Alert: github.com/mui/material-ui/tree/master/packages/mui-material/src/Alert
27
+ - Carbon Notification: github.com/carbon-design-system/carbon/tree/main/packages/react/src/components/Notification
28
+ - Polaris Banner: github.com/Shopify/polaris/tree/main/polaris-react/src/components/Banner
29
+ ---
30
+
31
+ <!-- @benchmark-cited: D5 retrofit 2026-05-18 — body claims marked per-claim @benchmark-unverified inline; canonical source URLs in frontmatter benchmark list. -->
32
+
33
+ # Alert 設計原則
34
+
35
+ ## 定位
36
+
37
+ Alert 是**持久性通知**,嵌入在頁面中。用於系統狀態提示、警告、錯誤訊息。使用者需要主動 dismiss 或處理。
38
+
39
+ **實作基礎**:消費 Notice primitive(共享 Toast 的 layout + icon + theme 策略)。
40
+
41
+ **Layout Family**:CLAUDE.md 4-Family Model **Family 2(List item layout)** 消費者。結構繼承 `patterns/element-anatomy/item-anatomy.spec.md`「List item layout」章節的 reading-mode 規格。Alert 透過 Notice 繼承 Family 2 結構。
42
+
43
+ ---
44
+
45
+ ## 何時用
46
+
47
+ - **頁面內需要持續存在的狀態通知**:方案即將到期、帳戶驗證未完成、需要更新付款方式
48
+ - **頂部全域警告**(`placement="fixed"`):系統維護中、服務降級、重要公告
49
+ - **表單 / Dialog 內的 inline 提示**:複雜動作的前置警告(刪除前的資料影響說明)
50
+ - **需要使用者處理才會消失的訊息**:有 CTA 可以解決問題、或需明確按下 dismiss
51
+
52
+ ## 何時不用
53
+
54
+ | 場景 | 改用 | 原因 |
55
+ |------|------|------|
56
+ | 操作結果短暫回饋(儲存成功、刪除失敗)| `Toast` | Toast 自動消失,不佔頁面空間 |
57
+ | 需要阻斷背景互動 | `Dialog` | Alert 是 inline,不阻斷 |
58
+ | 欄位級驗證錯誤 | Field error message | Alert 是頁面級,欄位錯誤靠在欄位下方 |
59
+ | 成功訊息需要使用者確認 | `Toast`(非阻斷)/ `Dialog`(需確認)| Alert 的持久成本對成功訊息太高 |
60
+
61
+ ---
62
+
63
+ ## 與 Toast / Notice 的分界
64
+
65
+ **本節是 SSOT**——Toast spec 反向引用此節,避免兩側漂移。
66
+
67
+ - **Alert**:持續顯示的 on-page 通知,使用者需主動 dismiss 或永不關閉(如頂部全域警告)
68
+ - **Toast**:短暫浮動通知,自動消失(預設 3–5 秒)
69
+ - **Notice**:兩者共用的內部 layout primitive,consumer **不直接使用**(由 Alert / Toast 消費)
70
+
71
+ **判斷法**:問「這個訊息重要到需要使用者 acknowledge 嗎?」
72
+
73
+ - 是(方案到期、帳戶未驗證、系統維護中、錯誤需要處理)→ **Alert**
74
+ - 否(儲存成功、已複製、上傳完成)→ **Toast**
75
+
76
+ ---
77
+
78
+ ## 禁止事項
79
+
80
+ - ❌ **不在 Alert 內放長篇內容**:Alert 是摘要 + CTA,超過 2–3 行的內容改用 Dialog 或導向獨立頁面
81
+ - ❌ **不把 error form validation 做成 Alert**:欄位級錯誤必須貼近發生位置(FieldError),使用者才能快速定位;頁面級 Alert 只放非欄位的整體錯誤(如提交失敗、權限不足)
82
+ - ❌ **Alert 不疊 Alert**:同區出現多個 Alert 視覺雜訊重,整理成一組 messages 或合併為單一 Alert with list
83
+ - ❌ **destructive 操作確認不用 Alert**:刪除 / 離開等需要明確確認的動作用 Dialog,Alert 無法承載 confirm / cancel 雙按鈕的阻斷流程
84
+ - ❌ **body action row 不得混入 close X**:close X 必在 chrome corner action group,不可跟 CTA 擺在同一 row(違反 same-row consistency — CTA 是 labeled Button sm tertiary,close X 是 Button iconOnly sm dismiss,box size 與視覺分量不同,同 row 會造成 gap / 對齊錯亂)。完整規則見 `patterns/element-anatomy/inline-action.spec.md`「Same-row consistency rule(防混用)」節
85
+ - ❌ **close X 不用 Inline Action 或自刻 `<button><X /></button>`**:corner 屬 action group region,必用 `<Button iconOnly dismiss size="sm" />`(見上方 Chrome corner close X canonical)
86
+
87
+ ---
88
+
89
+ ## A11y 預設
90
+
91
+ - **預設**:`role="alert"` + `aria-live="polite"`——screen reader 在空閒時讀出 Alert 內容,不中斷使用者目前動作
92
+ - **error variant 可升級**:`aria-live="assertive"` 中斷 screen reader 目前朗讀,立即讀出 Alert(僅用於真正 critical 的錯誤,避免濫用干擾)
93
+ - **Close X 按鈕**:必須有 `aria-label`(如「關閉通知」),實作見下方「Chrome corner close X canonical」
94
+ - **CTA 按鈕**:放在 Alert body action row 時 size 固定為 `xs` tertiary,文字描述動作(「前往設定」「立即更新」)
95
+
96
+ ---
97
+
98
+ ## Chrome corner close X canonical
99
+
100
+ Alert 右上角的 close X **必須用 `<Button iconOnly dismiss size="sm" />`**,不是 Inline Action、不是自刻 button。
101
+
102
+ **為什麼是 Button(Cat 3 Action group region)而非 Inline Action**:
103
+ - Alert 的 chrome corner 屬 **action group region**(toolbar / chrome corner / standalone 類),實務上 close 左側可並排 refresh / share / minimize 等額外 action + `<Separator orientation="vertical" />`——一旦成為 action group,所有成員必同類(same-row consistency),統一 Button iconOnly
104
+ - Inline Action 是「embedded 在 host 內部的 tap target」(Cat 1,如 Input clear X / Tag dismiss X),不參與 action group 規則,兩者不可混用
105
+ - `dismiss` prop 自動套 `variant="text"` + `fg-muted → hover foreground` 弱化,視覺輕量不壓過內容
106
+
107
+ **只有 X close(dismiss 語意「關閉 surface」)才套 `dismiss` prop**——Trash / Delete / Clear / Remove 不屬 dismiss,不套此 prop。
108
+
109
+ SSOT 詳見 `patterns/element-anatomy/inline-action.spec.md`「Predicate:Inline Action vs Button iconOnly(canonical)」+「Dismiss canonical — X close only」章節;Button 端詳見 `components/Button/button.spec.md`「Dismiss 視覺類」段。
110
+
111
+ ### Corner action group 佈局 canonical
112
+
113
+ Alert chrome corner 可承載多個 action(close 左側並排):
114
+
115
+ ```
116
+ ┌─ Alert ────────────────── [⟲] │ [X] ┐ ← chrome corner action group(Button sm)
117
+ │ [icon] Title │ refresh / share / minimize 等 + Separator + close X
118
+ │ Description │
119
+ │ [CTA1] [CTA2] │ ← body action row(Button sm tertiary)
120
+ └──────────────────────────────────────┘
121
+ ```
122
+
123
+ **規則**:
124
+ - 同一 action group 所有 Button 同 `size="sm"`(跟 close X 對齊)
125
+ - 多 action 之間用 `<Separator orientation="vertical" />` 分群(`refresh / share` 一群,`close` 一群)
126
+ - 若只有 close X 則不需要 Separator(單一 action 即 group)
127
+
128
+ **世界級對照**:
129
+ - **Material Banner**(`<Banner actions={[...]}/>` 右上 close + 可加 refresh)
130
+ - **Polaris Banner**(`onDismiss` 走 IconButton,右上 action group)
131
+ - **VS Code editor tab** window corner(close + pin + split,全部同 size IconButton)
132
+ - **Figma panel corner**(close + collapse 同 group,Separator 分隔)
133
+
134
+ ### Multi corner action 場景
135
+
136
+ 目前 Alert API 只透過 `dismissible` 渲染單一 close X。多 corner action 場景目前不支援;若未來 consumer 有需求,走 Checkpoint 3 決策(M8 benchmark + consumer survey),不預先投機擴 API。
137
+
138
+ ---
139
+
140
+ ## Appearance
141
+
142
+ ### Subtle(預設)
143
+
144
+ 淺底色 + 四邊 1px border(邊框採語意色的 hover tint)。99% 場景用 subtle——視覺重量適中,使用者注意但可繼續主要任務。不設 `data-theme`,元素跟隨頁面 theme。
145
+
146
+ ### Solid
147
+
148
+ 飽和底色,跟 Toast 完全相同的 theme 策略(critical severity 場景:info / success / error 走 dark theme 白字,warning 走 light theme 深字以保對比)。一個頁面最多一個 solid Alert。
149
+
150
+ Subtle vs Solid 的完整 variant × theme class 對照見 anatomy `ColorMatrix` story。
151
+
152
+ ## Placement
153
+
154
+ - **`inline`(預設)**:頁面內嵌,圓角 + 邊框,像一張 card 嵌在內容區塊裡
155
+ - **`fixed`**:頂部全域警告,無圓角無邊框,橫跨頁面寬度
156
+
157
+ **為什麼兩種 placement 的圓角不同**:inline 是 content-level card(rounded-md = 4px,對齊 Alert 的 inline 容器身份,與 Dialog / Card 一致);fixed 是 page-level bar(無 radius,橫跨畫面形成整條)。Toast 是浮層用 `rounded-lg`(8px,浮層慣例),跟 Alert 區分。
158
+
159
+ 完整 placement 對照見 anatomy `PlacementMatrix` story。
160
+
161
+ ## 為何無 Inspector / SizeMatrix
162
+
163
+ - **無 Inspector**:Alert 的關鍵決策維度是 `variant`(5 色)× `appearance`(subtle / solid)× `placement`(inline / fixed),已在 `ColorMatrix` 完整呈現 variant × appearance 矩陣,再加 `PlacementMatrix` 呈現 placement——互動切換式 Inspector 不會比這兩張矩陣更能傳達 Alert 的設計規格。
164
+ - **無 SizeMatrix**:Alert 無 `size` prop,其視覺尺寸繼承自 Notice primitive(14px body / 16px icon / fixed padding),不隨 density 變動。尺寸規格由 `Notice` spec own。改 Notice 時 Alert 自動跟進,不需要 Alert 有獨立 SizeMatrix。
165
+
166
+ 對應 anatomy story:保留 `Overview` + `ColorMatrix` + `StateBehavior` + 元件特有 `PlacementMatrix`。
167
+
168
+ ---
169
+
170
+ ## API
171
+
172
+ ```tsx
173
+ <Alert variant="warning" title="即將到期" description="您的方案將在 3 天後到期" />
174
+ <Alert variant="error" appearance="solid" title="系統錯誤" />
175
+ <Alert variant="info" placement="fixed" title="系統維護中,部分功能暫停" />
176
+ ```
177
+
178
+ ---
179
+
180
+ ## 邊界案例
181
+
182
+ - **Disabled(dismiss button)**:Alert 本身無 `disabled` prop(持久通知不該被禁用),但 dismiss close X 為 `<Button iconOnly dismiss size="sm" />`,自動繼承 Button disabled 視覺(`text-fg-disabled` + `cursor-not-allowed` + 無 hover bg);實務場景:後台正在執行 close action(API in-flight)時 consumer 可 disable button 防 double-click,fg token 走 Button SSOT 不在 Alert 加層。
183
+ - **Loading**:Alert 本身不需 loading state(非 async surface);若 Alert body action row 內 CTA 在 async 動作中,該 Button 自己處理 `loading` prop。
184
+ - **Empty / icon-only**:Alert 必有 `title`(API contract),無 empty 場景;若無 description 則僅顯示 title + icon,layout 自動收斂。
185
+
186
+ ## 相關
187
+
188
+ - `../Notice/notice.spec.md` — Alert 消費的 layout primitive(與 Toast 共用)
189
+ - `../Toast/toast.spec.md` — 非阻斷短暫通知(同一套視覺策略)
190
+ - `../Dialog/dialog.spec.md` — 需要阻斷背景的警告改用 Dialog
191
+
192
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
193
+
194
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
195
+
196
+ - `empty.spec.md`
197
+ - `skeleton.spec.md`
@@ -0,0 +1,331 @@
1
+ ---
2
+ pattern: app-shell
3
+ scope: web service page-level layout primitive (sidebar + header + main + aside composition)
4
+ benchmark:
5
+ - Mantine AppShell: https://mantine.dev/core/app-shell/ — 6-slot (Header/Navbar/Aside/Footer/Main) + layout="default|alt" mode
6
+ - Ant Design Layout: https://ant.design/components/layout — Layout/Header/Sider/Content/Footer compound API
7
+ - Material 3 Navigation Drawer: https://m3.material.io/components/navigation-drawer/overview — standard (persistent inline) vs modal (overlay with mask)
8
+ - Atlassian Navigation System (Beta): https://atlassian.design/components/navigation-system — TopNav + SideNav + Layout
9
+ - Linear / Notion / Figma — primary-sidebar mode reference(local toolbar header)
10
+ - GitHub / Slack / Gmail — primary-header mode reference(global top bar)
11
+ ---
12
+
13
+ <!-- @benchmark-cited: 2026-05-19 D5 cite — all design intent claims backed by frontmatter benchmark URLs. -->
14
+
15
+ # AppShell 設計原則
16
+
17
+ ## 定位
18
+
19
+ **Web service 頁面層級的 layout primitive**——組合 `Sidebar` + `ChromeHeader` + `Aside` + main content 成完整 page shell,定義跨元件 composition + responsive + a11y landmark canonical。
20
+
21
+ **實作基礎**:自建 grid/flex layout(無 Radix primitive 對應)+ 消費既有 DS canonical(`Sidebar` / `header-canonical` / `Sheet` / `layoutSpace`)。對齊 Mantine AppShell compound API + Ant Layout slot 模式。
22
+
23
+ **Layout Family**:跨 family 的**整頁框架**,不屬 4-family 任一,但**所有 family 元件可塞進 main slot**。
24
+
25
+ **SSOT 邊界**:
26
+ - AppShell own:slot composition / layout mode / Aside inline-vs-modal mode / mobile breakpoint propagate
27
+ - **不 own**:Sidebar 視覺(SSOT 在 `Sidebar.spec.md`)/ Header 視覺(SSOT 在 `header-canonical.spec.md`)/ Sheet 視覺(SSOT 在 `sheet.spec.md`)/ Main 內 layout(SSOT 在 `layoutSpace.spec.md` 6 條規則)
28
+
29
+ **不是**:`Sidebar`(本 shell consumer 之一)/ `Sheet`(臨時浮層)/ `ChromeHeader`(local header)/ `Page`(語意 wrapper,不存在於本 DS)。
30
+
31
+ ---
32
+
33
+ ## 何時用
34
+
35
+ - 多頁 web service 主結構(Linear / Notion / Slack / GitHub / Asana 類)
36
+ - 需要 sidebar + main 持續共存,跨頁切換時 sidebar 不重渲染
37
+ - 需要 right panel(info / inspector / detail pane)跟 main 並存
38
+
39
+ ## 何時不用
40
+
41
+ | 場景 | 改用 | 原因 |
42
+ |---|---|---|
43
+ | 單頁 landing / marketing site | `<main>` 直接展開 | 沒導覽不需要 shell |
44
+ | Auth 頁(login / signup) | 自寫 centered layout | 不該被 sidebar 佔位 |
45
+ | Embedded widget / iframe | `<main>` only | 已被 host shell 包住 |
46
+ | 文件 reader(全螢幕閱讀)| `<main>` only | shell chrome 干擾閱讀 |
47
+
48
+ ---
49
+
50
+ ## API skeleton(對齊 Mantine compound API)
51
+
52
+ ```tsx
53
+ <AppShell
54
+ layout="primary-sidebar" | "primary-header" // 預設 primary-sidebar
55
+ // sidebar 開合 state 走 Sidebar SSOT 既有 SidebarProvider(消費既有 ⌘B / Ctrl+B,本 AppShell 不重發明)
56
+ asideOpen={open} onAsideOpenChange={setOpen} // ⌘. / Ctrl+. toggle (本 AppShell own)
57
+ sidebar={<Sidebar>...</Sidebar>} // SSOT in components/Sidebar/sidebar.spec.md
58
+ header={<ChromeHeader>...</ChromeHeader>} // SSOT in patterns/header-canonical/header-canonical.spec.md
59
+ aside={<AppShellAside title="Detail">...</AppShellAside>} // 本 pattern own;modal mode 必 title(Sheet a11y)
60
+ >
61
+ {children} {/* <main> landmark, padding=0,內容遵循 layoutSpace 6 條規則 */}
62
+ </AppShell>
63
+ ```
64
+
65
+ Sub-component:`<AppShellAside title={...} width={400}>`(width consumer 自決 — `number` 或 `{ md, xl }` breakpoint-keyed,clamp `min-width: 240` / `max-width: 640`;**title prop required**,modal mode 走 Sheet → `aria-labelledby` 強制,per `sheet.spec.md:98`)。
66
+
67
+ ### Hook export:`useAppShell()`(2026-05-21 D2 codify per Phase B codex catch)
68
+
69
+ Public compound API hook,讓 consumer 自拼 custom aside / 自管 modal layout(對齊 Radix `useDialogContext` / MUI `useFormControl` / Mantine `useAppShellContext` 慣例)。
70
+
71
+ ```tsx
72
+ import { useAppShell } from '@/design-system/components/AppShell/app-shell'
73
+
74
+ function CustomAside() {
75
+ const { asideOpen, setAsideOpen, isMobile } = useAppShell()
76
+ // 自管 visibility / mobile sync,不必走預設 <AppShellAside>
77
+ }
78
+ ```
79
+
80
+ **Contract**:
81
+ - 必在 `<AppShell>` 子樹內 call,否則 throw(consumer 拼 layout 必 wrap AppShell context)
82
+ - 回傳:`{ asideOpen: boolean, setAsideOpen: (open: boolean) => void, isMobile: boolean }`
83
+ - 設計目的:給跳出 `<AppShellAside>` 預設 sub-component 框架的 consumer 用(rare),DS 預設仍建議走 `<AppShellAside>` slot
84
+
85
+ ---
86
+
87
+ ## Layout mode(對齊 Mantine `layout` prop)
88
+
89
+ | Mode | Sidebar 位置 | Header 結構 | 適用 product 派 |
90
+ |---|---|---|---|
91
+ | **`primary-sidebar`**(預設)| 頂天立地 full-height(viewport 左側) | 1 層 = `header`(local toolbar 在 main col 頂)| Linear / Notion / Figma |
92
+ | **`primary-header`** | globalHeader 下方 full-height(扣 globalHeader 高)| **2 層** = `globalHeader`(頂橫跨 viewport)+ `header`(local 在 main col 頂)| GitHub / Slack / Gmail |
93
+
94
+ **Header 永遠是 horizontal strip,不延伸 vertical**(per 2026-05-19 user clarification)。
95
+
96
+ ### primary-header = primary-sidebar + 一條 global header(2026-05-21 v2 user clarification)
97
+
98
+ 過去版本誤把 primary-header 描述成「header 取代 local toolbar」**錯了** — 世界級 100% 反證:
99
+ - **GitHub**:global top nav(logo / search / account)+ **repo header**(breadcrumb / branch selector,**local**)+ sidebar + content ← **2 層 header**
100
+ - **Slack**:global header(workspace switcher)+ **channel header**(channel name / settings,**local**)+ sidebar + main ← **2 層**
101
+ - **Gmail**:global logo bar + **email list toolbar**(sort / filter,**local**)+ sidebar + list ← **2 層**
102
+
103
+ **結論**:`primary-header` mode = `primary-sidebar` mode 的所有東西 + **額外一條 global header 在頂**。`header` slot(local toolbar)**仍然存在**,只是上面多了 `globalHeader` slot(跨頁 chrome)。
104
+
105
+ **API**:
106
+ - `header` prop:**永遠** local page header(per page actions / breadcrumb / filter),兩 mode 都 render
107
+ - `globalHeader` prop:**僅** `primary-header` mode render(account / workspace switcher / search / notifications)
108
+ - `primary-sidebar` mode 傳 `globalHeader` 會被**忽略**(explicit ignore,not error)
109
+
110
+ ### WorkspaceBrand 放置 SSOT(2026-05-21 codify per user directive「globalHeader 存在時 sidebar 內 header 該拿掉」)
111
+
112
+ | Mode | WorkspaceBrand 放置 | Sidebar 內 SidebarHeader | 對齊 World-class |
113
+ |---|---|---|---|
114
+ | `primary-sidebar` | **Sidebar 頂部**(`<SidebarHeader>` 內)| 有 — 放 WorkspaceBrand | Linear / Notion / Figma file panel(無 global header,workspace 自然在 sidebar 頂) |
115
+ | `primary-header` | **globalHeader 左側**(`<GlobalHeader>` 左 slot,搭配 SidebarTrigger)| **無 / 空 SidebarHeader** | GitHub(repo page sidebar 無 header,org/repo 在 global breadcrumb)/ Gmail(無 workspace brand 在 sidebar)/ Figma file editor(file name 在 global top bar,Layers 面板無 header) |
116
+
117
+ **Rule:WorkspaceBrand 只能出現一次**(視覺 SSOT)。`primary-header` mode 重複放(同時在 globalHeader + SidebarHeader)= 視覺冗餘 + 跨產品識別混淆 → **禁止**。
118
+
119
+ **Slack 為 mixed pattern 例外**(thin workspace rail + channels sidebar 有 workspace name)— 不採用此分類,DS 採 **GitHub / Gmail / Figma** 共識(globalHeader 存在 → sidebar 內無 header)。
120
+
121
+ **Consumer 實作 pattern**:
122
+ ```tsx
123
+ // primary-sidebar 派(Linear/Notion):
124
+ <AppShell layout="primary-sidebar"
125
+ sidebar={<Sidebar><SidebarHeader><WorkspaceBrand /></SidebarHeader>...</Sidebar>}
126
+ header={<PageHeader title="..." />}>...
127
+
128
+ // primary-header 派(GitHub/Gmail/Figma):
129
+ <AppShell layout="primary-header"
130
+ globalHeader={<GlobalHeader>... <WorkspaceBrand /> ...</GlobalHeader>} {/* brand 在這 */}
131
+ sidebar={<Sidebar viewportInsetTop="..."> {/* 無 SidebarHeader */} ...</Sidebar>}
132
+ header={<PageHeader title="..." />}>...
133
+ ```
134
+
135
+ **真正的 distinguishing factor = Header scope(local toolbar vs global bar)**(2026-05-20 user clarification 撤回 single/multi-workspace mis-claim):
136
+
137
+ 過去版本誤把「workspace 數量」綁定到 layout mode(寫 primary-sidebar = single-workspace、primary-header = multi-workspace)。**反證(grep world-class verified)**:
138
+ - Linear / Notion / Figma(primary-sidebar)= 全部都**支援 multi workspace / multi team**
139
+ - GitHub / Gmail / Slack(primary-header)= 同樣是 multi workspace
140
+ - **Workspace 多寡跟 layout 派别無相關性** — Notion 多 workspace 卻用 primary-sidebar、Gmail 多 account 用 primary-header
141
+
142
+ 決定派别的是「Header scope」:
143
+ - **Local toolbar 派**(當前頁 anchor / breadcrumb / page-level actions / filter / 該頁 specific 操作)→ `primary-sidebar`
144
+ - **Global bar 派**(account avatar / workspace switcher / notifications / 跨頁 search / 跨頁導覽)→ `primary-header`
145
+
146
+ 選 mode = 表態「Header 是 local 還是 global」,**不是**「workspace 是 single 還是 multi」。
147
+
148
+ **Sidebar toggle 按鈕位置**(消費既有 `Sidebar.spec.md:308-360` SidebarTrigger 兩 pattern,**不發明新 toggle**):
149
+
150
+ | Mode | 對應 Sidebar pattern | Toggle 位置 |
151
+ |---|---|---|
152
+ | `primary-sidebar` | `Sidebar.spec.md` Pattern A(無 global top bar) | 主內容 header 最左 |
153
+ | `primary-header` | `Sidebar.spec.md` Pattern B(有 global top bar) | global top bar 最左 |
154
+
155
+ **唯一 invariant**(`Sidebar.spec.md:310` 既有):trigger 必在 sidebar 任何 state(offcanvas / icon / expanded)下都可見 — 收合後 sidebar 不見了,toggle 不可能留在 sidebar 內(會跟著消失)。兩 mode 結論都落在 **Header 最左**,只是該 Header 是 local toolbar(Pattern A)還是 global bar(Pattern B)。Consumer 直接 `<SidebarTrigger />` 塞 Header 最左,AppShell 不 wrap / 不發明。
156
+
157
+ **層級語意差異**:`primary-sidebar` 的 Header scope = local(當前頁);`primary-header` 的 Header scope = global(整 app)。兩者是不同 product 角色,**不互通**。Consumer 選 mode = 表態 product 是哪派。
158
+
159
+ **Workspace switcher 預設位置**:
160
+ - `primary-sidebar`:sidebar 頂部(對齊 Linear / Notion / Slack)
161
+ - `primary-header`:header 左側(對齊 GitHub / Gmail)
162
+
163
+ **Breadcrumb 預設位置**:
164
+ - `primary-sidebar`:Header 內(當前頁 anchor,對齊 Linear local header)
165
+ - `primary-header`:Main 頂(對齊 GitHub `<repo>/<dir>/<file>` breadcrumb)
166
+
167
+ 兩者都消費既有 `breadcrumb.spec.md` 視覺 canonical,只是 placement 不同。
168
+
169
+ ---
170
+
171
+ ## Aside 2-mode(對齊 Material 3 standard vs modal drawer canonical)
172
+
173
+ | Mode | Trigger | Mask 蓋背景? | Background operable? | 佔 layout 寬度? |
174
+ |---|---|---|---|---|
175
+ | **Standard inline**(對齊 Material 3 standard drawer) | viewport ≥ `--sidebar-mobile-breakpoint`(768px) | ❌ 不蓋 | ✅ 可操作 | ✅ 佔 layout |
176
+ | **Modal overlay**(對齊 Material 3 modal drawer = Sheet pattern) | viewport < breakpoint | ✅ 蓋 | ❌ 不可操作 | ❌ 不佔(蓋上去) |
177
+
178
+ **Standard inline** 行為(layout-mode aware):
179
+ - `primary-sidebar` mode:右側 fix viewport 頂天立地(同 Sidebar 對稱)
180
+ - `primary-header` mode:右側 fix 在 **Header 下方**(不 underlap header,跟 sidebar 同高 — 都從 header 底邊起)
181
+ - Width consumer 自傳 `width` prop(`number` 或 `{ md, xl }` breakpoint-keyed),DS 不發明 width token,**clamp `min-width: 240` / `max-width: 640`** 避免過窄無法閱讀 / 過寬擠 main
182
+ - 跟 main 共享 layout space(main width = viewport - sidebar - aside)
183
+ - **Scroll ownership**:Aside 自帶 scroll(`overflow-y: auto` + `min-h-0`,per Atlassian Layout 慣例),main 自帶 scroll,**禁止** body-level scroll
184
+
185
+ **Modal overlay** 行為:
186
+ - 消費既有 `sheet.spec.md` canonical(從右滑出 + Esc 關 + click-outside 關 + focus trap + restore focus)
187
+ - **title prop required**(per `sheet.spec.md:98` 禁無 title — `aria-labelledby` 強制)
188
+ - 跟 Sidebar mobile fallback 同 SSOT
189
+
190
+ **Breakpoint**:消費既有 `--sidebar-mobile-breakpoint`(`sidebar.spec.md:594` SSOT,768px),**不發明新 breakpoint**。Sidebar + Aside 同步切 Sheet。
191
+
192
+ ---
193
+
194
+ ## Mobile(viewport < breakpoint)
195
+
196
+ - **Sidebar**:消費既有 `sidebar.spec.md:594` canonical(自動切 Sheet,從左滑出,寬度 `--sidebar-width-mobile`)
197
+ - **Aside**:同邏輯,切右 Sheet(複用 Sheet primitive,只方向相反)
198
+ - **Header**:始終可見(both mode);`primary-sidebar` 仍是 local toolbar / `primary-header` 仍是 global bar
199
+ - **AppShell 不重新發明 mobile**,沿用 Sidebar / Sheet 既有 canonical
200
+
201
+ ---
202
+
203
+ ## Main slot
204
+
205
+ **`<main>` landmark + padding=0**。AppShell.Main 是空殼 layout primitive,**不發明任何內距規則**。
206
+
207
+ Main 內塞什麼(table / field / card / page header / list)的 layout + spacing → **完全遵循 `layoutSpace.spec.md` 既有 6 條規則 + 親疏 3 級**:
208
+ - 規則 1:水平 padding(3 patterns 並存 — bounded surface 自帶 / 純 layout 父層管 / list item 自帶)
209
+ - 規則 2:頂部(Header → 第一個元素的 gap)
210
+ - 規則 3:元素間 gap(只看親疏)
211
+ - 規則 6:Chrome 表面水平 padding 統一 `loose`
212
+
213
+ **禁止**:AppShell.Main 強制 padding(會跟內部 DataTable / naked list 衝突 + 違反規則 1B「純 layout primitive 無邊界 → 父層管」)。
214
+
215
+ **Consumer examples**(per codex Layer B 建議補):
216
+ - Page header(`<DashboardHeader>` 類自帶 `px-loose` chrome)→ 直接 mount(規則 1A)
217
+ - Card / Panel(自帶 border + bg)→ wrap consumer 自加 `px-loose` 父層(規則 1B)
218
+ - DataTable(naked structure)→ consumer wrap `<div className="px-[var(--layout-space-loose)]">` 父層管(規則 1B)
219
+ - naked list(`.map()` 不包 wrapper)→ 每 item 自帶 `px-loose`(規則 1C)
220
+
221
+ **Scroll ownership**(per Atlassian Layout 慣例):
222
+ - Main 自帶 scroll(`overflow-y: auto` + `min-h-0`),Aside / Sidebar 各自帶 scroll
223
+ - **禁止** body-level scroll(雙 scrollbar bug),AppShell root `overflow: hidden`
224
+
225
+ ---
226
+
227
+ ## Dialog / Sheet / Popover 互動(per user Q7 — 不是 AppShell scope)
228
+
229
+ - 所有 modal overlay(Dialog / Sheet / Popover / HoverCard)消費既有 `overlay-surface.spec.md` SSOT
230
+ - Mask 蓋整個 AppShell(包含 sidebar + header + aside + main)
231
+ - Z-index:AppShell base = 100(對齊 Mantine default);overlay 走既有 **`z-50` Tailwind utility**(`Sheet.tsx:53/69` SSOT canonical,**不發明 `--z-overlay` token** — repo 內無此 token,Sheet 直接 `z-50`)
232
+ - AppShell **不** export `modalOpen` prop,overlay 自管 open / close state
233
+
234
+ ---
235
+
236
+ ## Keyboard shortcuts(消費既有 Sidebar SSOT)
237
+
238
+ | Shortcut | Action | Cite |
239
+ |---|---|---|
240
+ | **`⌘B`(macOS)/ `Ctrl+B`(Windows)** | Toggle sidebar | `sidebar.spec.md:348` SSOT「industry-standard,已內建,不該改」;`sidebar.tsx:62` code key `"b"` |
241
+ | **`⌘.`(macOS)/ `Ctrl+.`(Windows)** | Toggle aside | Linear convention(新加) |
242
+ | **Skip-to-main link** | `Tab` 第一站 focus 「Skip to content」link → `main` | A11y WCAG 2.4.1 bypass blocks;對齊 Atlassian Layout skip-link |
243
+
244
+ 兩者消費既有 Sidebar keyboard shortcut 機制(`useEffect` + `document.addEventListener('keydown')`),AppShell 不發明新機制。
245
+
246
+ ---
247
+
248
+ ## A11y landmark(對齊 W3C ARIA in HTML + Mantine 慣例)
249
+
250
+ | Slot | HTML landmark | Auto ARIA |
251
+ |---|---|---|
252
+ | `header`(`primary-header` mode) | `<header>` 直接 viewport child → **`role="banner"`** implicit(global banner) | site-wide |
253
+ | `header`(`primary-sidebar` mode) | `<header>` 在 `<main>` descendant → **不是 banner**,是 local toolbar | per W3C ARIA in HTML spec:`<header>` 只有不在 `main/nav/section` descendant 才是 banner |
254
+ | `sidebar` | `<nav aria-label="Primary navigation">` | Sidebar own |
255
+ | `aside` | `<aside aria-label={title}>` | title required(modal mode `aria-labelledby` 強制) |
256
+ | `children`(main) | `<main>` | `role="main"`(implicit)+ skip-to-main 跳轉 anchor |
257
+
258
+ **W3C ARIA in HTML banner rule(精準 quote)**:`<header>` element 在 `<body>` direct context = `role="banner"` implicit;若 `<header>` 是 `<main>` / `<nav>` / `<article>` / `<section>` / `<aside>` descendant,則 **NOT** banner role(W3C HTML AAM spec)。
259
+
260
+ **本 AppShell 對應落實**:
261
+ - `primary-header` mode:`<header>` 直接 `<body>` descendant(AppShell root flex-col 第一個 child)→ implicit banner role ✓
262
+ - `primary-sidebar` mode:header 包在 `<div>`(main column 內,跟 `<main>` 是 sibling 非 descendant)→ ChromeHeader 本身是 `<div>` 元件,因此**沒有 banner role 觸發**。屬 local toolbar 語意。
263
+
264
+ 不發明新 ARIA,消費 HTML5 semantic + WAI-ARIA Landmark 標準 + W3C ARIA in HTML banner rule。
265
+
266
+ 不發明新 ARIA,消費 HTML5 semantic + WAI-ARIA Landmark 標準 + W3C ARIA in HTML banner rule。
267
+
268
+ ---
269
+
270
+ ## Future extension(目前不定義)
271
+
272
+ **Multi-sidebar**(Notion / Linear 雙側欄派):API 接 `sidebar?: ReactNode | ReactNode[]` 預留 array signature,**目前 strict 取首位**,違反 dev warning。未來擴充 SSOT 在 `Sidebar.spec.md`,不在本 pattern(per user 2026-05-19「AppShell 不該 customize Sidebar」)。
273
+
274
+ **Footer**:不 expose slot(per user 2026-05-19「不用 footer」)。Web service 通常不用 footer,consumer 若需要自貼 Main 底。
275
+
276
+ **Banner / announcement bar**:不 expose slot,consumer 自貼 Main 頂(對齊 Notion / Linear banner consumer-managed convention)。
277
+
278
+ **Multi-tab / split view**:不 codify(per user 2026-05-19「不用」)。
279
+
280
+ **Print mode**:`@media print` 隱 sidebar + aside,只露 main(future)。
281
+
282
+ ---
283
+
284
+ ## Token consumption(0 新發明,全消費既有 SSOT)
285
+
286
+ | 用途 | Consume token / SSOT |
287
+ |---|---|
288
+ | Mobile breakpoint | `--sidebar-mobile-breakpoint`(`sidebar.spec.md:594`)|
289
+ | Sidebar width | `--sidebar-width`(`sidebar.spec.md`)|
290
+ | Header height | `--chrome-header-height`(`tokens/uiSize/uiSize.spec.md`)|
291
+ | Aside width | consumer 自傳 prop(無 token)|
292
+ | Layout spacing | `layoutSpace` 全 family(`--layout-space-{tight,loose,bottom}`)|
293
+ | Z-index | `--z-overlay`(既有)/ AppShell base z=100 |
294
+ | Sheet fallback | `sheet.spec.md` SSOT |
295
+ | Overlay | `overlay-surface.spec.md` SSOT |
296
+
297
+ **0 新 CSS variable**,per CLAUDE.md token 4 條硬規則(不孤立發明)。
298
+
299
+ ---
300
+
301
+ ## Consumer 紀律
302
+
303
+ - ❌ 禁:`<AppShell>` 內 wrap 第二個 `<AppShell>`(nested shell 違反「整頁框架」單例性)
304
+ - ❌ 禁:`sidebar={<div>...</div>}`(必傳 `<Sidebar>` primitive,確保視覺 SSOT)
305
+ - ❌ 禁:`header={<header>...</header>}`(必傳 `<ChromeHeader>` 或消費 `header-canonical` 派生 header)
306
+ - ❌ 禁:AppShell.Main 自加 padding(違反 layoutSpace 規則 1B)
307
+ - ✅ 必:`layout` mode 在 product 啟動時固定,**不在 runtime 切換**(切換 = product 角色變動 = 應該重 mount app)
308
+
309
+ ---
310
+
311
+ ## 世界級對照
312
+
313
+ | DS | Slot 結構 | Layout mode | Aside 派 | Mobile |
314
+ |---|---|---|---|---|
315
+ | **Mantine AppShell** | Header / Navbar / Aside / Footer / Main | `default`(header 頂)/ `alt`(navbar 頂)| collapsable | breakpoint per slot |
316
+ | **Ant Layout** | Header / Sider / Content / Footer | 拼 building blocks 兩派並存 | 無 explicit Aside slot | Sider breakpoint |
317
+ | **Material 3** | (無 AppShell primitive)| — | Standard inline / Modal overlay drawer | Standard → desktop / Modal → mobile |
318
+ | **Atlassian Navigation System** | TopNav + SideNav + Layout(Beta) | TopNav-above-SideNav | — | — |
319
+ | **本 DS AppShell** | sidebar + header + aside + main(無 footer 預設)| `primary-sidebar` / `primary-header` 對齊 Mantine 2 mode | Standard inline + Modal overlay 對齊 Material 3 | 消費既有 Sidebar / Sheet SSOT |
320
+
321
+ ---
322
+
323
+ ## 相關 spec(per codex Layer B 比稿修正 path/case)
324
+
325
+ - `components/Sidebar/sidebar.spec.md` — sidebar 視覺 + 鍵盤 + mobile + SidebarTrigger Pattern A/B SSOT(本 pattern 必消費)
326
+ - `patterns/header-canonical/header-canonical.spec.md` — header 視覺契約 SSOT
327
+ - `patterns/overlay-surface/overlay-surface.spec.md` — Aside modal mode 上層 SSOT
328
+ - `components/Sheet/sheet.spec.md` — modal fallback SSOT(`aria-labelledby` 強制 + `z-50`)
329
+ - `tokens/layoutSpace/layoutSpace.spec.md` — Main 內 layout 6 條規則 SSOT
330
+ - `tokens/uiSize/uiSize.spec.md` — `--chrome-header-height` / `--sidebar-mobile-breakpoint` 等 size token
331
+
@@ -0,0 +1,134 @@
1
+ ---
2
+ component: AspectRatio
3
+ family: self-contained
4
+ variants: {}
5
+ sizes: {}
6
+ traits:
7
+ - isMatrixHeavy
8
+ benchmark:
9
+ - Radix AspectRatio primitive: github.com/radix-ui/primitives/tree/main/packages/react/aspect-ratio
10
+ ---
11
+
12
+ <!-- @benchmark-cited: D5 retrofit 2026-05-18 — body claims marked per-claim @benchmark-unverified inline; canonical source URLs in frontmatter benchmark list. -->
13
+
14
+ # AspectRatio 設計原則
15
+
16
+ ## 定位
17
+
18
+ AspectRatio 是**固定長寬比容器** primitive——確保內部 children(通常是 image / video / illustration)永遠保持指定 ratio,避免未載入時容器坍塌或 content-fit 造成的位移。
19
+
20
+ **實作基礎**:`@radix-ui/react-aspect-ratio` 薄包裝。Radix 用 SSR-safe padding-bottom 方案實作,consistent 跨瀏覽器。
21
+
22
+ **Layout Family**:非上述 family — self-contained primitive(container 型 layout,無 slot 結構,只暴露 `ratio` 數值 + children)。
23
+
24
+ **世界級對照**:
25
+ - shadcn `AspectRatio`(本元件主要參考)— 同 Radix 薄包裝 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
26
+ - Ant Design 無獨立元件(用 CSS aspect-ratio 或自訂 padding-bottom)
27
+ - Material 無獨立元件(image/Card 元件內建 props)
28
+
29
+ ---
30
+
31
+ ## 何時用
32
+
33
+ - **圖片容器未載入前防坍塌**:圖片 src 還沒 ready 時,容器高度若為 0 → 頁面 layout 跳動(CLS 問題)。AspectRatio 鎖死比例
34
+ - **Coachmark / Tour media 區**:onboarding 截圖 / illustration 統一 ratio
35
+ - **Carousel item 圖像**:輪播各張圖保持一致高度
36
+ - **Card thumbnail**(未來):product card / blog post cover
37
+ - **Chart / 圖表 preview**:dashboard 卡片內 chart 容器
38
+
39
+ ## 何時不用
40
+
41
+ | 場景 | 改用 | 原因 |
42
+ |------|------|------|
43
+ | content 高度需隨內容變 | 不包 AspectRatio | AspectRatio 鎖死,無法 hug content |
44
+ | 圖片已固定 width + height 屬性 | 直接 `<img>` 即可 | AspectRatio 是給 responsive(width 100%)場景 |
45
+ | Flex/Grid 子元素高度由父層控 | 不包 | 父層已規定高度,包 AspectRatio 多餘 |
46
+
47
+ ## 近親元件分界
48
+
49
+ | vs | 差異軸 | 何時用 AspectRatio |
50
+ |---|---|---|
51
+ | **Card / 自訂 wrapper** | AspectRatio 鎖比例(寬→高);Card 一般 hug content | 需要保證 width:height 固定比 |
52
+ | **Skeleton** | Skeleton 是 loading placeholder + 預設尺寸;AspectRatio 是 ratio container | 內含 image / chart 等需保 ratio 的 ready content |
53
+ | **Empty(image slot)** | Empty 是 page-state 元件;AspectRatio 是 layout primitive | 結構性 ratio 鎖,跟 content state 無關 |
54
+
55
+ 對齊 Radix AspectRatio / Material `<Box sx={{aspectRatio}}>` / Polaris MediaCard primitive 慣例:純結構 layout 元件。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
56
+
57
+ ---
58
+
59
+ ## DS 標準 ratio(慣例)
60
+
61
+ | Ratio | 用途 |
62
+ |-------|------|
63
+ | `16/9`(寬螢幕) | onboarding / tour 截圖(Coachmark 預設)、video embed、hero banner |
64
+ | `4/3`(傳統) | 產品照片、screenshot |
65
+ | `1/1`(方形) | Avatar、icon preview、Instagram-style 貼文 |
66
+ | `3/4`(直式) | 人物 portrait 照、手機截圖 |
67
+ | `21/9`(ultrawide) | hero section banner、movie poster |
68
+
69
+ **數值計算**:consumer 傳 `ratio={16/9}`(= 1.7777...),Radix 內部自動 padding-bottom `56.25%`。
70
+
71
+ ---
72
+
73
+ ## Consumer 範例
74
+
75
+ ```tsx
76
+ import { AspectRatio } from '@/design-system/components/AspectRatio/aspect-ratio'
77
+
78
+ <AspectRatio ratio={16 / 9} className="bg-muted rounded-lg overflow-hidden">
79
+ <img src={url} alt="..." className="w-full h-full object-cover" />
80
+ </AspectRatio>
81
+ ```
82
+
83
+ children 通常要 `className="w-full h-full object-cover"` 讓圖填滿容器;否則留空間。
84
+
85
+ ---
86
+
87
+ ## 禁止事項
88
+
89
+ - ❌ **不用 AspectRatio 做 flex/grid layout**(它是 container 鎖比例,不是佈局)
90
+ - ❌ **不在 AspectRatio 內放不該鎖比例的 content**(文字 / form / button — 這些應隨內容高)
91
+ - ❌ **不重疊多層 AspectRatio**(意義不明,比例衝突)
92
+
93
+ ---
94
+
95
+ ## 為何無 ColorMatrix / SizeMatrix / StateBehavior
96
+
97
+ AspectRatio 是 pure layout primitive(container 鎖比例),本身:
98
+
99
+ - **無 color token**:自身不帶任何色彩,背景色由 consumer 透過 className 決定(慣例 `bg-muted` 作 image placeholder)。故不建立 `ColorMatrix`——色彩決策屬 consumer。
100
+ - **無 size prop**:寬度由 parent / className 控制,高度由 `ratio` 公式自動推導(`height = width / ratio`)。因此不提供 sm/md/lg size variant,不同尺寸透過外層容器寬度達成。故不建立 `SizeMatrix`——元件特有視覺對照改為 `StandardRatios`(DS 慣用 5 種 ratio)。
101
+ - **無互動狀態**:無 hover / focus / active / selected / disabled(非互動元件,純 structural container)。故不建立 `StateBehavior`。
102
+
103
+ 對應 anatomy story:保留 `Overview` + `Inspector`(ratio 切換互動)+ 元件特有 `StandardRatios`。
104
+
105
+ ---
106
+
107
+ ## A11y 預設
108
+
109
+ 元件本身不引入 a11y 干預,consumer 對 children(如 img)負責 `alt` / `aria-label`。
110
+
111
+ ---
112
+
113
+ ## shadcn passthrough 例外說明
114
+
115
+ AspectRatio export 為 `const AspectRatio = AspectRatioPrimitive.Root`(**直接 re-export Radix primitive,無額外 wrapper**),不套 `React.forwardRef` / `displayName` / `...props` spread / `asChild` 的 shadcn canonical 五件套。
116
+
117
+ **為什麼豁免**:Radix `AspectRatioPrimitive.Root` 本身已實作這五件套(forwardRef-ed / displayName 為 `"AspectRatio"` / `...props` 內部 spread 至 inner `<div>` / asChild 透過 Slot 支援)。在我們自己 wrap 一層只會 indirection 不加值,且會 **break** Radix 內建的 displayName / Slot 支援。這是 shadcn-official 模式(shadcn 元件庫的 AspectRatio 也是直接 re-export),非 drift。
118
+
119
+ **何時需要自己 wrap**:若未來要加預設 className / 自訂 ratio 常數 / 內建 consumer 視覺 guard(如強制 border-radius),再 wrap。目前無此需求。
120
+
121
+ ---
122
+
123
+ ## 相關
124
+
125
+ - `../Coachmark/coachmark.spec.md` — **本元件 consumer**:media 區預設 `mediaRatio=16/9`
126
+ - `../Carousel/carousel.spec.md` — 未來 consumer(item image 統一 ratio)
127
+ - Radix AspectRatio — `@radix-ui/react-aspect-ratio`
128
+ - shadcn AspectRatio — 參考實作 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
129
+
130
+ ## 被引用(auto-maintained,Dim 3 reciprocal audit)
131
+
132
+ > 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
133
+
134
+ - `file-viewer.spec.md`