@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.
- package/CLAUDE.md +201 -0
- package/README.md +7 -15
- package/cli-init.mjs +90 -0
- package/ds-canonical/commands/README.md +26 -0
- package/ds-canonical/commands/gov-status.md +79 -0
- package/ds-canonical/hooks/README.md +145 -0
- package/ds-canonical/hooks/_log-fire.sh +44 -0
- package/ds-canonical/hooks/block_prototype_imports.py +111 -0
- package/ds-canonical/hooks/check_app_shell_primary_header_consistency.sh +68 -0
- package/ds-canonical/hooks/check_audit_post_report_validator.sh +88 -0
- package/ds-canonical/hooks/check_audit_sample_escape.sh +73 -0
- package/ds-canonical/hooks/check_benchmark_citation.sh +106 -0
- package/ds-canonical/hooks/check_canonical_propagation.sh +189 -0
- package/ds-canonical/hooks/check_chrome_header_handcraft.sh +70 -0
- package/ds-canonical/hooks/check_codex_brief_invariants.sh +83 -0
- package/ds-canonical/hooks/check_codex_collab_5step.sh +108 -0
- package/ds-canonical/hooks/check_datatable_invariants.sh +117 -0
- package/ds-canonical/hooks/check_dim_count_drift.sh +72 -0
- package/ds-canonical/hooks/check_field_controls_contracts.sh +110 -0
- package/ds-canonical/hooks/check_field_family_invariants.sh +205 -0
- package/ds-canonical/hooks/check_file_size_budget.sh +60 -0
- package/ds-canonical/hooks/check_header_with_tabs_border.sh +87 -0
- package/ds-canonical/hooks/check_main_branch_workbench.sh +93 -0
- package/ds-canonical/hooks/check_naming_and_abstraction.sh +165 -0
- package/ds-canonical/hooks/check_opacity_token_usage.sh +149 -0
- package/ds-canonical/hooks/check_pattern_invariants.sh +194 -0
- package/ds-canonical/hooks/check_peoplepicker_ssot_drift.sh +56 -0
- package/ds-canonical/hooks/check_pixel_quantified_audit.sh +53 -0
- package/ds-canonical/hooks/check_propose_plain_chinese.sh +74 -0
- package/ds-canonical/hooks/check_propose_pre_grep_verify.sh +70 -0
- package/ds-canonical/hooks/check_select_all_canonical.sh +58 -0
- package/ds-canonical/hooks/check_solo_workflow.sh +258 -0
- package/ds-canonical/hooks/check_spec_class_drift.sh +88 -0
- package/ds-canonical/hooks/check_story_invariants.sh +612 -0
- package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +105 -0
- package/ds-canonical/hooks/check_tab_lg_chrome_header_equal.sh +66 -0
- package/ds-canonical/hooks/check_wrapper_primitive_schema_drift.sh +104 -0
- package/ds-canonical/hooks/enforce_home_charter.sh +44 -0
- package/ds-canonical/hooks/inject_pending_self_audit.sh +204 -0
- package/ds-canonical/hooks/lib/_approval_re.sh +33 -0
- package/ds-canonical/hooks/lib/_code_quality.sh +73 -0
- package/ds-canonical/hooks/lib/_cva_default_sync.sh +69 -0
- package/ds-canonical/hooks/lib/_governance_coverage_check.sh +49 -0
- package/ds-canonical/hooks/lib/_hardcoded_strings.sh +163 -0
- package/ds-canonical/hooks/lib/_layout_space_canonical.sh +56 -0
- package/ds-canonical/hooks/lib/_overlay_handcraft.sh +141 -0
- package/ds-canonical/hooks/lib/_person_data_richness.sh +42 -0
- package/ds-canonical/hooks/lib/_story_compile_drift.sh +48 -0
- package/ds-canonical/hooks/lib/_token_hygiene.sh +95 -0
- package/ds-canonical/hooks/log_governance_fires.sh +50 -0
- package/ds-canonical/hooks/log_skill_invokes.sh +41 -0
- package/ds-canonical/hooks/post_edit_dispatcher.sh +62 -0
- package/ds-canonical/hooks/retired/check_anatomy_section_numbering.sh +106 -0
- package/ds-canonical/hooks/retired/check_avatar_hovercard.sh +90 -0
- package/ds-canonical/hooks/retired/check_button_icon_literal.sh.retired-2026-04-28 +38 -0
- package/ds-canonical/hooks/retired/check_container_breathing.sh +142 -0
- package/ds-canonical/hooks/retired/check_governance_compliance.sh +61 -0
- package/ds-canonical/hooks/retired/check_icon_only_padding_formula.sh +104 -0
- package/ds-canonical/hooks/retired/check_item_content_primitive.sh +150 -0
- package/ds-canonical/hooks/retired/check_item_list_gap.sh +153 -0
- package/ds-canonical/hooks/retired/check_sideoffset_canonical.sh +65 -0
- package/ds-canonical/hooks/retired/check_spec_iteration_tag.sh +87 -0
- package/ds-canonical/hooks/retired/check_ssot_consultation.sh +88 -0
- package/ds-canonical/hooks/retired/check_sync_update.sh +20 -0
- package/ds-canonical/hooks/retired/check_third_party_dom_verified.sh +95 -0
- package/ds-canonical/hooks/retired/enforce_home_charter.sh +125 -0
- package/ds-canonical/hooks/retired/post_edit_canonical_interrogate.sh +109 -0
- package/ds-canonical/hooks/retired/pre_edit_spec_check.sh +68 -0
- package/ds-canonical/hooks/retired/pre_new_component_spec.sh +39 -0
- package/ds-canonical/hooks/retired/pre_write_subsumption_check.sh +112 -0
- package/ds-canonical/hooks/retired/stop_meta_self_audit.sh.retired-2026-05-13 +76 -0
- package/ds-canonical/hooks/retired/tests/test_check_anatomy_section_numbering.sh +14 -0
- package/ds-canonical/hooks/retired/tests/test_check_avatar_hovercard.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_container_breathing.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_governance_compliance.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_icon_only_padding_formula.sh +79 -0
- package/ds-canonical/hooks/retired/tests/test_check_item_content_primitive.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_item_list_gap.sh +163 -0
- package/ds-canonical/hooks/retired/tests/test_check_sideoffset_canonical.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_spec_iteration_tag.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_ssot_consultation.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_sync_update.sh +14 -0
- package/ds-canonical/hooks/retired/tests/test_check_third_party_dom_verified.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_enforce_home_charter.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_pre_edit_spec_check.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_pre_new_component_spec.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_pre_write_subsumption_check.sh +63 -0
- package/ds-canonical/hooks/session_start_governance_check.sh +263 -0
- package/ds-canonical/hooks/stop_passive_logging.sh +322 -0
- package/ds-canonical/hooks/stop_self_audit.sh +450 -0
- package/ds-canonical/hooks/tests/KNOWN-BROKEN.md +15 -0
- package/ds-canonical/hooks/tests/run-all.sh +76 -0
- package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +143 -0
- package/ds-canonical/hooks/tests/test_check_app_shell_primary_header_consistency.sh +140 -0
- package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +115 -0
- package/ds-canonical/hooks/tests/test_check_audit_sample_escape.sh +93 -0
- package/ds-canonical/hooks/tests/test_check_benchmark_citation.sh +115 -0
- package/ds-canonical/hooks/tests/test_check_canonical_propagation.sh +133 -0
- package/ds-canonical/hooks/tests/test_check_chrome_header_handcraft.sh +123 -0
- package/ds-canonical/hooks/tests/test_check_code_quality.sh +15 -0
- package/ds-canonical/hooks/tests/test_check_codex_collab_5step.sh +96 -0
- package/ds-canonical/hooks/tests/test_check_cva_default_sync.sh +15 -0
- package/ds-canonical/hooks/tests/test_check_datatable_invariants.sh +122 -0
- package/ds-canonical/hooks/tests/test_check_dim_count_drift.sh +98 -0
- package/ds-canonical/hooks/tests/test_check_field_controls_contracts.sh +126 -0
- package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +194 -0
- package/ds-canonical/hooks/tests/test_check_file_size_budget.sh +32 -0
- package/ds-canonical/hooks/tests/test_check_hardcoded_strings.sh +14 -0
- package/ds-canonical/hooks/tests/test_check_header_with_tabs_border.sh +110 -0
- package/ds-canonical/hooks/tests/test_check_layout_space_canonical.sh +73 -0
- package/ds-canonical/hooks/tests/test_check_main_branch_workbench.sh +147 -0
- package/ds-canonical/hooks/tests/test_check_naming_and_abstraction.sh +136 -0
- package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +110 -0
- package/ds-canonical/hooks/tests/test_check_overlay_handcraft.sh +126 -0
- package/ds-canonical/hooks/tests/test_check_pattern_invariants.sh +148 -0
- package/ds-canonical/hooks/tests/test_check_peoplepicker_ssot_drift.sh +108 -0
- package/ds-canonical/hooks/tests/test_check_person_data_richness.sh +58 -0
- package/ds-canonical/hooks/tests/test_check_pixel_quantified_audit.sh +142 -0
- package/ds-canonical/hooks/tests/test_check_propose_plain_chinese.sh +126 -0
- package/ds-canonical/hooks/tests/test_check_propose_pre_grep_verify.sh +117 -0
- package/ds-canonical/hooks/tests/test_check_select_all_canonical.sh +125 -0
- package/ds-canonical/hooks/tests/test_check_solo_workflow.sh +201 -0
- package/ds-canonical/hooks/tests/test_check_spec_class_drift.sh +135 -0
- package/ds-canonical/hooks/tests/test_check_story_anatomy.sh.broken +197 -0
- package/ds-canonical/hooks/tests/test_check_story_category.sh.broken +187 -0
- package/ds-canonical/hooks/tests/test_check_story_compile_drift.sh +15 -0
- package/ds-canonical/hooks/tests/test_check_story_invariants.sh +209 -0
- package/ds-canonical/hooks/tests/test_check_story_name_jargon.sh.broken +53 -0
- package/ds-canonical/hooks/tests/test_check_story_slot_split.sh +156 -0
- package/ds-canonical/hooks/tests/test_check_substantive_edit_approval_preflight.sh +176 -0
- package/ds-canonical/hooks/tests/test_check_tab_lg_chrome_header_equal.sh +138 -0
- package/ds-canonical/hooks/tests/test_check_token_hygiene.sh +21 -0
- package/ds-canonical/hooks/tests/test_check_wrapper_primitive_schema_drift.sh +169 -0
- package/ds-canonical/hooks/tests/test_enforce_home_charter.sh +77 -0
- package/ds-canonical/hooks/tests/test_inject_pending_self_audit.sh +125 -0
- package/ds-canonical/hooks/tests/test_log_governance_fires.sh +10 -0
- package/ds-canonical/hooks/tests/test_log_skill_invokes.sh +7 -0
- package/ds-canonical/hooks/tests/test_post_edit_dispatcher.sh +108 -0
- package/ds-canonical/hooks/tests/test_session_start_governance_check.sh +143 -0
- package/ds-canonical/hooks/tests/test_stop_capture_metrics.sh +95 -0
- package/ds-canonical/hooks/tests/test_stop_governance_drift_check.sh.broken +125 -0
- package/ds-canonical/hooks/tests/test_stop_harvest_corrections.sh +10 -0
- package/ds-canonical/hooks/tests/test_stop_passive_logging.sh +100 -0
- package/ds-canonical/hooks/tests/test_stop_self_audit.sh +76 -0
- package/ds-canonical/hooks/tests/test_stop_tsc_sanity.sh +10 -0
- package/ds-canonical/references/README.md +43 -0
- package/ds-canonical/references/audit-coverage-vs-24-checklist.md +74 -0
- package/ds-canonical/references/build-ui-canonicals.md +69 -0
- package/ds-canonical/references/cva-patterns.md +41 -0
- package/ds-canonical/references/drag-canonical.md +331 -0
- package/ds-canonical/references/item-anatomy-recipe.md +225 -0
- package/ds-canonical/references/naming-conventions.md +56 -0
- package/ds-canonical/references/principle-dim-map.json +515 -0
- package/ds-canonical/references/props-naming.md +45 -0
- package/ds-canonical/references/spec-rules.md +58 -0
- package/ds-canonical/references/ssot-consultation.md +63 -0
- package/ds-canonical/references/ssot-index.md +40 -0
- package/ds-canonical/references/story-baseline-registry.json +79 -0
- package/ds-canonical/references/structural-token-retention.md +42 -0
- package/ds-canonical/references/tailwind-gotchas.md +87 -0
- package/ds-canonical/references/ui-dev-rules.md +60 -0
- package/ds-canonical/rules/README.md +34 -0
- package/ds-canonical/rules/meta-patterns.md +87 -0
- package/ds-canonical/rules/self-verify.md +53 -0
- package/ds-canonical/rules/spec-rules.md +25 -0
- package/ds-canonical/rules/story-rules.md +56 -0
- package/ds-canonical/rules/ui-development.md +87 -0
- package/ds-canonical/skills/README.md +88 -0
- package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +181 -0
- package/ds-canonical/skills/code-quality-audit/SKILL.md +63 -0
- package/ds-canonical/skills/codex-collab/SKILL.md +249 -0
- package/ds-canonical/skills/codex-collab/references/brief-template.md +48 -0
- package/ds-canonical/skills/codex-collab/references/transport.md +58 -0
- package/ds-canonical/skills/codify-corrections/SKILL.md +184 -0
- package/ds-canonical/skills/codify-principle/SKILL.md +151 -0
- package/ds-canonical/skills/component-quality-gate/SKILL.md +102 -0
- package/ds-canonical/skills/component-quality-gate/references/checklist.md +79 -0
- package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +247 -0
- package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +123 -0
- package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +165 -0
- package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +91 -0
- package/ds-canonical/skills/delivery-handoff/SKILL.md +229 -0
- package/ds-canonical/skills/delivery-handoff/references/flow-diagram.md +180 -0
- package/ds-canonical/skills/delivery-handoff/references/handoff-template.md +177 -0
- package/ds-canonical/skills/delivery-handoff/references/inventory-checklist.md +196 -0
- package/ds-canonical/skills/design-system-audit/SKILL.md +343 -0
- package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +1260 -0
- package/ds-canonical/skills/design-system-audit/references/checkpoints.md +240 -0
- package/ds-canonical/skills/design-system-audit/references/historical-bugs.md +240 -0
- package/ds-canonical/skills/design-system-audit/references/principle-audit-protocol.md +364 -0
- package/ds-canonical/skills/design-system-audit/references/rule-placement.md +175 -0
- package/ds-canonical/skills/design-system-audit/references/spec-template.md +66 -0
- package/ds-canonical/skills/ensure-canonical/SKILL.md +196 -0
- package/ds-canonical/skills/governance-health/SKILL.md +146 -0
- package/ds-canonical/skills/knowledge-prune/SKILL.md +303 -0
- package/ds-canonical/skills/new-component/SKILL.md +170 -0
- package/ds-canonical/skills/new-component/references/new-component-checklist.md +85 -0
- package/ds-canonical/skills/performance-audit/SKILL.md +107 -0
- package/ds-canonical/skills/product-ui-audit/SKILL.md +230 -0
- package/ds-canonical/skills/product-ui-audit/references/audit-checks.md +246 -0
- package/ds-canonical/skills/product-ui-audit/references/common-misuses.md +329 -0
- package/ds-canonical/skills/product-ui-audit/references/report-template.md +159 -0
- package/ds-canonical/skills/propose-options/SKILL.md +177 -0
- package/ds-canonical/skills/prototype/SKILL.md +244 -0
- package/ds-canonical/skills/prototype/references/audit-checks.md +37 -0
- package/ds-canonical/skills/prototype/references/benchmark-sources.md +94 -0
- package/ds-canonical/skills/prototype/references/checkpoints.md +191 -0
- package/ds-canonical/skills/prototype/references/evaluation-matrix.md +141 -0
- package/ds-canonical/skills/prototype/references/ooux-template.md +198 -0
- package/ds-canonical/skills/prototype/references/proposal-template.md +229 -0
- package/ds-canonical/skills/scan-similar-bugs/SKILL.md +198 -0
- package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +159 -0
- package/ds-canonical/skills/story-writing/SKILL.md +122 -0
- package/ds-canonical/skills/story-writing/references/anatomy-standard.md +217 -0
- package/ds-canonical/skills/story-writing/references/category-templates.md +174 -0
- package/ds-canonical/skills/story-writing/references/example-selection.md +70 -0
- package/ds-canonical/skills/story-writing/references/self-check.md +20 -0
- package/ds-canonical/skills/ux-audit/SKILL.md +130 -0
- package/ds-canonical/skills/visual-audit/SKILL.md +245 -0
- package/ds-canonical/skills/visual-audit/output/.gitkeep +0 -0
- package/ds-canonical/skills/visual-audit/references/audit-architecture.md +100 -0
- package/ds-canonical/skills/visual-audit/references/visual-checklist.md +297 -0
- package/ds-canonical/skills/visual-audit/references/world-class-benchmarks.md +198 -0
- package/package.json +9 -5
- package/src/components/Accordion/accordion.spec.md +114 -0
- package/src/components/Alert/alert.spec.md +197 -0
- package/src/components/AppShell/app-shell.spec.md +331 -0
- package/src/components/AspectRatio/aspect-ratio.spec.md +134 -0
- package/src/components/Avatar/avatar.spec.md +329 -0
- package/src/components/Badge/badge.spec.md +380 -0
- package/src/components/Breadcrumb/breadcrumb.spec.md +257 -0
- package/src/components/BulkActionBar/bulk-action-bar.spec.md +210 -0
- package/src/components/Button/button.spec.md +460 -0
- package/src/components/Calendar/calendar.spec.md +242 -0
- package/src/components/Carousel/carousel.spec.md +253 -0
- package/src/components/Chart/chart.spec.md +155 -0
- package/src/components/Checkbox/checkbox.spec.md +344 -0
- package/src/components/Chip/chip.spec.md +237 -0
- package/src/components/CircularProgress/circular-progress.spec.md +268 -0
- package/src/components/Coachmark/coachmark.spec.md +230 -0
- package/src/components/Combobox/combobox.spec.md +180 -0
- package/src/components/Command/command.spec.md +171 -0
- package/src/components/DataTable/data-table.spec.md +525 -0
- package/src/components/DateGrid/date-grid.spec.md +215 -0
- package/src/components/DatePicker/date-picker.spec.md +334 -0
- package/src/components/DescriptionList/description-list.spec.md +214 -0
- package/src/components/Dialog/dialog.spec.md +202 -0
- package/src/components/DropdownMenu/dropdown-menu.spec.md +250 -0
- package/src/components/Empty/empty.spec.md +214 -0
- package/src/components/Field/field-controls.spec.md +338 -0
- package/src/components/Field/field.spec.md +438 -0
- package/src/components/Field/form-validation.spec.md +152 -0
- package/src/components/FieldControlGroup/field-control-group.spec.md +176 -0
- package/src/components/FileItem/file-item.spec.md +467 -0
- package/src/components/FileUpload/file-upload.spec.md +123 -0
- package/src/components/FileViewer/file-viewer.spec.md +373 -0
- package/src/components/HoverCard/hover-card.spec.md +157 -0
- package/src/components/Input/input.spec.md +193 -0
- package/src/components/LinkInput/link-input.spec.md +130 -0
- package/src/components/Menu/menu-item.spec.md +290 -0
- package/src/components/NameCard/name-card.spec.md +171 -0
- package/src/components/Notice/notice.spec.md +149 -0
- package/src/components/NumberInput/number-input.spec.md +126 -0
- package/src/components/OverflowIndicator/overflow-indicator.spec.md +120 -0
- package/src/components/PeoplePicker/people-picker.spec.md +263 -0
- package/src/components/Popover/popover.spec.md +198 -0
- package/src/components/ProgressBar/progress-bar.spec.md +232 -0
- package/src/components/RadioGroup/radio-group.spec.md +141 -0
- package/src/components/Rating/rating.spec.md +208 -0
- package/src/components/ScrollArea/scroll-area.spec.md +145 -0
- package/src/components/SegmentedControl/segmented-control.spec.md +295 -0
- package/src/components/Select/select.spec.md +299 -0
- package/src/components/SelectMenu/select-menu.spec.md +220 -0
- package/src/components/SelectionControl/selection-item.spec.md +128 -0
- package/src/components/Separator/separator.spec.md +109 -0
- package/src/components/Sheet/sheet.spec.md +148 -0
- package/src/components/Sidebar/sidebar.spec.md +713 -0
- package/src/components/Skeleton/skeleton.spec.md +104 -0
- package/src/components/Slider/slider.spec.md +353 -0
- package/src/components/Steps/steps.spec.md +465 -0
- package/src/components/Switch/switch.spec.md +215 -0
- package/src/components/Tabs/tabs.spec.md +314 -0
- package/src/components/Tag/tag.spec.md +282 -0
- package/src/components/Textarea/textarea.spec.md +151 -0
- package/src/components/TimePicker/time-picker.spec.md +279 -0
- package/src/components/Toast/toast.spec.md +177 -0
- package/src/components/Tooltip/tooltip.spec.md +139 -0
- package/src/components/TreeView/tree-view.spec.md +374 -0
- package/src/patterns/action-bar/action-bar.spec.md +458 -0
- package/src/patterns/element-anatomy/element-anatomy.spec.md +215 -0
- package/src/patterns/element-anatomy/inline-action.spec.md +315 -0
- package/src/patterns/element-anatomy/item-anatomy.spec.md +1042 -0
- package/src/patterns/header-canonical/header-canonical.spec.md +285 -0
- package/src/patterns/horizontal-overflow/horizontal-overflow.spec.md +191 -0
- package/src/patterns/overlay-surface/overlay-surface.spec.md +428 -0
- package/src/patterns/resize-handle/resize-handle.spec.md +109 -0
- package/src/tokens/color/color.spec.md +804 -0
- package/src/tokens/density/density.spec.md +127 -0
- package/src/tokens/elevation/elevation.spec.md +81 -0
- package/src/tokens/layoutSpace/layoutSpace.spec.md +314 -0
- package/src/tokens/motion/motion.spec.md +97 -0
- package/src/tokens/opacity/opacity.spec.md +78 -0
- package/src/tokens/orphan-tokens.spec.md +117 -0
- package/src/tokens/radius/radius.spec.md +123 -0
- package/src/tokens/typography/typography.spec.md +202 -0
- package/src/tokens/uiSize/uiSize.spec.md +438 -0
- package/src/styles/preset.css +0 -31
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: story-writing
|
|
3
|
+
description: Guide for writing Storybook stories (.stories.tsx / .principles.stories.tsx / .anatomy.stories.tsx) with world-class example quality. Enforces real-product scenarios, 「人」+「舉一反三」tests, Rule-note 原則>結論, and anatomy 6-story structure(含 A11y,2026-04-24). Invoke when user says「寫 story」「新增範例」「補 anatomy」「principles story」or is about to create/edit any `.stories.tsx` file in design-system.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Story Writing
|
|
7
|
+
|
|
8
|
+
Purpose: Storybook 是公開文件,範例 = 設計系統品質。本 skill 把「怎麼挑範例 / 怎麼寫 anatomy / 三方連動怎麼不漂移」集中成 invoke-time playbook,CLAUDE.md 只留最高準則 + 禁止清單。
|
|
9
|
+
|
|
10
|
+
## When to run
|
|
11
|
+
|
|
12
|
+
- User 說「寫 story」「新增範例」「補 anatomy」「principles story」「審 story」
|
|
13
|
+
- AI 即將建立 / 編輯任一 `.stories.tsx` / `.principles.stories.tsx` / `.anatomy.stories.tsx`
|
|
14
|
+
- Review 其他 contributor 的 story PR
|
|
15
|
+
|
|
16
|
+
## Preconditions
|
|
17
|
+
|
|
18
|
+
- 讀過 `.claude/rules/story-rules.md`(三層定位 + title 命名 + 範例最高準則)
|
|
19
|
+
- 該元件的 `.spec.md` 已存在且本 session 已讀(stories 必須反映 spec,不發明新規則)
|
|
20
|
+
- 若寫 anatomy:元件 `.tsx` 的 cva 定義已看過(TOKEN_MAP / SIZE_SPECS 必須與 code 一致)
|
|
21
|
+
|
|
22
|
+
## Workflow
|
|
23
|
+
|
|
24
|
+
### Phase 0.0 — Registry-driven baseline grep(2026-05-20 升級 per codex Layer B D4)
|
|
25
|
+
|
|
26
|
+
**MUST 在 Phase 0 / 0.5 / 1+ 之前先跑**:
|
|
27
|
+
|
|
28
|
+
1. **Load registry**:Read `.claude/references/story-baseline-registry.json`。檔內列每個 primitive(Sidebar / DataTable / ChromeHeader / etc.)的:
|
|
29
|
+
- `baseline`:production-grade canonical story path#StoryName
|
|
30
|
+
- `requiredHelpers`:必 import 的 helper list(WorkspaceBrand / MAIN_NAV / etc.)
|
|
31
|
+
- `antiPatterns`:regex + severity(block / warn)+ rationale
|
|
32
|
+
- `variantRules`:variant + size + prop combo canonical(eg. DataTable toolbar = text + sm + iconOnly + pressed)
|
|
33
|
+
2. **Read baseline + helpers**:跑 grep + Read 取真實 production canonical 用法,Read 對應 helper source code
|
|
34
|
+
3. **Produce diff table**:`primitive → baseline path → copied structure → deviations(if any with rationale)`
|
|
35
|
+
4. **No registry entry?**:STOP,先 add registry entry 才能寫 story。不能憑直覺寫 simplified mock。
|
|
36
|
+
5. **Marker required**:story 檔頭標 `// @story-baseline: <path>#<StoryName>` cite。
|
|
37
|
+
|
|
38
|
+
### Phase 0 — Baseline grep(legacy,2026-05-20 由 Phase 0.0 registry 取代)
|
|
39
|
+
|
|
40
|
+
(per M35 升 registry-driven,Phase 0 內容由 Phase 0.0 自動 cover。保留段供 legacy reference。)
|
|
41
|
+
|
|
42
|
+
### Phase 0.5 — 展示層拆分原則 mapping(展示 stories 必走)
|
|
43
|
+
|
|
44
|
+
對 `{name}.stories.tsx`(展示)層,寫前必走 4 步(對齊 memory `feedback_proactive_5layer_pipeline.md`「5-step pre-check」— 若寫 stories 時消費其他元件 tsx,該層也適用):
|
|
45
|
+
|
|
46
|
+
1. **對 category**(see `references/category-templates.md`)— 元件屬 A-G 哪 category,suggested core stories 是什麼?
|
|
47
|
+
2. **讀 spec.md** 列該元件 distinct rules(每 variant / prop / state 一條)+ 對照 category core list 補缺
|
|
48
|
+
3. **產 mapping table** rule → story(對齊 Polaris / Carbon / Storybook 官方,2026-04-26 verified):
|
|
49
|
+
- 同 affordance 同 rule 的 prop variations → **1 story + Controls 切**(❌ `WithStartIcon`+`WithEndIcon` → ✓ `WithIcon` 對照 grid)
|
|
50
|
+
- 不同 affordance → 必分(`IconOnly` / `FullWidth` / `Disclosure`)
|
|
51
|
+
- AllVariants / AllSizes 對照各 1
|
|
52
|
+
- Compound 有 new constraint(prop 名變 + 必某 affordance)→ 必分(`OverlayBadgeOnIconOnly`)
|
|
53
|
+
- 真實業務情境 → 1 場景 1 故事
|
|
54
|
+
4. **present mapping** 給 user sign-off(若走 skill);user 拍板才寫;反 pattern 在 step 3 即可避免
|
|
55
|
+
|
|
56
|
+
Hook `check_story_slot_split.sh` write-time block 同源反 pattern。Audit `/design-system-audit` Dim 28 後驗。
|
|
57
|
+
|
|
58
|
+
### Phase 1 — 定位(決定寫哪層 story)
|
|
59
|
+
|
|
60
|
+
問自己:這個 story 的受眾要做什麼?
|
|
61
|
+
|
|
62
|
+
| 目的 | 寫哪 | 職責 |
|
|
63
|
+
|------|------|------|
|
|
64
|
+
| 掃視 variant × size × state 渲染結果 | `{name}.stories.tsx`(展示) | 視覺目錄 |
|
|
65
|
+
| 查 token / 尺寸 / Inspect 面板取代 Figma | `{name}.anatomy.stories.tsx`(設計規格) | 技術查閱 |
|
|
66
|
+
| 學「何時用哪個 variant」的判斷 | `{name}.principles.stories.tsx`(設計原則) | 使用判斷 |
|
|
67
|
+
|
|
68
|
+
混層 = 污染(principles 放 anatomy 資料 / 展示塞 do/don't)。走錯層 → 重選。
|
|
69
|
+
|
|
70
|
+
### Phase 2 — 範例選擇(最高準則 + 驗收 test)
|
|
71
|
+
|
|
72
|
+
**參考 `references/example-selection.md`**——完整合法來源 / 禁止清單 / 2 個 test / 正確範例對照 / Rule note 品質 / 視覺品質。
|
|
73
|
+
|
|
74
|
+
核心三問:
|
|
75
|
+
1. 範例來源是真實 SaaS / 常見業務(Jira / Stripe / Notion / Figma 付款 / Slack 通知)?
|
|
76
|
+
2. 遮掉 title / label,5 秒看懂情境?(「人」test)
|
|
77
|
+
3. 讀者能推出自己產品怎麼用?(「舉一反三」test)
|
|
78
|
+
|
|
79
|
+
任一不過 → 改範例,不是補說明文字。
|
|
80
|
+
|
|
81
|
+
### Phase 3 — anatomy 6-story 結構(僅 anatomy 適用)
|
|
82
|
+
|
|
83
|
+
**參考 `references/anatomy-standard.md`**——每個元件 anatomy 必備 **6 件套**(`export const Overview / Inspector / ColorMatrix / SizeMatrix / StateBehavior / Accessibility`,一字不差;Accessibility 第 6 章 2026-04-24+ 對齊 Material / Polaris / Atlassian) + Inspect 面板規格 + token-first 原則 + 值溯源完整性。
|
|
84
|
+
|
|
85
|
+
**偏離 canonical 規則**(CLAUDE.md 「Consistency Audit 原則」):
|
|
86
|
+
- 追加第 7+ 個元件特有 story → OK,免 rationale
|
|
87
|
+
- 取代 6-canonical 中某個 → **必須在元件 spec.md 寫 rationale**
|
|
88
|
+
- 同概念改名(如 `VisualTokens` 取代 `ColorMatrix`) → **禁止**
|
|
89
|
+
|
|
90
|
+
`/design-system-audit` Dimension 13 會強制 grep 比對偏離 + rationale 追溯。
|
|
91
|
+
|
|
92
|
+
Checkpoint: 寫完後必驗:
|
|
93
|
+
- TOKEN_MAP / SIZE_SPECS 每筆對得上元件 .tsx 的 cva 定義?
|
|
94
|
+
- 藍圖每層 padding/margin/gap 都畫?(含子元素 `px-1`)
|
|
95
|
+
- State 用開發術語(default 不是 rest)?
|
|
96
|
+
- 色塊用 `var()` inline style(dark mode 自動更新)?
|
|
97
|
+
|
|
98
|
+
### Phase 4 — 連動檢查(stop 點)
|
|
99
|
+
|
|
100
|
+
改 `.tsx` 或 `.spec.md` 後寫 story:
|
|
101
|
+
- **高風險漂移點:cva `defaultVariants`** → grep `star 預設 default` 該元件所有檔案,一次改完
|
|
102
|
+
- spec 新加 rule → principles stories 必有對應 do/don't 範例
|
|
103
|
+
- 元件改 variant/size → anatomy TOKEN_MAP / SIZE_SPECS 同步
|
|
104
|
+
|
|
105
|
+
**STOP 條件**:若三方(code / spec / story)任一有矛盾且原因不清楚 → 停下問 user,不默默改一邊。
|
|
106
|
+
|
|
107
|
+
### Phase 5 — 自我檢查 checklist
|
|
108
|
+
|
|
109
|
+
**參考 `references/self-check.md`**——7 題 checklist 全部打勾才算完成:範例真實性 / 「人」test / 舉一反三 / 無極端案例 / 無代號 / Rule note 原則>結論 / 無中英夾雜。
|
|
110
|
+
|
|
111
|
+
## References
|
|
112
|
+
|
|
113
|
+
- `references/category-templates.md` — 7 category(A-G)suggested core stories(展示層 emergent typology)
|
|
114
|
+
- `references/example-selection.md` — 完整範例選擇原則(合法來源 / 禁止清單 / 2 test / 正確範例 / Rule note / 視覺品質)
|
|
115
|
+
- `references/anatomy-standard.md` — anatomy 6-story 結構 + Inspect 面板 + 品質規則
|
|
116
|
+
- `references/self-check.md` — 7 題自我檢查 checklist
|
|
117
|
+
|
|
118
|
+
## 相關
|
|
119
|
+
|
|
120
|
+
- `.claude/rules/story-rules.md`:三層定位 + title 命名(high-level signal)
|
|
121
|
+
- CLAUDE.md `# 失敗記憶索引` → 三方漂移:SegmentedControl cva defaultVariants bug
|
|
122
|
+
- `.claude/hooks/check_sync_update.sh`:Edit 後自動提醒三方連動
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# anatomy Story 標準(`{name}.anatomy.stories.tsx`)
|
|
2
|
+
|
|
3
|
+
以 `Button/button.anatomy.stories.tsx` 為範本。每個元件的設計規格必須包含以下 5 個 story。
|
|
4
|
+
|
|
5
|
+
## 為什麼有「設計規格」(anatomy.stories.tsx 的目的)
|
|
6
|
+
|
|
7
|
+
設計規格取代 Figma inspect,是**元件的技術規格表**。滿足兩個 audience:
|
|
8
|
+
|
|
9
|
+
1. **設計師 / PM 讀 spec**:詳盡解剖學(anatomy 圖標示每個 slot)、每個數值的 token 來源、每個 variant × state 的色彩組合、每個 size 的尺寸藍圖 — **檢閱方便性必須超越 Figma**,不需切工具,一頁看完
|
|
10
|
+
2. **工程師讀 code**:依規格資訊能直接開發出一模一樣的 tsx,不靠設計師協助 — token name / Tailwind class / padding / gap / typography 全部在規格上,Inspect 面板即時 resolve 出 px 值
|
|
11
|
+
|
|
12
|
+
因此 6-canonical / 6 件套 story(含 Accessibility 第 6 章,2026-04-24+)不是裝飾,是**兩個 audience 各自需要的資訊分層**:
|
|
13
|
+
- `Overview` = anatomy 圖 + variant 一覽 + props 速查(「這元件長什麼樣」)
|
|
14
|
+
- `Inspector` = 即時預覽 + inspect 面板(「各 prop 切換時 token 怎麼變」,超越 Figma 的互動檢閱)
|
|
15
|
+
- `ColorMatrix` = variant × state 色彩矩陣(「每格色彩 token 是哪個」)
|
|
16
|
+
- `SizeMatrix` = size × variant 尺寸藍圖(「每格尺寸 token 是哪個」)
|
|
17
|
+
- `StateBehavior` = 互動狀態前後對照(「hover / active / disabled 怎麼變」)
|
|
18
|
+
|
|
19
|
+
任一分層缺口 = 規格不完整 = Figma inspect 的替代目標沒達到。這就是為什麼 6-canonical(含 Accessibility)不是 N 個 random story,而是「足以 100% 還原元件 + 對齊世界級 a11y 章程」的最小必要切片。
|
|
20
|
+
|
|
21
|
+
## Canonical `export const` 名稱 + 中文顯示名(6 件套)
|
|
22
|
+
|
|
23
|
+
每個 `.anatomy.stories.tsx` 的 `export const` 識別名稱必須用英文、中文 story 顯示名必須**強制 `name:` 覆寫**,且兩者**一字不差對齊**以下 canonical:
|
|
24
|
+
|
|
25
|
+
| 順序 | `export const` | 中文 story `name`(強制覆寫,**不加序號**) |
|
|
26
|
+
|------|--------------|---------------------|
|
|
27
|
+
| 1 | `Overview` | `'元件總覽'` |
|
|
28
|
+
| 2 | `Inspector` | `'元件檢閱器'` |
|
|
29
|
+
| 3 | `ColorMatrix` | `'色彩對照表'` |
|
|
30
|
+
| 4 | `SizeMatrix` | `'尺寸對照表'` |
|
|
31
|
+
| 5 | `StateBehavior` | `'狀態行為'` |
|
|
32
|
+
| 6 | `Accessibility` | `'無障礙與鍵盤'`(互動元件強制,純視覺 indicator N/A)|
|
|
33
|
+
| 7+ | 元件特有 | 中文命名,見下方擴充規則 |
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
export const Overview = {
|
|
37
|
+
name: '元件總覽', // ← 強制覆寫,不可省
|
|
38
|
+
render: () => (...),
|
|
39
|
+
} satisfies Story
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 為什麼強制 `name:` 覆寫(不加序號)
|
|
43
|
+
|
|
44
|
+
- **強制中文覆寫**:不覆寫時 Storybook sidebar 顯示英文 identifier(`Overview`),中英混雜破壞中文 spec 一致性
|
|
45
|
+
- **不加序號**(2026-04-26 起 user 反饋):序號無價值且容易跳號(N/A skip 後 1 2 3 5 視覺破碎)。Sidebar 排序由 `export` 順序決定(Storybook 預設 `storySort: 'function'` 已對應 export 順序;若依字母排,本系統元件數有限,人工順序可接受)
|
|
46
|
+
- **世界級對照**:Polaris(Anatomy / Variants / States)/ Material(Anatomy / Guidelines)/ Atlassian(Examples / Code) 的 Storybook 皆為每個 story 明確標題,**無一使用序號前綴**
|
|
47
|
+
|
|
48
|
+
### Canonical 是**預設 6 section 都要建**(含 Accessibility),N/A 是嚴格例外
|
|
49
|
+
|
|
50
|
+
**6-canonical section = 每個 Components/(public)元件預設都該有**(Accessibility 第 6 章 2026-04-24+ 加入,對齊 Material / Polaris / Atlassian)。N/A 不是「省工豁免」,是嚴格例外 — 必須是「建了毫無意義 / 反而有害」才算 N/A。下方判斷標準**從嚴**。
|
|
51
|
+
|
|
52
|
+
**判斷預設 applicable**(採 Polaris / Material / Atlassian 世界級 baseline):
|
|
53
|
+
- **Inspector**:**幾乎所有 public 元件都 applicable**。只要元件有 ≥ 2 props,就該有 Inspector 讓 designer 切 props 看 render + token 對照。拒絕 Inspector 的唯一理由 = 元件 props < 2(極罕見,例 Separator / Skeleton 無互動 prop)
|
|
54
|
+
- **ColorMatrix**:applicable 如元件有 variant / hue / severity / theme。N/A 僅當元件色彩完全繼承 context(例 HoverCard 繼承 page theme 無自己 palette)
|
|
55
|
+
- **SizeMatrix**:applicable 如元件有 size prop(sm/md/lg)。固定尺寸才 N/A(Notice / Chip / Avatar 的特定固定場合)
|
|
56
|
+
- **StateBehavior**:applicable 如元件有任何互動 state(hover / selected / disabled / loading / error / focus)。純靜態 indicator(Badge / Tag)才 N/A
|
|
57
|
+
- **Accessibility**(2026-04-24 加,對齊 Material / Polaris / Atlassian 專章):applicable 如元件有任何鍵盤互動 / ARIA / focus 管理。內含:ARIA props 對照表 / Keyboard map(Tab/Enter/Esc/arrow)/ Focus order 圖 / WCAG AA 對比 snapshot。純視覺 indicator(Badge / Tag / Separator)才 N/A。**Migration strategy**:existing 元件**不 retroactively backfill**;新元件 / 重大修改時建;`/design-system-audit` 稽核發現缺 → flag + 補
|
|
58
|
+
|
|
59
|
+
**嚴格警告**:曾經被誤用「applicable-where-meaningful」放行大量元件跳 Inspector,造成 anatomy 紙本文件不如世界級。**2026-04-21 audit 重修:policy 改回「6-canonical 預設全建(含 Accessibility),N/A 要硬 rationale」**。N/A 不是省工通行證。
|
|
60
|
+
|
|
61
|
+
### 允許的偏離(CLAUDE.md「Consistency Audit 原則」公式)
|
|
62
|
+
|
|
63
|
+
#### `@anatomy-rationale:` 檔頭註解(scope-N/A 的 canonical escape)
|
|
64
|
+
|
|
65
|
+
當某 section(Inspector / ColorMatrix / SizeMatrix / StateBehavior / Accessibility)是**設計上 N/A**(非「未做完」),於 `*.anatomy.stories.tsx` 檔頭以**多行註解**列出 N/A 段 + 一行原因:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
// @anatomy-rationale:
|
|
69
|
+
// SizeMatrix N/A — Skeleton 為純結構 placeholder,寬高由 consumer 控制,無 size tier
|
|
70
|
+
// StateBehavior N/A — Skeleton 無互動 state(僅 loading 一態,Overview 已示範)
|
|
71
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
72
|
+
// ...
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**何時用**:section 是**設計範圍外**的 N/A — 例:Skeleton 無互動 state / Separator 為結構元件 / 無參數的 layout primitive。
|
|
76
|
+
**何時不用**:section 只是還沒填完 — 補完內容,不要拿 escape 規避。
|
|
77
|
+
**世界級對照**:對齊 ESLint `eslint-disable-next-line {rule}` 的 per-line allowlist idiom — 每個豁免必有具名 rule + 一行 rationale,不允許整檔默默繞過。
|
|
78
|
+
|
|
79
|
+
`check_story_anatomy.sh` 識別 `@anatomy-rationale:` block:列出的 section 視為 legitimately N/A;未列出的 missing section 仍 violation。
|
|
80
|
+
|
|
81
|
+
#### 其他允許的偏離
|
|
82
|
+
|
|
83
|
+
1. **追加第 6+ 個元件特有 story**:OK,不需 rationale。命名遵循以下格式:
|
|
84
|
+
- `export const` 用 PascalCase 英文(如 `StandardRatios` / `LayoutMatrix` / `ColorBindingRule`)
|
|
85
|
+
- 中文 `name:` 必須用編號前綴 + 中文描述:`'6. 標準比例'` / `'6. 佈局矩陣'` / `'6. 色彩綁定規則'`
|
|
86
|
+
- ❌ 不准用素顏型 `'色彩綁定規則'`(破壞編號連續性)
|
|
87
|
+
- ❌ 不准帶括號 context `'6. Orientation(horizontal / vertical)'` — 括號寫在 story 標題本體,不影響 sidebar 文字
|
|
88
|
+
2. **缺 6-canonical 某一項(N/A)**:**必須在元件 spec.md 寫一段 rationale**,格式:「本元件無 `{SectionName}` story,因為 {原因}」。典型原因:
|
|
89
|
+
- Badge / Tag:純視覺 indicator,無互動狀態 → 不需 StateBehavior
|
|
90
|
+
- Chart:色彩來自 ChartConfig 不來自元件 variant → 不需 ColorMatrix
|
|
91
|
+
- Separator / Skeleton / CircularProgress / Avatar:無 size tier(自由 number)→ 不需 SizeMatrix(或 SizeMatrix 改為「範圍展示」)
|
|
92
|
+
- Notice / Alert:固定單一 size(Material Banner / Polaris Banner 共識) → 不需 SizeMatrix
|
|
93
|
+
3. **保留 canonical 編號**:若有 Overview(1) + ColorMatrix(3) + StateBehavior(5),**編號保持 3 和 5**,不重編為 2 和 3 — 這讓讀者在 sidebar 一眼看出「這個元件跳過了 2 和 4」而非誤以為 canonical 就只有 3 個 section(6-canonical 模型同理)
|
|
94
|
+
4. **同概念改名**:不允許(如 `VisualTokens` 取代 `ColorMatrix` / `StyleMatrix` 取代 `ColorMatrix`)一律改回 canonical
|
|
95
|
+
|
|
96
|
+
**`/design-system-audit` Dimension 13 強制 grep 比對**:
|
|
97
|
+
- `export const` 名稱 ≠ canonical → violation
|
|
98
|
+
- 無 `name:` 覆寫(依賴 identifier) → violation
|
|
99
|
+
- `name:` 值 ≠ canonical 中文(含編號前綴) → violation
|
|
100
|
+
- 缺 6-canonical 某項且 spec.md 無 rationale → violation
|
|
101
|
+
|
|
102
|
+
## 元件總覽(Overview)
|
|
103
|
+
|
|
104
|
+
- Anatomy 圖——標示所有 slot(標準版面 + iconOnly 等變體版面)
|
|
105
|
+
- Variant 一覽——每個 variant 一行:渲染元件 + 一句話角色描述
|
|
106
|
+
- Props 速查表——prop / type / default / 說明
|
|
107
|
+
|
|
108
|
+
## 元件檢閱器(Inspector,取代 Figma inspect)
|
|
109
|
+
|
|
110
|
+
- 控制項:variant / danger / state / size / iconOnly(依元件調整)
|
|
111
|
+
- 左側:即時預覽 + 尺寸藍圖
|
|
112
|
+
- 右側:Inspect 面板,分區顯示 Color / Layout / Typography / Style
|
|
113
|
+
- **State 使用開發術語**:default / hover / active / disabled(不用 rest)
|
|
114
|
+
|
|
115
|
+
## 色彩對照表(ColorMatrix)
|
|
116
|
+
|
|
117
|
+
- Variant × State 矩陣
|
|
118
|
+
- 每格:渲染元件 + bg / text / border token 標註(含即時色塊)
|
|
119
|
+
- 標準 variant 與 danger variant 分開
|
|
120
|
+
|
|
121
|
+
## 尺寸對照表(SizeMatrix)
|
|
122
|
+
|
|
123
|
+
- Size token 對照表(每個 size 的所有 token 一覽)
|
|
124
|
+
- 含 iconOnly 等變體模式的覆寫說明
|
|
125
|
+
- 視覺預覽矩陣(Variant × Size,含變體模式)
|
|
126
|
+
|
|
127
|
+
## 狀態行為(StateBehavior)
|
|
128
|
+
|
|
129
|
+
- 每個互動狀態的前後對照(如 loading spinner 替換規則)
|
|
130
|
+
- 所有 variant 的 disabled 渲染(含變體模式)
|
|
131
|
+
- 元件特有狀態(如 checked toggle)
|
|
132
|
+
|
|
133
|
+
## 無障礙與鍵盤(Accessibility,2026-04-24 新增,對齊 Material / Polaris / Atlassian 專章)
|
|
134
|
+
|
|
135
|
+
**對齊世界級**:Material 3 / Polaris / Atlassian DSP 三家元件文件皆有 A11y + Keyboard 專章。散在 StateBehavior(focus/disabled)+ principles(do/don't)不夠突出,designer / audit 找 a11y 資訊需要翻多檔。
|
|
136
|
+
|
|
137
|
+
**包含**(applicable 時必有):
|
|
138
|
+
- **ARIA props 對照表**:每 prop 對應的 aria-* mapping(e.g. `disabled` → `aria-disabled` / `required` → `aria-required`)
|
|
139
|
+
- **Keyboard map**:Tab / Shift+Tab / Enter / Space / Esc / Arrow keys(↑↓←→) 各做什麼
|
|
140
|
+
- **Focus order 圖**:複合元件(DatePicker / Combobox / DropdownMenu)的 focus 進入 → 內部 navigation → 退出流程
|
|
141
|
+
- **WCAG AA 對比 snapshot**:主要 state(default / hover / focus / disabled)對比度通過 visual-audit Layer A
|
|
142
|
+
|
|
143
|
+
**N/A 條件**:純視覺 indicator(Badge / Tag / Separator / Skeleton / Avatar 非 interactive 時)— rationale 寫 spec「本元件無互動」。
|
|
144
|
+
|
|
145
|
+
**Migration**:
|
|
146
|
+
- 新元件 / 元件重大修改時**強制**建
|
|
147
|
+
- **既有元件不 retroactively backfill**(尊重 user 2026-04-24 指示)
|
|
148
|
+
- `/design-system-audit` Dim 10(a11y 覆蓋)擴充:發現 interactive 元件缺 Accessibility story → flag
|
|
149
|
+
- 新元件 checklist 加 `Accessibility story 建立`
|
|
150
|
+
|
|
151
|
+
## 三層 stories 互聯 cross-link(2026-04-24 新增)
|
|
152
|
+
|
|
153
|
+
每個 story 頂部 meta 或底部 Rule note 必含統一 **「See also」** 區塊,讓讀者從任一層入口跳到其他角度:
|
|
154
|
+
|
|
155
|
+
```markdown
|
|
156
|
+
See also:
|
|
157
|
+
- 展示({name}.stories.tsx) — 真實業務場景
|
|
158
|
+
- 設計規格({name}.anatomy.stories.tsx) — 6-matrix inspect
|
|
159
|
+
- 設計原則({name}.principles.stories.tsx) — do/don't + 情境選擇
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**為什麼需要**:展示 / 設計規格 / 設計原則 3 層職責不重複但視角不同(「看 → 查 → 判斷」)。沒有 cross-link 讀者容易 stuck 在一層,漏看其他角度的 canonical。
|
|
163
|
+
|
|
164
|
+
**實作**:`compile-stories.mjs` 自動在每個 story 的 docs meta 注入此 section;consumer 不手寫。
|
|
165
|
+
|
|
166
|
+
## Story earn-existence philosophy(2026-04-24 新增 — audit Dim 24/25 對應)
|
|
167
|
+
|
|
168
|
+
每個 manual story(非 auto-compiled 的部分)必 earn its existence。理由:多餘 story = noise,增加維護成本 + drift 風險 + 讀者(人 + AI)認知負擔。
|
|
169
|
+
|
|
170
|
+
**核心 philosophy**:
|
|
171
|
+
1. **以「可舉一反三」為主** — 一個 story 教一條原則,讀者能類推到其他情境
|
|
172
|
+
2. **Manual 補充模糊原則,讓抽象具象化** — spec 有模糊 rule 時,manual story 用具體 Jira/Stripe/Notion 劇情把原則釘下來。給「人」看得懂為主
|
|
173
|
+
3. **禁止湊數 / 重複 / 秀肌肉**
|
|
174
|
+
|
|
175
|
+
**每 manual story 必過 2 earn test**:
|
|
176
|
+
- (a) **unique teaching** — 這個 story 教一條其他 story 沒教的原則?
|
|
177
|
+
- (b) **grounding necessity** — 移除後,spec 某條抽象原則會 degrade 為難懂?
|
|
178
|
+
|
|
179
|
+
兩題皆 NO → retire 候選(audit Dim 24/25 會抓)。兩題任一 YES → 合法保留。
|
|
180
|
+
|
|
181
|
+
**範例(illustrative)**:
|
|
182
|
+
- ✅ OK:`DialogWithForm` — 教 Dialog 內 form field-wrapper canonical(grounds 抽象「form gap」rule)
|
|
183
|
+
- ❌ redundant:`DialogWithFormAndCancelButton` — 跟 `DialogWithForm` 只差 cancel button,不新教任何原則
|
|
184
|
+
- ❌ showing-off:`DialogHugeSize1000px` — 極端 size 不教原則,只秀技術
|
|
185
|
+
|
|
186
|
+
## 設計規格品質規則
|
|
187
|
+
|
|
188
|
+
- **Token-first**:所有數值以 token name 為主(如 `h-field-sm`),resolved px 值為輔助灰字。開發者只需確認 token 正確——theme / density 的值解析由系統處理
|
|
189
|
+
- **不含 density 雙值**:不顯示 `28px (md) / 32px (lg)`,只顯示 token name + 當前 resolved 值
|
|
190
|
+
- **Dev 語言**:使用開發術語(default 不是 rest,用 Tailwind utility name 如 `px-3` `gap-1`)
|
|
191
|
+
- **藍圖完整性**:render 函式中**每一層**的 padding / margin / gap 都必須在藍圖中呈現——包括子元素的間距(如 label span 的 `px-1`),不可遺漏
|
|
192
|
+
- **範例驗證**:每個範例必須用 spec.md 的所有規則逐條驗證(如 badge 不應出現在 loading / disabled 狀態)
|
|
193
|
+
- **色塊即時渲染**:使用 `var()` 內聯樣式,確保切換 dark mode / density 時自動更新
|
|
194
|
+
- **資料正確性**:TOKEN_MAP / SIZE_SPECS 等資料必須與元件 `.tsx` 的 `cva()` 定義交叉比對,確認完全一致
|
|
195
|
+
- **值溯源完整性**:設計規格中出現的每個行為描述,必須追到 code 中的具體值。不可只描述行為模式而省略數值——包括 Provider 層級設定(如 `delayDuration`)、全域設定檔(`main.tsx`、`preview.tsx`)、CSS 變數定義檔。規則:**如果 code 裡有具體數字,設計規格就必須標出來**
|
|
196
|
+
|
|
197
|
+
## 連動更新規則
|
|
198
|
+
|
|
199
|
+
三份文件互為依賴,任一變動必須同步更新其他兩份:
|
|
200
|
+
|
|
201
|
+
| 異動來源 | 必須連動更新 |
|
|
202
|
+
|---------|-------------|
|
|
203
|
+
| **`.tsx` 元件程式碼**(variant / size / token / 內部結構) | → 設計規格(TOKEN_MAP、SIZE_SPECS、藍圖、Inspect 面板)<br>→ 展示(如有對應的 story) |
|
|
204
|
+
| **`.spec.md` 設計原則**(新增 / 修改 / 刪除規則) | → 設計原則 stories(do/don't 範例必須反映最新 spec)<br>→ 設計規格(範例驗證:確認規格中的範例不違反新規則) |
|
|
205
|
+
| **設計規格 story**(結構調整、新增對照維度) | → 展示(確保展示仍是規格的便利瀏覽版,不脫節) |
|
|
206
|
+
|
|
207
|
+
## 高風險漂移點:`cva()` defaultVariants
|
|
208
|
+
|
|
209
|
+
**`defaultVariants` 是三方(code / spec / story)最容易漂移的位置,改之前必須意識到四方聯動:**
|
|
210
|
+
|
|
211
|
+
| 改什麼 | 必須同步 |
|
|
212
|
+
|--------|---------|
|
|
213
|
+
| `cva()` 裡的 `defaultVariants.size`(或 variant / state) | 1. 元件 `.spec.md` 的 prop 表 / 預設標記<br>2. 元件 `.tsx` 頂端 docblock 的 `★ 預設` 標記<br>3. `{name}.anatomy.stories.tsx` 的 SIZE_SPECS 表 / default marker<br>4. 若屬 field-height family → `tokens/uiSize/uiSize.spec.md` 的 family 清單 |
|
|
214
|
+
|
|
215
|
+
**曾發生的 bug**:SegmentedControl 的 cva `defaultVariants.size` 是 `md`,spec.md + docblock + anatomy 都寫 `sm ★default`——三方不一致持續存在到 audit 才發現(2026-04-18 修正)。
|
|
216
|
+
|
|
217
|
+
**預防法**:改 `defaultVariants` 前,grep 該元件所有檔案(`grep "★\|預設\|default" packages/design-system/src/components/{Name}/`),一次改完所有出現位置,不單改 code 就收工。
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# 展示 Story Trait-Based Typology v2(2026-04-26)
|
|
2
|
+
|
|
3
|
+
世界級 DS(Polaris / Material / Atlassian / Ant / Carbon / Storybook 官方)的 Storybook story 結構**不是** category-based prescription(「button-likes 必有 5 stories」),是**trait-based**——元件依自身能力宣告 traits,required stories 由 trait 衍生。本 doc 是本 DS canonical typology v2,取代 v1 7-category。
|
|
4
|
+
|
|
5
|
+
對應 `.claude/rules/story-rules.md`「拆分原則」+ M8 world-class benchmark。
|
|
6
|
+
|
|
7
|
+
## 為什麼 v2 trait-based(取代 v1 category-based)
|
|
8
|
+
|
|
9
|
+
v1 7 categories(A 視覺 variant / B field control / C selection / D structural / E scenario / F media / G internal)在實踐中暴露 4 盲點:
|
|
10
|
+
1. **Over-engineered**:A 要求 ≥5 stories 比 Carbon 整 component 還多
|
|
11
|
+
2. **Switch 一刀切**:C 要求 group stories,但 Material/Polaris/Carbon 的 Switch 全是 standalone(對齊 single-toggle idiom)
|
|
12
|
+
3. **Scope-N/A 沒寫**:Toast 沒 size 軸,A 卻硬要 AllSizes
|
|
13
|
+
4. **G 不該定 required stories**:Internal 是 DS visibility governance,不是 story shape
|
|
14
|
+
|
|
15
|
+
**M8 benchmark 證據**(2026-04-26 raw source 掃 5 系統):
|
|
16
|
+
- **Carbon Button**:10 stories,disabled/sizes 走 args(Controls)
|
|
17
|
+
- **Polaris Button**:24 stories(variant × tone matrix,但 sizes 散在 per-variant)
|
|
18
|
+
- **MUI Button**:18 example files,trait-driven(BasicButtons / OutlinedButtons / IconLabelButtons / LoadingButtons)
|
|
19
|
+
- **Ant Button**:22 demos,one demo = one focused trait
|
|
20
|
+
- **Storybook 官方**:推薦 Default first + CSF3 args,**不 prescribe count or required set**
|
|
21
|
+
- **共識**:`Default` 必有 / `WithIcon` merged grid 不拆 / overlay default-open `useState(true)` / Disabled 多數有但非絕對 / scenarios 多寡看 component 性質
|
|
22
|
+
|
|
23
|
+
→ trait-based 對齊 5/5 benchmark systems(M8 ≥ 3 ✓ overshot)。
|
|
24
|
+
|
|
25
|
+
## Trait-based core canonical
|
|
26
|
+
|
|
27
|
+
### Universal(每元件必有)
|
|
28
|
+
|
|
29
|
+
- **Default** — 最 minimal 代表性範例(對齊 Storybook 官方 + Carbon idiom)
|
|
30
|
+
|
|
31
|
+
### Conditional traits → required stories
|
|
32
|
+
|
|
33
|
+
元件在 **spec.md frontmatter** 的 `traits: [...]` 宣告,`scripts/compile-stories.mjs` + hook 會驗證 required stories 齊全:
|
|
34
|
+
|
|
35
|
+
| Trait | 何時宣告 | Required stories(traits 觸發後必有) |
|
|
36
|
+
|-------|---------|----------------------------------|
|
|
37
|
+
| `hasVariants` | ≥ 2 visual variants(primary/secondary/danger 等) | `AllVariants` 對照 grid,**或** ≥ 2 個 per-variant exports |
|
|
38
|
+
| `hasSizes` | ≥ 2 sizes(sm/md/lg 等) | `AllSizes` merged grid(❌ 禁止 per-size 拆 `Small`+`Medium`+`Large`) |
|
|
39
|
+
| `hasInteractiveStates` | hover / focus / disabled / loading 任一可見 | `Disabled` own story(`Loading` 視 prop / `Error` 視 validation 而定) |
|
|
40
|
+
| `isOverlay` | Dialog / Sheet / Popover / Tooltip / Drawer 類 portal-rendered | `OpenSnapshot` story(`defaultOpen` / `useState(true)` 對齊 M15)+ ≥ 3 業務 scenarios |
|
|
41
|
+
| `isInputLike` | text / number / search / textarea field | `WithError` + `WithHelpText` + `WithIcon` merged grid |
|
|
42
|
+
| `isSelectionMulti` | Checkbox / Radio / 多選 toggle | `States`(checked/unchecked/indeterminate/disabled)+ `VerticalGroup` + `Disabled`(group level) |
|
|
43
|
+
| `isSelectionSingle` | Switch / 單一 toggle(無群組概念) | `States` only(對齊 Material/Polaris/Carbon Switch idiom — 無 group story) |
|
|
44
|
+
| `isMatrixHeavy` | Avatar / Skeleton / Spinner / Badge / Slider 等 token × size 正交視覺軸 | ≥ 4 matrix stories(`Modes` / `Shapes` / `Colors` / `AllSizes` 任 4) |
|
|
45
|
+
| `isStructural` | DataTable / Steps / Tabs / Accordion 結構主導 | 每結構變體 1 story(無固定數,過 earn-existence) |
|
|
46
|
+
| `isInternal` | L3 building block(被其他元件消費) | 1 `Default` + ≤ 1 composition scenario(寬鬆,Internal/ 命名空間下) |
|
|
47
|
+
|
|
48
|
+
### Optional universal
|
|
49
|
+
|
|
50
|
+
- 1+ `RealScenario` story(Jira / Stripe / Notion / Figma / Slack / Gmail 真實業務情境),**過 earn-existence 2 test 才開**:
|
|
51
|
+
- Q1:教別 story 沒教的原則?
|
|
52
|
+
- Q2:移除後 spec 理解 degrade?
|
|
53
|
+
- 兩題皆 NO → retire 候選
|
|
54
|
+
|
|
55
|
+
## Typical story counts(對齊 Carbon / Polaris median)
|
|
56
|
+
|
|
57
|
+
| 元件類型 | Stories range | 對照 |
|
|
58
|
+
|---------|---------------|------|
|
|
59
|
+
| L1 minimal(Switch / Skeleton)| 1-3 | Carbon Checkbox 5 |
|
|
60
|
+
| L1 standard(Button / Input)| 4-8 | Carbon Button 10 |
|
|
61
|
+
| Overlay(Dialog / Sheet)| 6-12 | Polaris Modal 16 / Ant Modal 17 |
|
|
62
|
+
| Matrix-heavy(Avatar)| 4-6 | Polaris Avatar 5 |
|
|
63
|
+
| Structural(DataTable)| 8-12 | (本 DS 11) |
|
|
64
|
+
| Internal primitive | 1-2 | Carbon hidden _PrefixedExport |
|
|
65
|
+
|
|
66
|
+
## Scope-N/A 例外子句
|
|
67
|
+
|
|
68
|
+
某 trait 在 spec.md「邊界案例 scope」明示 N/A → 該 trait required stories 跳過,不違反 typology:
|
|
69
|
+
|
|
70
|
+
- **Toast**:`hasSizes=false`(ephemeral notification 單尺寸)→ AllSizes 跳過
|
|
71
|
+
- **Coachmark**:`hasInteractiveStates=false`(無 disabled / loading 概念)→ Disabled 跳過
|
|
72
|
+
- **Skeleton**:`hasVariants=false`(只 default skeleton 形狀)→ AllVariants 跳過
|
|
73
|
+
|
|
74
|
+
**規則**:跳過 trait 時 spec.md 必明文 rationale(例「Toast 是 ephemeral notification,單尺寸對齊 Sonner / Polaris Toast idiom,無 size 軸」)。**禁止**默默 skip。
|
|
75
|
+
|
|
76
|
+
## How to use(寫 / audit story 時)
|
|
77
|
+
|
|
78
|
+
1. 該元件宣告哪些 traits?(讀 spec.md frontmatter `traits:` array)
|
|
79
|
+
2. 對照本 doc traits → required stories list
|
|
80
|
+
3. 缺哪個 → 補(若 spec.md 該 trait 真有效)
|
|
81
|
+
4. 多哪個 → 過 earn-existence 2 test;不過 → retire
|
|
82
|
+
5. **scope-N/A 例外**:該 trait 在 spec.md 明示 N/A → 跳過 OK,但 spec.md 必有 rationale
|
|
83
|
+
|
|
84
|
+
## 邊界 case
|
|
85
|
+
|
|
86
|
+
- **多 trait 元件**(e.g. Button = `hasVariants` + `hasSizes` + `hasInteractiveStates`)→ 各 trait required 都有
|
|
87
|
+
- **Family 跨界**(Field control 同時 isInputLike + hasInteractiveStates)→ Union of all traits
|
|
88
|
+
- **新 trait 提議**:跑 M8(≥ 3 家 DS benchmark)+ Checkpoint user sign-off,不孤立發明
|
|
89
|
+
|
|
90
|
+
## Typology 演進規則(對齊 user mandate「除非調整標準」)
|
|
91
|
+
|
|
92
|
+
本 typology 是 canonical SSOT。**禁止**單元件偏離不記 rationale。Typology 本身可演進,但流程:
|
|
93
|
+
|
|
94
|
+
1. 提案 invoke `/ensure-canonical` skill(M19 trigger)
|
|
95
|
+
2. 跑 M8 benchmark(≥ 3 家 DS)
|
|
96
|
+
3. Checkpoint sign-off
|
|
97
|
+
4. 落地 5-layer pipeline(typology + hook + audit + scaffold + memory)
|
|
98
|
+
|
|
99
|
+
## Cross-link
|
|
100
|
+
|
|
101
|
+
- `.claude/rules/story-rules.md`「拆分原則」— canonical 上游 one-liner
|
|
102
|
+
- `/story-writing` SKILL.md Phase 0 — write-time mapping
|
|
103
|
+
- Hook `check_story_category.sh` — pre-write enforcement(攔不符 trait core)
|
|
104
|
+
- `/design-system-audit` Dim 29 — periodic verify
|
|
105
|
+
- `/new-component` Phase 5 — 新元件 trait-based scaffold
|
|
106
|
+
- `scripts/compile-stories.mjs` — runtime trait → required stories check
|
|
107
|
+
|
|
108
|
+
# Principles canonical(設計原則層,2026-04-26 加)
|
|
109
|
+
|
|
110
|
+
第三層 stories `{name}.principles.stories.tsx` 的 canonical structure。對齊 M8 benchmark(Polaris / Carbon / Ant 3 家 verifiable):
|
|
111
|
+
|
|
112
|
+
## 世界級對照
|
|
113
|
+
|
|
114
|
+
3 種哲學:
|
|
115
|
+
- **Carbon**(超嚴謹):~10 H2(`Overview / Formatting / Content / Universal behaviors / Modifiers / Related`)
|
|
116
|
+
- **Polaris**(中等):4 H2(`Best practices / Content guidelines / Related components / Accessibility`)
|
|
117
|
+
- **Ant**(極薄):1 H2(`When To Use`)
|
|
118
|
+
|
|
119
|
+
採 **Polaris-aligned 中等**(避免 Carbon-style 過細 + Ant-style 過薄)+ 接受既有 project naming(`VsXRule` 對齊 Carbon「X versus Y」)。
|
|
120
|
+
|
|
121
|
+
## Universal core(每元件 ≥ 1)— 2026-04-26 v3 整合
|
|
122
|
+
|
|
123
|
+
**重要**:WhenToUse + WhenNotToUse + VsXRule 都教「何時用 X」decision tree,**過度切割造成 noise**。對齊 Polaris/Material/Ant 共識(ONE integrated section),預設整合成單一 story。
|
|
124
|
+
|
|
125
|
+
| Story name(canonical)| 教什麼 | 世界級 anchor |
|
|
126
|
+
|---------------------|--------|---------------|
|
|
127
|
+
| **`UsageGuidance`**(預設,整合)| **何時用 + 何時不用 + 替代元件 / sibling comparison** 統一 decision tree | Polaris `Best practices` / Material `Usage` / Ant `When To Use`(共識) |
|
|
128
|
+
| `Vs{Sibling}Rule` | 視覺 deep-dive 對照(若需要 visual matrix 比較,deep-dive 才用)| Carbon `X versus Y` H3 |
|
|
129
|
+
| `ContentGuidelines` | 文案 do/don't(若元件 render 使用者文案)| Polaris `Content guidelines` H2 |
|
|
130
|
+
|
|
131
|
+
**判斷整合 vs split**:
|
|
132
|
+
- 對 80% 元件:**ONE `UsageGuidance`** 涵蓋 何時用 / 何時不用 / sibling 已足夠 — 對齊 Polaris/Material/Ant
|
|
133
|
+
- 對 20% 元件(超複雜 sibling matrix,如 Toast vs Alert vs Dialog):integrate 後加 `VsXRule` deep-dive(視覺 do/don't 對照,文字無法表達)
|
|
134
|
+
- `ContentGuidelines` 永遠獨立(文案 vs 元件選擇 是不同主題)
|
|
135
|
+
|
|
136
|
+
**Legacy aliases 接受**(不強制 rename 既存 stories):
|
|
137
|
+
- `WhenToUse` / `WhenNotToUse` / `Vs*Rule` 任 1 已存在 = 算「has core」
|
|
138
|
+
- 新元件用 `UsageGuidance` 整合單一 story
|
|
139
|
+
|
|
140
|
+
**規則**:每元件 principles 至少 **2 個 stories**(任意 combo:canonical 4 + component-specific `*Rule` + 描述性名稱如 `BlueConnectorLogic` / `ParentControlled` 都算 valid)。**全 4 個必有** = over-engineer(Polaris 4/4,但 Carbon Ant 都不到);**少於 2 stories** = principles 太薄無教學價值。Audit `audit-content-quality.mjs` 採寬鬆 ≥ 2 exports 標準(承認既有 component-specific naming idiom)。
|
|
141
|
+
|
|
142
|
+
## Canonical naming(取代既有 drift 變體)
|
|
143
|
+
|
|
144
|
+
| 既有 drift 命名 | Canonical | Rationale |
|
|
145
|
+
|---------------|-----------|-----------|
|
|
146
|
+
| `Forbidden*` / `Donts` / `Pitfalls` / `Prohibitions` / `NonGoals` / `VisualDonts` | **`WhenNotToUse`** | Polaris/Carbon 共識用「When NOT to use」semantics |
|
|
147
|
+
| `UsageScenarioRule` / `WhatItIs` / `MvpScope` | **`WhenToUse`** | 對齊 Polaris/Carbon/Ant 三家 |
|
|
148
|
+
| `Vs{X}Rule`(`VsTabsRule` / `VsCheckboxRule` 等) | **保留**(對齊 Carbon `versus` idiom)| 已是世界級 |
|
|
149
|
+
| `{Topic}Rule`(其他 component-specific) | **保留**(過 earn-existence 即可)| 可選 component-specific 規則 |
|
|
150
|
+
|
|
151
|
+
## 可選 stories(過 earn-existence)
|
|
152
|
+
|
|
153
|
+
- `VariantDecision` — 元件 ≥ 3 variants 各自 semantic 不同(Button / Banner / Notification)時可加
|
|
154
|
+
- `CompositionRules` — 元件可 non-trivial 組合(Field family / ActionBar)時可加
|
|
155
|
+
- `AccessibilityNotes` — 非 mechanical a11y(mechanical 留 anatomy)
|
|
156
|
+
- 其他 component-specific `XRule` — 過 earn-existence 2-test
|
|
157
|
+
|
|
158
|
+
## 跟 anatomy / showcase 分權
|
|
159
|
+
|
|
160
|
+
| 該放 principles | 該放 anatomy | 該放 showcase |
|
|
161
|
+
|-----------------|--------------|---------------|
|
|
162
|
+
| Do/don't 視覺對照 | Token / size matrix | 真實場景 + variant grid |
|
|
163
|
+
| 跟近親元件比較 | Inspector 數值 | AllVariants / AllSizes |
|
|
164
|
+
| 何時用 / 不該用 | StateBehavior 視覺 | Disabled / Loading state demo |
|
|
165
|
+
| 文案 / 內容 guidelines | ColorMatrix | 業務 scenario 範例 |
|
|
166
|
+
|
|
167
|
+
**禁止**:do/don't 對照放 showcase(屬 principles)/ token table 放 showcase(屬 anatomy)/ 純 variant grid 無 rule 放 principles(屬 showcase)。
|
|
168
|
+
|
|
169
|
+
## 強制機制
|
|
170
|
+
|
|
171
|
+
- **Hook** `check_principles_canonical.sh`:PreToolUse 攔不符 ≥ 2 universal core
|
|
172
|
+
- **Audit Dim 30**:periodic verify
|
|
173
|
+
- **`/new-component` Phase 5.3**:scaffold 4 universal stories template
|
|
174
|
+
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# 範例選擇原則(完整)
|
|
2
|
+
|
|
3
|
+
每次新增、修改、或審查 story 範例時的第一準則——適用 `.stories.tsx` / `.principles.stories.tsx` / `.anatomy.stories.tsx` 的所有範例情境。
|
|
4
|
+
|
|
5
|
+
## 最高準則:用耳熟能詳的真實業務場景,禁止極端 / 虛構 / 佔位案例
|
|
6
|
+
|
|
7
|
+
Storybook 是**公開文件**,受眾是任何打開的設計師 / 開發者 / PM。範例的核心功能是**教學**,不是展示元件能跑——不是跑得起來就算,而是要讓讀者從範例**推得出自己產品該怎麼用**。
|
|
8
|
+
|
|
9
|
+
## 合法場景來源(按優先序)
|
|
10
|
+
|
|
11
|
+
1. **對標世界級 SaaS 的真實功能**:Jira task status、Linear priority、Slack DM notification、Notion settings toggle、Figma toolbar、GitHub PR review、Stripe 付款、Airtable filter、Google Docs 權限設定
|
|
12
|
+
2. **台灣 / 全球常見業務流程**:電商結帳(信用卡 / 轉帳 / 貨到付款)、訂閱方案(月付 / 年付 / 企業)、文件協作(編輯 / 評論 / 唯讀)、表單提交(送出 / 儲存草稿 / 放棄變更)
|
|
13
|
+
3. **該元件原生生態的慣用場景**:Segmented 的「全部 / 進行中 / 已完成」、Tabs 的「總覽 / 活動 / 成員 / 設定」、RadioGroup 的付款方式、Checkbox 的同意條款
|
|
14
|
+
|
|
15
|
+
## 明確禁止
|
|
16
|
+
|
|
17
|
+
| 禁止類型 | 範例 | 為什麼 |
|
|
18
|
+
|---------|------|-------|
|
|
19
|
+
| **佔位符** | `Option A / B / C`、`Lorem ipsum`、`foo / bar`、`Test value` | 無情境,讀者學不到任何東西 |
|
|
20
|
+
| **抽象代號** | `按鈕一 / 按鈕二`、`Variant X`、`Rule A / B` | 不是產品語言,破壞「受眾是設計師」的前提 |
|
|
21
|
+
| **極端不現實案例** | 單 button「刪除全部使用者資料包含備份無法復原」、filter 有 50 個項目、dialog 嵌套 5 層 | 非日常使用情境,失去教學價值 |
|
|
22
|
+
| **視覺符號表達式** | `│─ 業務 ─│`、`A → B → C`、ASCII art | 不是產品 UI,污染 Storybook 視覺 |
|
|
23
|
+
| **spec 內部代號** | 「符合 Rule 3.2」「遵循 Convention A」 | 讀者沒讀 spec 也要看得懂 |
|
|
24
|
+
|
|
25
|
+
## 兩個驗收 test(寫完 / 審時自問)
|
|
26
|
+
|
|
27
|
+
### Test 1 — 「人」test
|
|
28
|
+
新加入的設計師打開 Storybook,**遮住所有 title / label / note**,只看元件裡的文字和情境,能不能 5 秒內說出「喔這是在做 X 流程」?
|
|
29
|
+
- 能 → 場景有教學力
|
|
30
|
+
- 不能 → 改成具體業務場景,不是補說明文字
|
|
31
|
+
|
|
32
|
+
### Test 2 — 「舉一反三」test
|
|
33
|
+
讀者看完這 3-5 個範例,**推得出自己專案類似情境該怎麼用嗎**?
|
|
34
|
+
- 能 → 範例涵蓋了決策維度(如 RadioGroup 的付款方式 + 訂閱方案 + 權限角色 = 教會讀者「決策節點類」的三個面向)
|
|
35
|
+
- 不能 → 範例之間同質、缺維度——增加互補場景而非重複
|
|
36
|
+
|
|
37
|
+
**黃金比例**:5 個具代表性的真實場景 > 20 個重複 placeholder。
|
|
38
|
+
|
|
39
|
+
## 正確範例(✅)對照
|
|
40
|
+
|
|
41
|
+
- **Button**:「送出表單 / 儲存草稿 / 放棄變更」(表單流程三按鈕)、「刪除專案」(destructive confirm)
|
|
42
|
+
- **Badge**:「3 個新通知」、「未讀訊息 12」、「必填」、「Beta」
|
|
43
|
+
- **SegmentedControl**:「總覽 / 活動 / 成員 / 設定」(workspace tab)、「日 / 週 / 月」(時間範圍)
|
|
44
|
+
- **RadioGroup**:「信用卡 / 銀行轉帳 / 超商付款」(付款方式)、「月付 / 年付(省 20%)/ 企業」(訂閱)
|
|
45
|
+
- **Switch**:「Bluetooth 開 / 關」、「Email 通知」、「Dark mode」
|
|
46
|
+
- **Checkbox**:「我同意服務條款」、「寄送促銷 email」(訂閱偏好)
|
|
47
|
+
|
|
48
|
+
## 適用範圍
|
|
49
|
+
|
|
50
|
+
| Story 類型 | 適用性 | 備註 |
|
|
51
|
+
|-----------|-------|------|
|
|
52
|
+
| `.principles.stories.tsx` | **最嚴格** | 教學性高,範例品質 = 設計系統品質 |
|
|
53
|
+
| `.stories.tsx`(展示) | 嚴格 | 範例代表元件「日常應該長這樣」,不是 test case |
|
|
54
|
+
| `.anatomy.stories.tsx` | 彈性 | token 藍圖 / inspect 面板可用合成內容,但**元件渲染範例仍須真實場景** |
|
|
55
|
+
| `explorations/` | 寬鬆 | 比稿可用抽象內容,但定案後轉入正式系統前須替換 |
|
|
56
|
+
|
|
57
|
+
## Rule note 品質
|
|
58
|
+
|
|
59
|
+
**Rule note 必須傳達原則而非結論**,讓讀者能舉一反三——寫「為什麼」而不只是「是什麼」。例如:
|
|
60
|
+
- ❌「禁止 primary」 → ✅「工具層必須是視覺重量最低的一層,否則搶走業務焦點」
|
|
61
|
+
- ❌「全程 icon-only」 → ✅「這些 icon 在此脈絡下約定俗成,使用者不需 label 就能辨識」
|
|
62
|
+
|
|
63
|
+
## 視覺與文案品質
|
|
64
|
+
|
|
65
|
+
- **Toolbar 範例**統一使用 `ToolbarFrame`(滿版 + 短標題),不用裸 `ButtonGroup` 漂在半空
|
|
66
|
+
- `ToolbarFrame` 標題模擬真實產品(2–4 字如「文件」「專案」),說明放在下方 `Label`,不塞進標題導致文字與按鈕碰撞
|
|
67
|
+
- 同一個 story 內的範例容器必須一致,不混用不同寬度
|
|
68
|
+
- ❌/✅ 判斷放在 `Label`,不放在 ToolbarFrame 標題內
|
|
69
|
+
- **排版層級清晰**:主標用 `h3`(深色、正常大小),副標用 `text-caption`(灰色、限寬 720px),Label 用 `text-footnote`(最小字、範例解說)。三層視覺上必須有明顯區隔
|
|
70
|
+
- **icon-only 按鈕有 `aria-label`**;互動範例可用鍵盤操作
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Story 自我檢查清單
|
|
2
|
+
|
|
3
|
+
寫完 / 審時逐條打勾:
|
|
4
|
+
|
|
5
|
+
- [ ] 所有範例文字是真實產品可能出現的句子(不是 Option A/B/C、不是「按鈕一」)
|
|
6
|
+
- [ ] 每個範例可追溯到世界級 SaaS 或常見業務場景(能說出「這參考 Jira / Stripe / Notion 哪個功能」)
|
|
7
|
+
- [ ] 沒有極端不現實案例(50 個 filter、5 層 dialog、單 button 寫滿 3 行)
|
|
8
|
+
- [ ] 「人」test 通過(遮標題光看元件懂情境)
|
|
9
|
+
- [ ] 「舉一反三」test 通過(讀者能推出自己產品該怎麼用)
|
|
10
|
+
- [ ] Label / note 沒有 spec 代號(Rule A、Variant X)或抽象符號表達式
|
|
11
|
+
- [ ] Rule note 傳達原則(「為什麼」),不只是結論(「是什麼」)
|
|
12
|
+
- [ ] 檔內註解語言一致(中文檔純中文、英文檔純英文,不中英夾雜)
|
|
13
|
+
- [ ] 若是 anatomy:TOKEN_MAP / SIZE_SPECS 和 .tsx 的 cva 完全一致
|
|
14
|
+
|
|
15
|
+
## 交付前最後一輪
|
|
16
|
+
|
|
17
|
+
- [ ] `npm run storybook` 本地跑過,每個 story 視覺正常渲染
|
|
18
|
+
- [ ] `npx tsc --noEmit` 無錯
|
|
19
|
+
- [ ] dark mode 切換正常(色塊 / 文字色自動更新)
|
|
20
|
+
- [ ] density 切換正常(若元件屬 field-height family)
|