@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,176 @@
1
+ ---
2
+ component: FieldControlGroup
3
+ family: self-contained
4
+ variants: {}
5
+ sizes: {}
6
+ traits: []
7
+ # traits: [] rationale(2026-05-15 audit Dim 29 fix):layout-primitive,no trait variants(border-collapse only)。
8
+ # 對齊 spec frontmatter schema completeness — 即便 N/A 也明示 empty array + rationale comment,避免 audit gap。
9
+ benchmark:
10
+ - Ant Design Space.Compact: github.com/ant-design/ant-design/blob/master/components/style/compact-item.ts
11
+ - Bootstrap input-group: github.com/twbs/bootstrap/blob/v5.3.3/scss/forms/_input-group.scss
12
+ - Chakra UI Group + InputGroup: github.com/chakra-ui/chakra-ui/blob/main/apps/www/content/docs/components/input.mdx
13
+ ---
14
+
15
+ <!-- @benchmark-cited: D5 retrofit 2026-05-18 — Ant Space.Compact + Bootstrap input-group + Chakra Group claims verified via WebFetch + inline URL. -->
16
+
17
+ # FieldControlGroup spec
18
+
19
+ ## 定位
20
+
21
+ **Layout Family**:self-contained(form composition layout-primitive,非 4-Family element layout — 對齊 frontmatter `family: self-contained`)。
22
+
23
+ **多個 Field controls 視覺接合成一個 input frame**(border-collapse pattern)。對齊 ButtonGroup 同類接合 idiom — `<X>Group` 命名一致(X = button → ButtonGroup;X = field control → FieldControlGroup)。
24
+
25
+ **自建 + 理由**:無單一 Radix / shadcn 對應 primitive(shadcn 沒提供;Radix 沒對應)。對齊 [Ant `Space.Compact`](https://ant.design/components/space#spacecompact)(verified source)mechanism + [Bootstrap `.input-group`](https://getbootstrap.com/docs/5.3/forms/input-group/)(verified SCSS)idiom 自建。
26
+
27
+ ## 何時用
28
+
29
+ - 兩個語意連動的 control 視覺一體(電話 = 國碼 + 號碼;金額 = 幣別 + 數字)
30
+ - DataTable 進階篩選 row(field + operator + value)
31
+ - Search input + Submit button
32
+ - Range input(start + end)
33
+ - Phone / address 多段輸入
34
+
35
+ ## 何時**不用**
36
+
37
+ - 單一 control(直接用 Field 即可)
38
+ - 多個獨立 fields 垂直排列 → 用 `FieldGroup`
39
+ - 同一 question 多 options(Checkbox 群組)→ 用 `CheckboxGroup` / `RadioGroup`
40
+ - 需 outer 統一 border 但 children 之間有顯著 gap(非接合)→ 直接 `flex gap-2`
41
+
42
+ ## 近親分界
43
+
44
+ | 元件 | scope | 視覺 | 語意 |
45
+ |--|--|--|--|
46
+ | `FieldGroup` | 多 Field 垂直堆疊 | gap 分離 | layout primitive |
47
+ | **`FieldControlGroup`** | 多 control 橫向接合 | border collapse | layout primitive(本元件)|
48
+ | `RadioGroup` / `CheckboxGroup` | 1 question 多 options | 各自獨立 | semantic group(ARIA role)|
49
+ | `ButtonGroup` | 多 Button 接合 | border collapse | layout primitive(同 mechanism) |
50
+
51
+ ## API
52
+
53
+ ```ts
54
+ interface FieldControlGroupProps extends HTMLAttributes<HTMLDivElement> {
55
+ size?: 'sm' | 'md' | 'lg' // default 'md',Mode A 從 Field context 來
56
+ block?: boolean // 對齊 Ant Space.Compact `block`,默 false=inline-flex
57
+ }
58
+ ```
59
+
60
+ **子元件支援 list**(對齊 Ant Space.Compact 限定 list 策略,verified):
61
+ - ✅ Input / NumberInput / Select / Combobox / DatePicker / DatePickerRange / Button
62
+ - ❌ Field(包 Field 進 group 語意亂)/ FieldGroup(垂直 vs 橫向衝突)/ 純 Layout primitive
63
+
64
+ ## 行為機制(verified Ant compact-item.ts L21-92)
65
+
66
+ 1. **子保留 border + radius**(不 strip)
67
+ 2. **鄰接子負 margin 重疊 border**:`> * + * { margin-left: -1px }`(border 寬度疊在一起 = 視覺 1 條線)
68
+ 3. **Z-index 提升** for active control(避免被鄰接 border 蓋)
69
+ - default `z-index: 2`
70
+ - hover / focus / focus-within `z-index: 3`(Ant z-3,Bootstrap z-5;我們對齊 Ant)
71
+ - disabled `z-index: 0`
72
+ 4. **Border radius 規則**:
73
+ - 第一個子:右側 radii = 0(`rounded-r-none`)
74
+ - 中間子:全 radii = 0(`rounded-none`)
75
+ - 最後一個:左側 radii = 0(`rounded-l-none`)
76
+ 5. **Container display**:default `inline-flex` / `block` prop → `flex w-full`
77
+ 6. **Items align**:`items-stretch`(同高)
78
+
79
+ ## Width 配置 canonical(W-A,對齊 Ant)
80
+
81
+ **子 controls 自管 width**:
82
+ - Fixed:`<Select className="w-[140px]">`
83
+ - Flex:`<Input className="flex-1">`
84
+ - 混合 OK(filter row 典型:fixed + fixed + flex)
85
+
86
+ **禁止**:不開 `Cell` wrapper(指 indirection 不必要;Ant Space.Compact 同樣不開)。
87
+
88
+ ## Size cascade
89
+
90
+ **Mode A**(包進 Field 當 control slot):
91
+ ```tsx
92
+ <Field>
93
+ <FieldLabel>電話</FieldLabel>
94
+ <FieldControlGroup> {/* size 自動繼承 Field context */}
95
+ <Select className="w-[80px]" options={codes} />
96
+ <Input className="flex-1" />
97
+ </FieldControlGroup>
98
+ </Field>
99
+ ```
100
+
101
+ **Mode B**(standalone):
102
+ ```tsx
103
+ <FieldControlGroup size="md"> {/* 顯式 size,默 md */}
104
+ ...
105
+ </FieldControlGroup>
106
+ ```
107
+
108
+ **Mode C**(進 Popover,density 鎖 md):children 自然吃 md(Popover density canonical)。
109
+
110
+ ## A11y 預設
111
+
112
+ - Container 不加 ARIA role(透明 wrapper,不是 semantic group)
113
+ - Children 各自 a11y 標註(每個 Select/Input 自帶 aria-label)
114
+ - Tab 鍵在 children 之間正常移動(no focus trap)
115
+ - Disabled 透過 children 各自 disabled prop(不從 Group 層級 cascade)
116
+
117
+ ## 禁止事項(❌)
118
+
119
+ - ❌ 包 Field 進 FieldControlGroup(雙層 wrapper 無意義 + label/error 處理混亂)
120
+ - ❌ 不同 size 的 children 混用(視覺高度不一致)
121
+ - ❌ 一個 child 設 disabled / 一個設 readonly 等不同 mode(語意一體應一致)
122
+ - ❌ 開 Cell wrapper(違 Ant idiom;子 className 控 width 即可)
123
+ - ❌ Vertical 堆疊用 FieldControlGroup(用 FieldGroup;本元件僅 horizontal)
124
+ - ❌ **包 `<div>` / `<span>` wrapper 在 FieldControlGroup direct children 外**(2026-05-04 #2 真實 bug):
125
+ CSS `[&>*]` 直接子選擇器命中 wrapper(無 border/radius)→ inner Field control 保留 left/right radii → **圓角破圖**。
126
+ 修法:Field control 必為 direct child;若需 className 給 inner Field control,透過 component prop forward
127
+ (e.g. FilterValuePicker 的 `className` prop 直接 forward 給 inner Input/Select),不另開 wrapper div。
128
+ - ❌ Field controls trigger 內部 `w-full` 無法被外加 `className="w-[Xpx]"` override(同 cn() 後 specificity 順序)
129
+ → 必用 `!w-[Xpx]` (Tailwind important) OR 外加 `flex-shrink-0` + 設容器 grid-cols。
130
+
131
+ ## States
132
+
133
+ | State | 視覺 | z-index |
134
+ |--|--|--|
135
+ | default | 各 child 自身 border | 2 |
136
+ | hover(子)| 該 child border-hover | 3 |
137
+ | focus / focus-within(子)| 該 child focus ring | 3 |
138
+ | disabled(子)| 該 child disabled style + **FCG-local override `border-input`**(K12,2026-05-04) | 0 |
139
+
140
+ **Disabled border integrity canonical(K12,2026-05-04)**:全域 disabled = `border-transparent`(讓 standalone field 視覺輕量),但**FCG context 下,disabled child 強制 `border-input`** — 確保:(a) FCG 整體外圈 border 健在,(b) inner divider 健在(不會因兩相鄰 disabled cells 都 transparent 而消失)。bg-disabled 仍區分狀態,border 維護群組視覺整合性。對齊 [Bootstrap input-group](https://getbootstrap.com/docs/5.3/forms/input-group/) / [Ant Space.Compact](https://ant.design/components/space#spacecompact) disabled idiom。
141
+
142
+ 實作(v7 — semantic token):
143
+ ```tsx
144
+ [&>*[data-field-mode="disabled"]]:border-[var(--border-opaque)]
145
+ ```
146
+ 保留 global `bg-disabled`(neutral-2 灰底)— disabled state 視覺主要由 bg 承載。
147
+
148
+ **為什麼用 `--border-opaque` 而非 `--border`**:`--border`(neutral-5 = 15% alpha)會跟 cell bg compositing — 灰底上 composite 略深(物理對比結果)。**`--border-opaque`** semantic token(其 primitive 後盾為 `--color-neutral-5-opaque`,solid #D9D9D9)不分 bg 永遠同色,divider 在 white edit cell 跟 grey disabled cell 上視覺完全一致。
149
+
150
+ **Token 系統設計**:`--border-opaque` 在 `semantic.css` L289 新增,語意「視覺等同 `--border` 但 alpha-immune」。對齊 [Ant Design `colorBorderSecondary`](https://ant.design/docs/react/customize-theme#seedtoken) solid idiom — Ant 用此 token 在 table 外框 + row divider(non-white bg 場景),跟 input alpha border 視覺層級分。
151
+
152
+ **為什麼不 override bg**:user 明確要求 disabled cells 有底色(辨識 state)。bg 灰底是 disabled state 的主要視覺載體,FCG context 不應抹除。
153
+ | error(子)| 該 child border-error | 3(error 視覺在最上)|
154
+
155
+ **整 row error**:目前 v1 不支援 row-level error(走 cell-level)。未來若需可走 outer border-error wrapper,但 v1 follow Ant 不做。
156
+
157
+ ## Loading / Empty / 驗證
158
+
159
+ - Loading:子 control 各自處理(Input loading state / Select loading)
160
+ - Empty:N/A(layout primitive,無資料概念)
161
+ - 驗證:子 control 自管(form library 透過 Field 處理)
162
+
163
+ ## 世界級對照
164
+
165
+ | 框架 | 命名 | 機制 | sizing | 子 scope |
166
+ |--|--|--|--|--|
167
+ | **[Ant Space.Compact](https://ant.design/components/space#spacecompact)** | layout primitive | 負 margin 重疊 + z-index 3 | `size: small/middle/large` (group prop)| Button + 各 form control(限定 list)|
168
+ | **[Bootstrap input-group](https://getbootstrap.com/docs/5.3/forms/input-group/)** | CSS class | flexbox + first/last border-radius | group-level sizing,個別 children 不能設 | input/select/btn/text addon |
169
+ | **[Chakra Group](https://www.chakra-ui.com/docs/components/group)** | `attached` prop primitive | `attached`+`grow` props | per-child | Input + Addon/Element(InputGroup 已 deprecated v3)|
170
+ | **Mantine** | 無此 idiom | — | — | — |
171
+
172
+ 3/4 共識 → 我們的實作對齊 Ant + Bootstrap 主軸。
173
+
174
+ ## 變更紀錄
175
+
176
+ - 2026-05-04 v1:Initial。基於 Ant compact-item.ts source verify 訂機制。Filter / Sort 對齊 Ant W-A 子自管 width。
@@ -0,0 +1,467 @@
1
+ ---
2
+ component: FileItem
3
+ family: 2
4
+ variants: {}
5
+ sizes: {}
6
+ traits:
7
+ - hasInteractiveStates
8
+ benchmark:
9
+ - Ant Design Upload (file list): github.com/ant-design/ant-design/tree/master/components/upload
10
+ - Polaris Thumbnail: github.com/Shopify/polaris/tree/main/polaris-react/src/components/Thumbnail
11
+ ---
12
+
13
+ <!-- @benchmark-cited: D5 retrofit 2026-05-18 — body claims marked per-claim @benchmark-unverified inline; canonical source URLs in frontmatter benchmark list. -->
14
+
15
+ # FileItem 設計原則
16
+
17
+ **檔案上傳列表項目**——顯示檔案名稱、上傳進度、狀態(uploading / completed / error)。
18
+
19
+ **實作基礎**:組合元件——Icon + Text + ProgressBar + Button,無 external primitive base。
20
+
21
+ **Layout Family**:CLAUDE.md 4-Family Model **Family 2(List item layout)** 消費者。結構繼承 `patterns/element-anatomy/item-anatomy.spec.md`「List item layout」章節的 reading-mode 規格。FileItem 在 rich mode 用 avatar 作 item boundary。
22
+
23
+ **命名 rationale**:`compact / rich` 表達精簡 vs 完整內容呈現(對齊 Discord embed type='rich' / Slack rich preview / Notion rich text 世界級 idiom)。不叫 `lg/sm`——兩者是資訊量不同的展示策略,不是同一結構的尺寸縮放。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
24
+
25
+ ---
26
+
27
+ ## 何時用
28
+
29
+ - **檔案上傳清單**:drag-drop upload、multiple file selector 的選中檔案列表
30
+ - **附件展示**:email / comment / ticket 的附件列表(rich mode 顯示縮圖 + 檔名)
31
+ - **批次處理進度**:CSV / JSON 匯入的逐檔進度追蹤(compact mode,預設)
32
+ - **上傳錯誤回報**:顯示哪些檔案失敗 + 重試按鈕
33
+
34
+ ## 何時不用
35
+
36
+ | 場景 | 改用 | 原因 |
37
+ |------|------|------|
38
+ | 只是顯示已上傳檔名(純連結)| `LinkInput` / plain `<a>` | FileItem 承載 upload 狀態,靜態連結不需要 |
39
+ | 下載進度(不是上傳)| 自訂 download 元件 | FileItem 專為 upload 流程設計,下載有不同 UX(瀏覽器原生)|
40
+ | 照片 / 影片 gallery | Grid / Carousel | Gallery 需要預覽 grid 佈局,FileItem 是 list 單行 |
41
+ | 資料夾階層 | `TreeView` | FileItem 是平面列表,階層用 tree |
42
+
43
+ ---
44
+
45
+ ## Mode
46
+
47
+ | Mode | Prefix | Typography | 適用場景 |
48
+ |---|---|---|---|
49
+ | `compact`(預設) | Paperclip icon 16px | 掃描模式 | 批次上傳的一般檔案(CSV、JSON) |
50
+ | `rich` | Avatar 48px square(固定) | 閱讀模式(ListItem md) | 需要縮圖預覽的檔案(圖片、文件) |
51
+
52
+ compact 為預設——多數 upload 清單是「快速掃視多檔」場景,只有需要縮圖預覽才升級為 rich。
53
+
54
+ ## Typography(兩 mode 都 scanning typography · 2026-04-23 user 指示)
55
+
56
+ **兩 mode 統一 scanning typography**(row 帶 `leading-compact`,對齊 MenuItem / Steps 的 Family 1 scanning idiom):
57
+
58
+ | | compact | rich |
59
+ |---|---|---|
60
+ | label | text-body (14px) + `leading-compact` (1.3) | text-body (14px) + `leading-compact` (1.3) |
61
+ | description | text-caption (12px) + `leading-compact` | text-caption (12px) + `leading-compact` |
62
+ | ItemContent `mode` | `"scanning"` | `"scanning"` |
63
+ | Gap token | `--item-gap-label-desc-scanning` | `--item-gap-label-desc-scanning` |
64
+
65
+ **為什麼兩 mode 都 scanning**:FileItem 是檔案列表 row — 使用者需快速掃視多檔(Gmail attachment / Google Drive 清單),掃描 typography 視覺緊湊符合語義。Rich mode 保留 Avatar 48 thumbnail 作視覺引導,但文字層採 scanning idiom。
66
+
67
+ ## 結構(2026-04-23 修正對齊 item-anatomy canonical)
68
+
69
+ ### 共通 layout invariants(兩 mode 都遵守)
70
+
71
+ | 間距 | 值 | 來源 canonical |
72
+ |------|-----|--------------|
73
+ | **Label ↔ Description gap** | `--item-gap-label-desc-scanning`(2px,scanning mode)— FileItem 走 scanning typography(掃視密集列表) | `patterns/element-anatomy/item-anatomy.spec.md`「Label ↔ Desc 間距 / 4 token 矩陣」+ primitive `<ItemContent mode="scanning">` |
74
+ | **Content ↔ ProgressBar gap** | `gap-2`(8px) | 兩 mode 一致(compact 用 py-2 + absolute 自然達成;rich 用 explicit flex-col gap-2) |
75
+ | **Suffix 高度**(小 suffix,icons ≤24) | `h-[1lh]` + items-center inline 對齊 label 第一行 | `patterns/element-anatomy/item-anatomy.spec.md`「24px 閾值對齊規則」 |
76
+
77
+ ### compact(預設)
78
+
79
+ ```
80
+ [📎] [ label
81
+ ↓ --item-gap-label-desc-scanning (2px,scanning mode md)
82
+ desc? ] [suffix h-[1lh]]
83
+ [ ██████████░░ ] ← 底部 progress bar(absolute,content 與 bar ≈ 8px gap)
84
+ ```
85
+
86
+ ### rich(完整呈現)
87
+
88
+ ```
89
+ [Avatar 48 square [ label ─────────────────── ↑ label top = avatar top
90
+ 固定,top-align ↓ --item-gap-label-desc-scanning (2px,scanning mode md)
91
+ 作視覺引導] desc ] [suffix h-[1lh]]
92
+ ↓ 自動填滿餘空間(min 8px gap)
93
+ [ ██████████░░ ] ────────── ↓ bar bottom = avatar bottom(1-line 時)
94
+ ```
95
+
96
+ ### Rich layout invariant(2026-04-23 user 校準)
97
+
98
+ **1-line desc 時**:
99
+ - Content col `minHeight = AVATAR_SIZE (48)` + `justify-between` + `gap-2`
100
+ - **label 頂 = avatar 頂**(row `items-start`)
101
+ - **progress bar 底 = avatar 底**(minHeight + justify-between 的剩餘空間分配)
102
+ - 中間 gap 自動填(label+desc+bar 總高 < 48 時,剩餘空間成為 gap,至少 `gap-2`=8px)
103
+
104
+ **multi-line desc 時**:
105
+ - Content 自然高度超過 avatar 48
106
+ - Progress bar 溢出 avatar 底(正常語義:內容撐長了)
107
+ - **desc ↔ progress bar 保持 8px min gap**(`gap-2` 強制)
108
+
109
+ **無 progress bar 時**:`justify-center` 取代 `justify-between`,content 垂直置中對齊 avatar 中心。
110
+
111
+ ### Rich Avatar 對齊的明文例外(上游 item-anatomy 24px 規則的例外)
112
+
113
+ item-anatomy「> 24 prefix + 有 desc」規則要求 prefix 對齊 content 塊**中心**(items-center)。
114
+ FileItem rich **刻意不遵守**這條,使用 `items-start`(top-align),原因:
115
+
116
+ > **當 FileItem rich 被放在「檔案上傳管理 box」等 tight-stack 情境**(consumer 移除 border 並 0 gap 相連時),avatar 作為**每個 item 的視覺邊界引導**——若 avatar 中心對齊,連續 item 的 avatar 會擠在一起失去「每筆檔案一個 thumbnail」的視覺節奏。top-align 讓 avatar 明確標示每個 item 的起點。
117
+
118
+ ### Avatar 尺寸(固定 48px)
119
+
120
+ Avatar **固定 48px square**,不隨 content 高度變化。content(label + desc + bar)可自然 > 48(2-line desc 時)或 < 48(無 desc + 無 bar 時),avatar 始終 48。
121
+
122
+ ## Padding
123
+
124
+ | Mode | 規則 |
125
+ |---|---|
126
+ | compact(預設) | 消費 item-layout 公式(py 隨 size / density 變化,padding / gap 對齊 menu item 規格) |
127
+ | rich | py 固定(高度由 avatar 決定,不走 row 公式),padding / gap 採 rich 專屬 token(具體值見 `file-item.tsx` cva) |
128
+
129
+ ## 邊框 / 背景(AR15-21 canonical,2026-04-21 · 2026-04-22 擴充)
130
+
131
+ | Mode | 容器視覺 | Rationale |
132
+ |------|---------|-----------|
133
+ | **rich**(所有 status) | `border border-divider rounded-md bg-surface` | Rich mode **永遠是「檔案 card」**,不因 status 改變——Slack / Notion / Linear attachment 皆獨立 card;邊框讓每個 row 視覺上是自立單元 |
134
+ | **compact + 有 progress**(上傳中 / 類 Upload manager 完成態) | 無背景、無邊框,只靠 progress bar 提供 affordance | 「正在發生」/「剛發生」的動態 narrative,progress 本身就是視覺焦點 |
135
+ | **compact + 無 progress**(form attachment 靜態態) | `bg-secondary rounded-md`(= neutral-3 色) | 靜態清單(form / 訊息附件)背景色區隔出「檔案 row」邊界,跟純文字內容區分。**為何 `bg-secondary` 不 `bg-neutral-3`**:`--secondary` 是 semantic token 經 `@theme inline` 橋接成合法 Tailwind utility,`--color-neutral-3` 是 primitive token(僅 `:root` CSS var)不生成 utility,寫 `bg-neutral-3` 會 silent 失效。對齊 Badge low / ProgressBar track SSOT(同色) |
136
+
137
+ ### Hover 行為 canonical(2026-04-23)
138
+
139
+ **FileItem 永不顯示 hover-bg**,不論 mode / status / onClick。affordance 只靠 `cursor-pointer`(onClick 存在時)+ actions icon / hover-swap(status slot icon fade → action icon fade)。
140
+
141
+ **Rationale(permanent visual anchor → 不加 hover-bg double-emphasis)**:
142
+
143
+ | Mode | 永久 visual anchor | 加 hover-bg 後果 |
144
+ |------|-------------------|-----------------|
145
+ | rich | `border + rounded-md + bg-surface` 永遠 card | card + hover-bg = 雙層強調,視覺 heavy |
146
+ | compact Type B(無 status) | `bg-secondary rounded-md` 永遠 pill | pill bg + hover-bg neutral-hover 兩層相近灰,視覺雜 |
147
+ | compact Type A(uploading / error / completed with bar) | 底部 2px progress bar(分隔線型 permanent affordance) | bar + hover-bg 同時並存,affordance 重複 |
148
+
149
+ 三種型態**都已 anchored**,hover-bg 是多餘的視覺層。Cursor + click 本身已是足夠互動 affordance,世界級檔案 card / attachment 皆如此。
150
+
151
+ **世界級對照**(M8 / M12 benchmark):
152
+
153
+ | DS | File card / attachment hover 行為 | 跟本 canonical 對齊? |
154
+ |----|----------------------------------|----------------------|
155
+ | Slack file tile | border highlight,**無 bg 變化** | ✓ |
156
+ | Notion file callout | **無 bg 變化**,action icons fade in | ✓ |
157
+ | Figma file card | shadow lift,**無 bg 變化** | ✓ |
158
+ | Gmail attachment chip | **無 bg 變化**,download icon fade in | ✓ |
159
+ | Dropbox / Google Drive file **row**(flush transparent 無 permanent anchor) | **有** hover-bg | Opposite case(證明 canonical:anchored → 無、flush → 有) |
160
+
161
+ **跟 MenuItem / DataTable row 對比**(它們用 hover-bg):兩者是 **flush transparent row**(無 permanent bg / border),hover-bg 是唯一 affordance。FileItem 三種型態皆已 anchored → 反向 canonical。
162
+
163
+ **反例**(本 session 修正):
164
+ - 原 code `hoverClass = onClick ? 'cursor-pointer hover:bg-neutral-hover' : ''` → rich card 上 hover 多一層灰 bg 雙層強調;Type B pill 上 hover 加 `bg-neutral-hover` 跟 pill 底色近似造成視覺雜
165
+ - 修為 `hoverClass = onClick ? 'cursor-pointer' : ''`
166
+
167
+ **❌ 反例**:
168
+ - Rich mode 無邊框 → 與一般 list item 無法區分,跟 MenuItem 混淆
169
+ - Compact mode 靜態 item 無 bg → 純文字列,使用者不知這是「可點下載的檔案」
170
+ - 外層 list wrapper 加邊框 / `overflow-hidden` → 雙重邊框(list 邊框 + item card 邊框)視覺干擾;並強制邊框相黏破壞 card 自立性(2026-04-22 user 糾正)
171
+
172
+ ---
173
+
174
+ ## 可下載狀態 canonical(2 use case)
175
+
176
+ **核心區分**:「檔案可下載」不是單一 state,而是 **2 種使用場景**,各自有 prop signature + 視覺節奏。
177
+
178
+ ### Type A — Upload manager(Google Drive / Dropbox 類上傳管理 box)
179
+
180
+ **語意**:上傳流程的延續——完成後**仍保留 progress + status narrative**,使用者能回顧「這檔剛被上傳且已完成」。
181
+
182
+ | 屬性 | 值 |
183
+ |------|---|
184
+ | `status` | `"completed"`(持續保留,不清除) |
185
+ | Progress bar | 100% 完成條(不隱藏) |
186
+ | Status icon | 綠 ✓(passive) |
187
+ | hover 行為 | **status slot hover-swap**:✓ → Download ↓(icon button)觸發 `onDownload` |
188
+ | **Row-click**(= Type B 行為) | **推薦**:consumer 傳 `onClick` 讓整 row 可點 → **預設用 FileViewer 開啟**(consumer 決定,也可直接下載)。Hover-swap + Row-click 可並存。 |
189
+ | Rich 背景 | `border card`(永遠) |
190
+ | Compact 背景 | 無(progress bar 還在) |
191
+ | 刪除按鈕 | optional(業務權限) |
192
+
193
+ ```tsx
194
+ <FileItem
195
+ mode="rich"
196
+ name="report.pdf"
197
+ status="completed"
198
+ onDownload={() => download(id)}
199
+ actions={<Button size="xs" iconOnly variant="text" startIcon={Trash2} onClick={del} aria-label="刪除" />}
200
+ />
201
+ ```
202
+
203
+ ### Type B — Form attachment(表單 / 訊息附件靜態態)
204
+
205
+ **語意**:附件列表——檔案「已經在那」,不再是 upload 動作的延續。
206
+
207
+ | 屬性 | 值 |
208
+ |------|---|
209
+ | `status` | **`undefined`**(不傳;無 progress / 無 status icon) |
210
+ | Progress bar | 無 |
211
+ | Status icon | 無 |
212
+ | hover 行為 | 整 row `hover:bg-neutral-hover` + cursor-pointer |
213
+ | Row-click | **`onClick` 為主要 affordance** → **預設 FileViewer 開啟**(consumer 決定,也可下載) |
214
+ | Rich 背景 | `border card`(永遠) |
215
+ | Compact 背景 | `bg-secondary`(區隔「這是檔案 row」;primitive `--color-neutral-3` 的 semantic 橋接名,見邊框 / 背景章節) |
216
+ | 刪除按鈕 | optional(業務權限) |
217
+
218
+ ```tsx
219
+ <FileItem
220
+ mode="compact"
221
+ name="report.pdf"
222
+ description="2.3 MB"
223
+ onClick={() => openViewer(id)}
224
+ actions={hasDeletePermission ? <ItemInlineActionButton icon={Trash2} size="sm" onClick={del} /> : undefined}
225
+ />
226
+ ```
227
+
228
+ **選用判斷**:
229
+ - 上傳剛發生 / 還在 upload box 情境 → Type A(保留 narrative)
230
+ - 檔案進駐表單 / 留言 / 既有資料 → Type B(靜態)
231
+
232
+ ### Description ReactNode 可含 clickable 元素
233
+
234
+ Description 是 ReactNode,**不限純文字**。常見場景:
235
+ - Error 描述含 "View log" 需可點 → 用 `<a className="underline">View log</a>` 或 inline Button:
236
+
237
+ ```tsx
238
+ <FileItem
239
+ mode="compact"
240
+ name="backup-failed.json"
241
+ status="error"
242
+ description={
243
+ <>
244
+ Network timeout.{' '}
245
+ <a href="#logs" className="underline hover:text-error-hover">View log</a>
246
+ </>
247
+ }
248
+ onRetry={noop}
249
+ />
250
+ ```
251
+
252
+ 視覺上 underline + hover 色變讓使用者知道「那段文字可點」。
253
+
254
+ ### 不可混用 invariants
255
+
256
+ **Invariant 1 — rich 跟 compact 不可混用**:
257
+ 同一 list 內**只能一種 mode**。rich 是「檔案 card」視覺語言(border + avatar + 完整 metadata),compact 是「掃視密集列表」視覺語言(paperclip + filename),兩者並排會:
258
+ - 高度差異過大(rich ~72px / compact ~36px)破壞 row rhythm
259
+ - Avatar vs paperclip prefix 視覺語言衝突
260
+ - consumer 要混用代表情境定位不清 —— 選一種
261
+
262
+ **Invariant 2 — Type A completed 跟 Type B 不共存**:
263
+ Type A completed(100% bar + ✓)屬「剛完成的 upload session」視覺;Type B(無 bar)屬「已存 attachment」視覺 —— 業務語義互斥。完成後 consumer 會把 item 轉成 Type B(移除 status 屬性),不會同時顯示「completed with bar」+「無 bar」。
264
+
265
+ **合法 mixed 情境**(email 草稿 / 多步驟 upload flow):Type A **active**(`uploading` / `error`)+ Type B(saved attachments)— 只在 **compact mode 內**。
266
+
267
+ ---
268
+
269
+ ## List wrapper canonical(多 item 間距)
270
+
271
+ `FileItem` 連續排列時 list wrapper gap,**統一規則**(2026-04-23 簡化,user 指示):
272
+
273
+ | Mode | List wrapper gap | Rationale |
274
+ |------|----------------|-----------|
275
+ | **Rich**(單一 mode list) | `gap-2`(8px) | card 邊框不相黏(standalone card invariant) |
276
+ | **Compact**(單一 mode list,所有情境) | `gap-1`(4px) | 統一 — 不論 Type A only / Type B only / Type A+B mixed,都用 gap-1 簡化 canonical。Type A 無 bg 的 0-gap 選項已捨棄,簡化 consumer 心智負擔 |
277
+
278
+ **Rich + Compact 不可混用**(見 Invariant 1 上方),故無「混用 gap」決策。
279
+
280
+ ### List wrapper 本身不加視覺
281
+
282
+ **規則**(2026-04-22 user 直指):FileItem 各自 own 視覺(rich card / compact bg),list wrapper 只負責垂直排列 + gap。**不應該有外框**(無 `border` / 無 `rounded-*` / 無 `overflow-hidden`)— 否則:
283
+ - FileItem rich 自帶 card,list 再加外框 → 雙重 card
284
+ - 強制邊框合併(user 2026-04-22 指出的 `border rounded-lg overflow-hidden` 反例)
285
+
286
+ ```tsx
287
+ // ✅ Rich list
288
+ <div className="flex flex-col gap-2">
289
+ {files.map(f => <FileItem key={f.id} mode="rich" {...f} />)}
290
+ </div>
291
+
292
+ // ✅ Compact Type B(form attachment,靜態灰底)
293
+ <div className="flex flex-col gap-1">
294
+ {files.map(f => <FileItem key={f.id} mode="compact" {...f} />)}
295
+ </div>
296
+
297
+ // ✅ Compact Type A only(upload manager,全有 status)
298
+ <div className="flex flex-col">
299
+ {files.map(f => <FileItem key={f.id} mode="compact" status={f.status} progress={f.progress} {...f} />)}
300
+ </div>
301
+
302
+ // ✅ Compact mixed Type A + Type B(email 草稿、舊附件 + 新上傳)
303
+ <div className="flex flex-col gap-1">
304
+ {allFiles.map(f => <FileItem key={f.id} mode="compact" status={f.isUploading ? 'uploading' : undefined} {...f} />)}
305
+ </div>
306
+
307
+ // ❌ 反例:list 加外框 + overflow-hidden(雙重 card / 強制邊框相黏)
308
+ <div className="flex flex-col border rounded-lg overflow-hidden">
309
+ {files.map(f => <FileItem key={f.id} mode="rich" {...f} />)}
310
+ </div>
311
+ ```
312
+
313
+ **Clickable → 下載 / 預覽 canonical**(AR15):
314
+ - FileItem 提供 `onClick` prop,consumer 傳入即進 clickable 模式(hover + cursor + keyboard)
315
+ - Type A / Type B 都可以用 `onClick`(Type A 可跟 `onDownload` hover-swap 並存)
316
+ - consumer 決定具體行為(download / FileViewer),元件只提供 row 可點擊能力
317
+
318
+ ## ProgressBar
319
+
320
+ **SSOT**:FileItem 不自 roll bar,消費 `../ProgressBar/progress-bar.spec.md` 元件(Radix Progress 包裝 + 本 DS token)。避免視覺漂移。
321
+
322
+ | 屬性 | 值 | 依據 |
323
+ |---|---|---|
324
+ | 消費元件 | `<ProgressBar status={...} value={...} height={compact ? 2 : undefined} />` | 本 DS ProgressBar SSOT(公開 API 固定 4px;`height` 是 internal-only 逃生艙,FileItem 為唯一合法 consumer) |
325
+ | status 映射 | `uploading → inProgress` / `completed → success` / `error → error` | ProgressBar `status` 原生支援 |
326
+ | height 映射 | `compact → 2px` / `rich → 4px`(預設) | compact mode 極密集 row layout 需要更細 track;rich mode 走 DS 預設 4px |
327
+ | value | `status === 'completed' ? 100 : progress` | completed 永遠 100% |
328
+
329
+ 改動進度條視覺(高度 / 色 / 動畫) → 去 ProgressBar 改,**本元件無本地 bar 實作**。
330
+
331
+ ## Actions(suffix,row dedicated region canonical)
332
+
333
+ Consumer 自行組合。按 `patterns/element-anatomy/item-anatomy.spec.md`「Predicate」+「Row action 絕對值 cap」,**row dedicated action 絕對值 cap = ≤ 24px,不隨 row tier 放大**。依 row 高度分兩種實作:
334
+
335
+ | Mode | Row 高度 | 實作 | 尺寸 |
336
+ |------|---------|------|------|
337
+ | `rich` | 56 (≥ 28) | **Button iconOnly `size="xs"`**(24 固定,不隨 row 放大) | 24 |
338
+ | `compact` | 24 | **ItemInlineActionButton**(row 太小容不下 Button xs 24,會填滿 row 無呼吸) | icon 16, hover-bg 22 |
339
+
340
+ ```tsx
341
+ // Rich(row 56)→ Button xs iconOnly 固定 24(≤ 24 cap)
342
+ <FileItem actions={
343
+ <Button size="xs" iconOnly variant="text" startIcon={Trash2} aria-label="刪除" onClick={del} />
344
+ } />
345
+
346
+ // Compact(row 24)→ Inline Action(因 Button xs 24 會填滿 row)
347
+ <FileItem actions={
348
+ <ItemInlineActionButton icon={Trash2} size="sm" aria-label="刪除" onClick={del} />
349
+ } />
350
+ ```
351
+
352
+ **為什麼 Row ≥ 28 用 Button xs 固定**:row 放大不代表 action 要放大——世界級 DS(Material DataGrid / Polaris / Atlassian / Apple HIG)row action 都是固定小 icon button(20–24),row 高度變化只影響 row padding 與 content,不影響 action 尺寸。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
353
+
354
+ **為什麼 Row ≤ 24 用 Inline Action**:compact row 高度 24 裝不下 Button xs(24)——Button 會填滿整個 row,失去 row padding 與 icon 呼吸空間。Inline Action(icon 16 + hover-bg 22)剛好符合「action ≤ row - padding」的呼吸需求。
355
+
356
+ **Trash/Delete 不是 dismiss 語意**:`dismiss` 嚴格保留給「X close overlay session」(Dialog / Sheet / Popover / Alert close X)。Row 的 Trash/Delete 語意是 `onRemove`(從集合移除一個 item,見 `.claude/rules/ui-development.md`「元件 Props 命名」「onRemove」),**不套 Button `dismiss` prop**:
357
+ - Rich mode Button `variant="text"` 預設 icon 已是 fg-muted → foreground,hover 弱化視覺自然呈現
358
+ - Compact mode ItemInlineActionButton 本來就 fg-muted → foreground(Inline Action default)
359
+
360
+ 參見 `patterns/element-anatomy/item-anatomy.spec.md`「Predicate」+「Real case 表」+「Row action 絕對值 cap」。
361
+
362
+ ## Status ↔ Action hover-swap(passive → active affordance)
363
+
364
+ **世界級 UX pattern**(Gmail / Slack / Dropbox 附件 convention):status 預設是 passive 狀態標記(綠 ✓ / 紅 ✗),使用者 hover 整個 row 時,**狀態 icon 自動換成「相應的操作」**,click 即觸發:
365
+
366
+ | status | Passive icon | Hover 換成 | Consumer handler |
367
+ |--------|-------------|-----------|------------------|
368
+ | `completed` | `CircleCheck` 綠 ✓ | `Download ↓` | `onDownload` |
369
+ | `error` | `XCircle` 紅 ✗ | `RotateCw ⟲` | `onRetry` |
370
+ | `uploading` | *(progress %)* | *(無 swap)* | — |
371
+
372
+ **幾何一致性(2026-04-22 canonical · row action ≤ 24 cap)**:status slot 容器大小 **= consumer 的 delete action 尺寸**:
373
+ - `mode="rich"` → `var(--field-height-xs)`(24 固定,與 Button xs iconOnly 同)
374
+ - `mode="compact"` → 16px(與 ItemInlineActionButton icon 同)
375
+
376
+ Passive status icon 置中於 action-sized 容器,hover 時 active action 填滿同一容器。這讓 flex gap token 測量的是**兩個同尺寸 action slot 之間的真實 gap**,不被 hover bg overflow 吃掉——status slot 尺寸 = 同 size delete slot,gap token 才能如實呈現;歷史 bug 細節見 CLAUDE.md `# 失敗記憶索引`。
377
+
378
+ 世界級 DS 的幾何鐵律:**同一 flex 列的互動元素必須有統一 box 尺寸**,gap token 才能如實呈現。
379
+
380
+ **Backward compat**:consumer 若沒傳 `onDownload` / `onRetry`,status icon 永遠保持 passive(不響應 hover)——既有使用者無感。
381
+
382
+ **為什麼值得這麼做**:
383
+ - passive 階段清楚告知使用者檔案狀態(✓ / ✗ 顏色強訊號)
384
+ - hover 階段立即提供相應行動(completed → 下載 / error → 重試),不需另外挪位置做按鈕
385
+ - 符合「改一處看多處」的 design system primitive 思維:passive + active 共用 slot,不讓使用者多認一處
386
+
387
+ ```tsx
388
+ <FileItem
389
+ mode="rich"
390
+ name="report.pdf"
391
+ status="completed"
392
+ onDownload={() => downloadFile(id)} // hover ✓ → ↓
393
+ actions={<Button size="xs" iconOnly variant="text" startIcon={Trash2} onClick={del} aria-label="刪除" />}
394
+ />
395
+
396
+ <FileItem
397
+ mode="compact"
398
+ name="backup.json"
399
+ status="error"
400
+ description="There's something wrong."
401
+ onRetry={() => retryUpload(id)} // hover ✗ → ⟲
402
+ actions={<ItemInlineActionButton icon={Trash2} size="sm" onClick={del} aria-label="刪除" />}
403
+ />
404
+ ```
405
+
406
+ ## Suffix 24px 閾值
407
+
408
+ | Mode | 最大 suffix 元素 | 有 desc 時 | alignment |
409
+ |---|---|---|---|
410
+ | compact(預設) | Button xs = 24px ≤ 24px | — | `h-[1lh]` inline |
411
+ | rich | Button sm = 28px > 24px | block | `h-[calc(1lh+2px+desc_lh)]` |
412
+
413
+ ## A11y 預設
414
+
415
+ - **`aria-busy` for uploading**:`status="uploading"` 時 row 自動 `aria-busy="true"`,SR 朗讀「busy」避免 user 嘗試互動已 in-flight item。
416
+ - **Error state live region**:`status="error"` row 自動 `role="status"` + `aria-live="polite"`,error 訊息(label + description)即時 announce,user 不用主動 navigate 過去。`polite` 不打斷既有 SR 朗讀,適合 file upload 非緊急情境。
417
+ - **Action button labels**:Download / retry / remove 等 inline action 必傳 `aria-label`(中文 / consumer locale)— 「下載 report.pdf」/「重試上傳」/「移除附件」,單純「下載」/「刪除」缺檔名 context SR user 無法區分多 row。
418
+ - **ProgressBar 整合**:消費的 `<ProgressBar>` 自帶 `role="progressbar"` + `aria-valuenow` / `aria-valuemax`,本元件不再重複;keyboard 不需 focus progress bar(被動指示器,非互動元素)。
419
+ - **Row clickable**:傳 `onClick` 時自動 `role="button"` + `tabIndex=0` + Enter / Space activate,keyboard user 與 mouse user 等價可達 FileViewer / download。
420
+ - **Status icon hover-swap a11y**:hover-swap 不改變 SR 語意 — passive icon `aria-hidden`,active action button 自帶 `aria-label`,避免 SR user 收到視覺 swap 噪音。
421
+
422
+ ---
423
+
424
+ ## 與 FileUpload 的分界
425
+
426
+ | 元件 | 職責 | 場景 |
427
+ |------|------|------|
428
+ | **FileItem** | 單一檔案 row primitive — 顯示一個檔案的 name / status / progress / actions | List 內的單筆 / detail / preview / message attachment |
429
+ | **FileUpload** | Dropzone + file list orchestrator — 拖放區 + 多 FileItem 排列 + 上傳狀態管理 | 完整上傳流程入口 |
430
+
431
+ **判斷**:
432
+
433
+ - **完整上傳流程**(drag-drop / validate / list multiple files)→ 用 `FileUpload`(內部消費多個 `FileItem`)
434
+ - **單一檔案展示 / preview**(message bubble 附件 / detail page header / FileViewer 觸發點)→ 直接用 `FileItem`
435
+ - **Form attachment field**(留言區附件、ticket attachments)→ 視場景:有上傳行為走 `FileUpload`,只展示既有附件走 `FileItem` list(Type B)
436
+
437
+ **簡單記**:**有 dropzone 用 FileUpload,沒 dropzone 用 FileItem**。FileItem 不應自帶 dropzone(會跟 FileUpload 重複職責)。
438
+
439
+ ---
440
+
441
+ ## 禁止事項
442
+
443
+ - ❌ **不用 FileItem 做 generic list row**(menu / settings 列表 / nav)→ 改 `MenuItem`。FileItem prefix(paperclip / Avatar 48 thumbnail)、status pattern(uploading / error)、ProgressBar slot 都是檔案專屬語義,套到 generic row 會視覺 / 語意誤導。
444
+ - ❌ **不用 FileItem 做 selection picker**(選檔案、選 template)→ 改 `Combobox` / `Select` / `Listbox`。FileItem 設計是「展示已存在的檔案 row」,不是「從候選池挑一個」;hover / selected state 與 picker 語義不對齊。
445
+ - ❌ **不在 FileItem 內塞自組 ProgressBar**(`<div className="bg-primary h-1" style={{width: `${progress}%`}} />`)→ 必消費內建 `<ProgressBar>` SSOT。自組會視覺漂移(高度 / 動畫 / status 色不一致)+ 失去 a11y attributes。
446
+ - ❌ **不混用 rich + compact 在同一 list**(詳「Invariant 1」)— 高度差破壞 row rhythm,prefix 視覺語言衝突。
447
+ - ❌ **不用 FileItem 做下載進度**(瀏覽器原生下載 UX 已足夠)— FileItem 為 upload narrative 設計,download progress 走自訂元件。
448
+
449
+ ---
450
+
451
+ ## 為何無 Inspector
452
+
453
+ FileItem 決策維度是 `mode`(compact / rich)× `status`(uploading / completed / error / static)× `size`——已在 `ColorMatrix` / `ModeMatrix` / `SizeMatrix` / `StateBehavior` 四張矩陣完整覆蓋。互動 Inspector 不會比結構性矩陣對照更有教學價值——「選 mode 的 test / 選 status 的 test」是需要 side-by-side 比對的決策,不是單值試玩。
454
+
455
+ ColorMatrix 已建:展示 status × 元素(filename / description / progress bar / status icon)色彩矩陣,明示 status 只驅動 **progress bar + status icon + description** 升階,**不染容器背景**(避免整 row 轉紅蓋過其他 metadata)。Container hover / selected / disabled 則走 item-anatomy row primitive SSOT。
456
+
457
+ ---
458
+
459
+ ## 相關
460
+
461
+ - `../../patterns/element-anatomy/item-anatomy.spec.md` — 閱讀模式(compact / rich)
462
+ - `../Avatar/avatar.spec.md` — Avatar shape(rich mode 的 icon 容器)
463
+ - `../FileUpload/file-upload.spec.md` — **配對元件**:FileUpload 是拖放 / 點擊上傳區塊,FileItem 是已上傳檔案 row 顯示;兩者構成完整 file-handling 元件組
464
+ - `../LinkInput/link-input.spec.md` — 純連結(非 upload 流程)替代
465
+ - `../TreeView/tree-view.spec.md` — 階層 file structure 場景
466
+ - `../ProgressBar/progress-bar.spec.md` — ProgressBar SSOT(FileItem consumes ProgressBar for upload bar)
467
+ - `../../tokens/color/color.spec.md` — Track 底色(`bg-secondary` 使用原則)