@qijenchen/design-system 0.1.0-beta.82 → 0.1.0-beta.84
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 +8 -8
- package/README.md +3 -2
- package/dist/components/Alert/alert.js.map +1 -1
- package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -1
- package/dist/components/AppShell/app-shell.d.ts +1 -1
- package/dist/components/AppShell/app-shell.d.ts.map +1 -1
- package/dist/components/AppShell/app-shell.js +22 -2
- package/dist/components/AppShell/app-shell.js.map +1 -1
- package/dist/components/Avatar/avatar.d.ts.map +1 -1
- package/dist/components/Avatar/avatar.js +4 -4
- package/dist/components/Avatar/avatar.js.map +1 -1
- package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -1
- package/dist/components/Breadcrumb/breadcrumb.js +1 -1
- package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
- package/dist/components/Button/button.d.ts +2 -2
- package/dist/components/Button/button.d.ts.map +1 -1
- package/dist/components/Button/button.js +12 -3
- package/dist/components/Button/button.js.map +1 -1
- package/dist/components/Calendar/calendar.d.ts +13 -5
- package/dist/components/Calendar/calendar.d.ts.map +1 -1
- package/dist/components/Calendar/calendar.js +7 -1
- package/dist/components/Calendar/calendar.js.map +1 -1
- package/dist/components/Carousel/carousel.d.ts.map +1 -1
- package/dist/components/Carousel/carousel.js +8 -3
- package/dist/components/Carousel/carousel.js.map +1 -1
- package/dist/components/Chart/chart.d.ts.map +1 -1
- package/dist/components/Chart/chart.js +1 -0
- package/dist/components/Chart/chart.js.map +1 -1
- package/dist/components/Checkbox/checkbox.d.ts +1 -1
- package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox/checkbox.js +8 -4
- package/dist/components/Checkbox/checkbox.js.map +1 -1
- package/dist/components/Chip/chip.d.ts +1 -1
- package/dist/components/Chip/chip.d.ts.map +1 -1
- package/dist/components/Chip/chip.js.map +1 -1
- package/dist/components/Coachmark/coachmark.d.ts +10 -3
- package/dist/components/Coachmark/coachmark.d.ts.map +1 -1
- package/dist/components/Coachmark/coachmark.js.map +1 -1
- package/dist/components/Combobox/combobox.d.ts +5 -1
- package/dist/components/Combobox/combobox.d.ts.map +1 -1
- package/dist/components/Combobox/combobox.js +30 -13
- package/dist/components/Combobox/combobox.js.map +1 -1
- package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
- package/dist/components/DataTable/cell-registry.js +53 -62
- package/dist/components/DataTable/cell-registry.js.map +1 -1
- package/dist/components/DataTable/column-types.d.ts +10 -4
- package/dist/components/DataTable/column-types.d.ts.map +1 -1
- package/dist/components/DataTable/column-types.js.map +1 -1
- package/dist/components/DataTable/data-table-column-visibility-panel.d.ts +1 -1
- package/dist/components/DataTable/data-table-column-visibility-panel.js +183 -0
- package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -0
- package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-filter-panel.js +607 -0
- package/dist/components/DataTable/data-table-filter-panel.js.map +1 -0
- package/dist/components/DataTable/data-table-interaction-layer.d.ts +11 -15
- package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-interaction-layer.js +1 -3
- package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
- package/dist/components/DataTable/data-table-sort-manager.js +140 -0
- package/dist/components/DataTable/data-table-sort-manager.js.map +1 -0
- package/dist/components/DataTable/data-table.d.ts +5 -6
- package/dist/components/DataTable/data-table.d.ts.map +1 -1
- package/dist/components/DataTable/data-table.js +36 -15
- package/dist/components/DataTable/data-table.js.map +1 -1
- package/dist/components/DataTable/filter-operators.js +140 -0
- package/dist/components/DataTable/filter-operators.js.map +1 -0
- package/dist/components/DataTable/filter-tree.js +312 -0
- package/dist/components/DataTable/filter-tree.js.map +1 -0
- package/dist/components/DataTable/index.d.ts +3 -0
- package/dist/components/DataTable/index.d.ts.map +1 -1
- package/dist/components/DataTable/index.js +12 -1
- package/dist/components/DataTable/index.js.map +1 -1
- package/dist/components/DataTable/lib/column-meta.js +25 -0
- package/dist/components/DataTable/lib/column-meta.js.map +1 -0
- package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
- package/dist/components/DateGrid/date-grid.js +3 -1
- package/dist/components/DateGrid/date-grid.js.map +1 -1
- package/dist/components/DatePicker/date-picker.d.ts +7 -1
- package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
- package/dist/components/DatePicker/date-picker.js +105 -74
- package/dist/components/DatePicker/date-picker.js.map +1 -1
- package/dist/components/Dialog/dialog.d.ts +20 -3
- package/dist/components/Dialog/dialog.d.ts.map +1 -1
- package/dist/components/Dialog/dialog.js +38 -20
- package/dist/components/Dialog/dialog.js.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.js +3 -1
- package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
- package/dist/components/Field/field-context.d.ts +45 -5
- package/dist/components/Field/field-context.d.ts.map +1 -1
- package/dist/components/Field/field-context.js +19 -0
- package/dist/components/Field/field-context.js.map +1 -1
- package/dist/components/Field/field-edit-keys.d.ts +21 -0
- package/dist/components/Field/field-edit-keys.d.ts.map +1 -0
- package/dist/components/Field/field-edit-keys.js +19 -0
- package/dist/components/Field/field-edit-keys.js.map +1 -0
- package/dist/components/Field/field-types.d.ts +20 -1
- package/dist/components/Field/field-types.d.ts.map +1 -1
- package/dist/components/Field/field-types.js.map +1 -1
- package/dist/components/Field/field-wrapper.d.ts +3 -2
- package/dist/components/Field/field-wrapper.d.ts.map +1 -1
- package/dist/components/Field/field-wrapper.js +38 -39
- package/dist/components/Field/field-wrapper.js.map +1 -1
- package/dist/components/Field/field.d.ts +2 -1
- package/dist/components/Field/field.d.ts.map +1 -1
- package/dist/components/Field/field.js.map +1 -1
- package/dist/components/FieldControlGroup/field-control-group.d.ts +1 -1
- package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
- package/dist/components/FileItem/file-item.d.ts.map +1 -1
- package/dist/components/FileItem/file-item.js +1 -1
- package/dist/components/FileItem/file-item.js.map +1 -1
- package/dist/components/FileUpload/file-upload.d.ts +1 -1
- package/dist/components/FileUpload/file-upload.js.map +1 -1
- package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
- package/dist/components/FileViewer/file-viewer.js +7 -2
- package/dist/components/FileViewer/file-viewer.js.map +1 -1
- package/dist/components/FileViewer/image-renderer.d.ts.map +1 -1
- package/dist/components/FileViewer/image-renderer.js +22 -1
- package/dist/components/FileViewer/image-renderer.js.map +1 -1
- package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
- package/dist/components/HoverCard/hover-card.js +5 -3
- package/dist/components/HoverCard/hover-card.js.map +1 -1
- package/dist/components/InlineEdit/index.d.ts +2 -0
- package/dist/components/InlineEdit/index.d.ts.map +1 -0
- package/dist/components/InlineEdit/index.js +5 -0
- package/dist/components/InlineEdit/index.js.map +1 -0
- package/dist/components/InlineEdit/inline-edit.d.ts +59 -0
- package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -0
- package/dist/components/InlineEdit/inline-edit.js +164 -0
- package/dist/components/InlineEdit/inline-edit.js.map +1 -0
- package/dist/components/Input/input.d.ts +6 -11
- package/dist/components/Input/input.d.ts.map +1 -1
- package/dist/components/Input/input.js +43 -13
- package/dist/components/Input/input.js.map +1 -1
- package/dist/components/LinkInput/link-input.d.ts +2 -2
- package/dist/components/LinkInput/link-input.d.ts.map +1 -1
- package/dist/components/LinkInput/link-input.js +6 -5
- package/dist/components/LinkInput/link-input.js.map +1 -1
- package/dist/components/Menu/menu-item.d.ts +14 -2
- package/dist/components/Menu/menu-item.d.ts.map +1 -1
- package/dist/components/Menu/menu-item.js +25 -3
- package/dist/components/Menu/menu-item.js.map +1 -1
- package/dist/components/NumberInput/number-input.d.ts +3 -3
- package/dist/components/NumberInput/number-input.d.ts.map +1 -1
- package/dist/components/NumberInput/number-input.js +6 -5
- package/dist/components/NumberInput/number-input.js.map +1 -1
- package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
- package/dist/components/OverflowIndicator/overflow-indicator.js +2 -6
- package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
- package/dist/components/Pagination/pagination.js +1 -1
- package/dist/components/Pagination/pagination.js.map +1 -1
- package/dist/components/PeoplePicker/index.js +7 -1
- package/dist/components/PeoplePicker/index.js.map +1 -1
- package/dist/components/PeoplePicker/people-picker.d.ts +9 -2
- package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
- package/dist/components/PeoplePicker/people-picker.js +23 -10
- package/dist/components/PeoplePicker/people-picker.js.map +1 -1
- package/dist/components/PeoplePicker/person-display.d.ts +6 -3
- package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
- package/dist/components/PeoplePicker/person-display.js +19 -14
- package/dist/components/PeoplePicker/person-display.js.map +1 -1
- package/dist/components/Popover/popover.d.ts.map +1 -1
- package/dist/components/Popover/popover.js +3 -1
- package/dist/components/Popover/popover.js.map +1 -1
- package/dist/components/ProfileCard/profile-card.d.ts +2 -2
- package/dist/components/ProfileCard/profile-card.js +3 -3
- package/dist/components/ProfileCard/profile-card.js.map +1 -1
- package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
- package/dist/components/RadioGroup/radio-group.js +15 -9
- package/dist/components/RadioGroup/radio-group.js.map +1 -1
- package/dist/components/ScrollArea/scroll-area.d.ts +11 -1
- package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
- package/dist/components/ScrollArea/scroll-area.js +6 -3
- package/dist/components/ScrollArea/scroll-area.js.map +1 -1
- package/dist/components/Select/select.d.ts +46 -5
- package/dist/components/Select/select.d.ts.map +1 -1
- package/dist/components/Select/select.js +109 -28
- package/dist/components/Select/select.js.map +1 -1
- package/dist/components/SelectMenu/select-menu.d.ts +3 -1
- package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
- package/dist/components/SelectMenu/select-menu.js +8 -1
- package/dist/components/SelectMenu/select-menu.js.map +1 -1
- package/dist/components/SelectionControl/boolean-value.d.ts +11 -0
- package/dist/components/SelectionControl/boolean-value.d.ts.map +1 -0
- package/dist/components/SelectionControl/boolean-value.js +23 -0
- package/dist/components/SelectionControl/boolean-value.js.map +1 -0
- package/dist/components/SelectionControl/index.d.ts +1 -0
- package/dist/components/SelectionControl/index.d.ts.map +1 -1
- package/dist/components/SelectionControl/index.js +2 -0
- package/dist/components/SelectionControl/index.js.map +1 -1
- package/dist/components/Sheet/index.js +2 -1
- package/dist/components/Sheet/sheet.d.ts +7 -1
- package/dist/components/Sheet/sheet.d.ts.map +1 -1
- package/dist/components/Sheet/sheet.js +5 -2
- package/dist/components/Sheet/sheet.js.map +1 -1
- package/dist/components/Sidebar/sidebar.d.ts +9 -4
- package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
- package/dist/components/Sidebar/sidebar.js +8 -10
- package/dist/components/Sidebar/sidebar.js.map +1 -1
- package/dist/components/Slider/slider.d.ts.map +1 -1
- package/dist/components/Slider/slider.js.map +1 -1
- package/dist/components/Switch/switch.d.ts +6 -6
- package/dist/components/Switch/switch.d.ts.map +1 -1
- package/dist/components/Switch/switch.js +3 -2
- package/dist/components/Switch/switch.js.map +1 -1
- package/dist/components/Tabs/tabs.d.ts.map +1 -1
- package/dist/components/Tabs/tabs.js +15 -1
- package/dist/components/Tabs/tabs.js.map +1 -1
- package/dist/components/Textarea/textarea.d.ts +2 -2
- package/dist/components/Textarea/textarea.d.ts.map +1 -1
- package/dist/components/Textarea/textarea.js +50 -42
- package/dist/components/Textarea/textarea.js.map +1 -1
- package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
- package/dist/components/TimePicker/time-columns.js +42 -38
- package/dist/components/TimePicker/time-columns.js.map +1 -1
- package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
- package/dist/components/TimePicker/time-picker.js +8 -6
- package/dist/components/TimePicker/time-picker.js.map +1 -1
- package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
- package/dist/components/Tooltip/tooltip.js +7 -5
- package/dist/components/Tooltip/tooltip.js.map +1 -1
- package/dist/components/TreeView/tree-view.d.ts +56 -1
- package/dist/components/TreeView/tree-view.d.ts.map +1 -1
- package/dist/components/TreeView/tree-view.js +211 -12
- package/dist/components/TreeView/tree-view.js.map +1 -1
- package/dist/index.d.ts +115 -58
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +93 -108
- package/dist/index.js.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.d.ts +7 -6
- package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
- package/dist/tokens/categorical-color.js +15 -0
- package/dist/tokens/categorical-color.js.map +1 -1
- package/dist/tokens/motion/motion.d.ts +7 -6
- package/dist/tokens/motion/motion.d.ts.map +1 -1
- package/dist/tokens/motion/motion.js +6 -6
- package/dist/tokens/motion/motion.js.map +1 -1
- package/dist/tokens/motion/overlay-motion.d.ts +19 -0
- package/dist/tokens/motion/overlay-motion.d.ts.map +1 -0
- package/dist/tokens/motion/overlay-motion.js +9 -0
- package/dist/tokens/motion/overlay-motion.js.map +1 -0
- package/dist/tokens/uiSize/icon-size.js +5 -0
- package/dist/tokens/uiSize/icon-size.js.map +1 -0
- package/ds-canonical/fork/governance.lock +37 -19
- package/ds-canonical/fork/hooks/_log-fire.sh +46 -0
- package/ds-canonical/fork/hooks/block_prototype_imports.py +15 -4
- package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +145 -13
- package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +17 -5
- package/ds-canonical/fork/hooks/check_dynamic_tailwind_class.sh +47 -0
- package/ds-canonical/fork/hooks/check_escape_marker_abuse.sh +27 -0
- package/ds-canonical/fork/hooks/check_field_family_invariants.sh +61 -1
- package/ds-canonical/fork/hooks/check_layout_space_magic_numbers.sh +28 -4
- package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +36 -0
- package/ds-canonical/fork/hooks/check_story_determinism.sh +39 -0
- package/ds-canonical/fork/hooks/check_story_invariants.sh +119 -0
- package/ds-canonical/fork/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
- package/ds-canonical/fork/manifest.json +20 -0
- package/ds-canonical/fork/preamble.md +22 -18
- package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +9 -3
- package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +3 -3
- package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +7 -0
- package/ds-canonical/fork/skills/performance-audit/SKILL.md +4 -2
- package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +3 -3
- package/ds-canonical/fork/skills/propose-options/SKILL.md +3 -3
- package/ds-canonical/fork/skills/prototype/SKILL.md +1 -1
- package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +2 -2
- package/ds-canonical/fork/skills/visual-audit/SKILL.md +10 -2
- package/ds-canonical/hooks/README.md +1 -1
- package/ds-canonical/hooks/block_prototype_imports.py +15 -4
- package/ds-canonical/hooks/check_audit_post_report_validator.sh +65 -7
- package/ds-canonical/hooks/check_benchmark_citation.sh +5 -3
- package/ds-canonical/hooks/check_codex_brief_invariants.sh +28 -1
- package/ds-canonical/hooks/check_consumer_app_invariants.sh +145 -13
- package/ds-canonical/hooks/check_ds_anchor_preflight.sh +17 -5
- package/ds-canonical/hooks/check_dynamic_tailwind_class.sh +47 -0
- package/ds-canonical/hooks/check_escape_marker_abuse.sh +27 -0
- package/ds-canonical/hooks/check_field_family_invariants.sh +61 -1
- package/ds-canonical/hooks/check_layout_space_magic_numbers.sh +28 -4
- package/ds-canonical/hooks/check_naming_and_abstraction.sh +1 -1
- package/ds-canonical/hooks/check_opacity_token_usage.sh +36 -0
- package/ds-canonical/hooks/check_pixel_quantified_audit.sh +3 -2
- package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +6 -1
- package/ds-canonical/hooks/check_propose_without_benchmark.sh +6 -2
- package/ds-canonical/hooks/check_ssot_header_declaration.sh +55 -0
- package/ds-canonical/hooks/check_story_determinism.sh +39 -0
- package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +8 -7
- package/ds-canonical/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
- package/ds-canonical/hooks/lib/_story_compile_drift.sh +1 -1
- package/ds-canonical/hooks/lib/_token_hygiene.sh +10 -1
- package/ds-canonical/hooks/stop_self_audit.sh +31 -0
- package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +24 -0
- package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +44 -0
- package/ds-canonical/hooks/tests/test_check_benchmark_citation.sh +3 -3
- package/ds-canonical/hooks/tests/test_check_codex_brief_invariants.sh +43 -2
- package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +112 -0
- package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +9 -2
- package/ds-canonical/hooks/tests/test_check_dynamic_tailwind_class.sh +76 -0
- package/ds-canonical/hooks/tests/test_check_escape_marker_abuse.sh +24 -0
- package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +27 -2
- package/ds-canonical/hooks/tests/test_check_fork_user_plugin_install.sh +3 -1
- package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +41 -2
- package/ds-canonical/hooks/tests/test_check_ssot_header_declaration.sh +72 -0
- package/ds-canonical/hooks/tests/test_check_tabs_content_chrome_body_double_gap.sh +76 -0
- package/ds-canonical/references/audit-coverage-vs-24-checklist.md +1 -1
- package/ds-canonical/references/build-ui-canonicals.md +2 -1
- package/ds-canonical/references/failure-class-registry.json +145 -0
- package/ds-canonical/references/governance-audit-coverage.md +33 -0
- package/ds-canonical/references/item-anatomy-recipe.md +2 -2
- package/ds-canonical/references/scenario-definition.md +6 -9
- package/ds-canonical/references/ssot-consultation.md +2 -2
- package/ds-canonical/references/ssot-index.md +5 -4
- package/ds-canonical/references/story-baseline-registry.json +8 -2
- package/ds-canonical/references/structural-token-retention.md +6 -9
- package/ds-canonical/rules/meta-patterns.md +8 -8
- package/ds-canonical/rules/self-verify.md +4 -3
- package/ds-canonical/rules/spec-rules.md +1 -1
- package/ds-canonical/rules/story-rules.md +2 -2
- package/ds-canonical/rules/ui-development.md +4 -2
- package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +9 -3
- package/ds-canonical/skills/code-quality-audit/SKILL.md +3 -3
- package/ds-canonical/skills/codex-collab/SKILL.md +9 -7
- package/ds-canonical/skills/codex-collab/references/brief-template.md +1 -1
- package/ds-canonical/skills/codify-principle/SKILL.md +2 -2
- package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
- package/ds-canonical/skills/component-quality-gate/references/checklist.md +2 -2
- package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +57 -68
- package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +29 -0
- package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +29 -10
- package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +21 -0
- package/ds-canonical/skills/delivery-handoff/SKILL.md +5 -0
- package/ds-canonical/skills/design-system-audit/SKILL.md +27 -26
- package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +13 -1
- package/ds-canonical/skills/design-system-audit/references/rule-placement.md +1 -1
- package/ds-canonical/skills/governance-health/SKILL.md +2 -1
- package/ds-canonical/skills/knowledge-prune/SKILL.md +3 -0
- package/ds-canonical/skills/knowledge-prune/references/prune-dimensions-d5-d10.md +1 -0
- package/ds-canonical/skills/new-component/SKILL.md +7 -5
- package/ds-canonical/skills/new-component/references/new-component-checklist.md +1 -1
- package/ds-canonical/skills/performance-audit/SKILL.md +2 -2
- package/ds-canonical/skills/product-ui-audit/SKILL.md +3 -3
- package/ds-canonical/skills/propose-options/SKILL.md +3 -3
- package/ds-canonical/skills/prototype/SKILL.md +1 -1
- package/ds-canonical/skills/scan-similar-bugs/SKILL.md +2 -2
- package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +3 -3
- package/ds-canonical/skills/story-writing/SKILL.md +3 -3
- package/ds-canonical/skills/visual-audit/SKILL.md +10 -2
- package/ds-story-manifest.json +29 -20
- package/llms-full.txt +22 -1
- package/llms.txt +5 -4
- package/package.json +7 -3
- package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
- package/src/components/Accordion/accordion.stories.tsx +16 -1
- package/src/components/Alert/alert.principles.stories.tsx +1 -1
- package/src/components/Alert/alert.spec.md +8 -10
- package/src/components/Alert/alert.stories.tsx +28 -28
- package/src/components/Alert/alert.tsx +1 -1
- package/src/components/AppShell/_demo-helpers.tsx +6 -3
- package/src/components/AppShell/app-shell.spec.md +4 -4
- package/src/components/AppShell/app-shell.tsx +28 -2
- package/src/components/AspectRatio/aspect-ratio.spec.md +1 -1
- package/src/components/AspectRatio/aspect-ratio.stories.tsx +7 -89
- package/src/components/Avatar/avatar.anatomy.stories.tsx +7 -3
- package/src/components/Avatar/avatar.principles.stories.tsx +19 -15
- package/src/components/Avatar/avatar.spec.md +2 -2
- package/src/components/Avatar/avatar.stories.tsx +8 -6
- package/src/components/Avatar/avatar.tsx +13 -5
- package/src/components/Badge/badge.principles.stories.tsx +1 -1
- package/src/components/Badge/badge.spec.md +2 -0
- package/src/components/Badge/badge.stories.tsx +4 -2
- package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +6 -4
- package/src/components/Breadcrumb/breadcrumb.stories.tsx +6 -5
- package/src/components/Breadcrumb/breadcrumb.tsx +3 -2
- package/src/components/BulkActionBar/bulk-action-bar.spec.md +4 -2
- package/src/components/Button/button.principles.stories.tsx +1 -1
- package/src/components/Button/button.spec.md +2 -2
- package/src/components/Button/button.tsx +18 -3
- package/src/components/Calendar/calendar.anatomy.stories.tsx +12 -10
- package/src/components/Calendar/calendar.principles.stories.tsx +14 -6
- package/src/components/Calendar/calendar.spec.md +5 -4
- package/src/components/Calendar/calendar.stories.tsx +7 -4
- package/src/components/Calendar/calendar.tsx +26 -7
- package/src/components/Carousel/carousel.anatomy.stories.tsx +5 -4
- package/src/components/Carousel/carousel.spec.md +2 -2
- package/src/components/Carousel/carousel.tsx +11 -3
- package/src/components/Chart/chart.anatomy.stories.tsx +7 -4
- package/src/components/Chart/chart.principles.stories.tsx +1 -1
- package/src/components/Chart/chart.stories.tsx +2 -8
- package/src/components/Chart/chart.tsx +3 -0
- package/src/components/Checkbox/checkbox.anatomy.stories.tsx +28 -49
- package/src/components/Checkbox/checkbox.principles.stories.tsx +1 -1
- package/src/components/Checkbox/checkbox.spec.md +11 -26
- package/src/components/Checkbox/checkbox.stories.tsx +11 -8
- package/src/components/Checkbox/checkbox.tsx +18 -13
- package/src/components/Chip/chip.anatomy.stories.tsx +44 -24
- package/src/components/Chip/chip.principles.stories.tsx +1 -1
- package/src/components/Chip/chip.spec.md +5 -4
- package/src/components/Chip/chip.tsx +5 -1
- package/src/components/CircularProgress/circular-progress.principles.stories.tsx +7 -4
- package/src/components/CircularProgress/circular-progress.spec.md +3 -3
- package/src/components/CircularProgress/circular-progress.stories.tsx +2 -2
- package/src/components/Coachmark/coachmark.anatomy.stories.tsx +2 -2
- package/src/components/Coachmark/coachmark.principles.stories.tsx +2 -1
- package/src/components/Coachmark/coachmark.spec.md +5 -5
- package/src/components/Coachmark/coachmark.stories.tsx +3 -1
- package/src/components/Coachmark/coachmark.tsx +10 -3
- package/src/components/Combobox/combobox.anatomy.stories.tsx +2 -2
- package/src/components/Combobox/combobox.tsx +53 -19
- package/src/components/Command/command.anatomy.stories.tsx +2 -2
- package/src/components/Command/command.principles.stories.tsx +1 -1
- package/src/components/Command/command.stories.tsx +42 -10
- package/src/components/DataTable/cell-registry.tsx +86 -63
- package/src/components/DataTable/column-types.ts +10 -1
- package/src/components/DataTable/data-table-column-visibility-panel.tsx +1 -1
- package/src/components/DataTable/data-table-filter-panel.tsx +4 -1
- package/src/components/DataTable/data-table-interaction-layer.tsx +15 -19
- package/src/components/DataTable/data-table.anatomy.stories.tsx +15 -13
- package/src/components/DataTable/data-table.principles.stories.tsx +9 -9
- package/src/components/DataTable/data-table.spec.md +32 -12
- package/src/components/DataTable/data-table.stories.tsx +16 -17
- package/src/components/DataTable/data-table.tsx +103 -60
- package/src/components/DataTable/index.ts +3 -0
- package/src/components/DateGrid/date-grid.anatomy.stories.tsx +4 -4
- package/src/components/DateGrid/date-grid.principles.stories.tsx +1 -1
- package/src/components/DateGrid/date-grid.spec.md +1 -1
- package/src/components/DateGrid/date-grid.tsx +3 -1
- package/src/components/DatePicker/date-picker.anatomy.stories.tsx +8 -8
- package/src/components/DatePicker/date-picker.principles.stories.tsx +3 -3
- package/src/components/DatePicker/date-picker.spec.md +3 -3
- package/src/components/DatePicker/date-picker.stories.tsx +4 -5
- package/src/components/DatePicker/date-picker.tsx +99 -45
- package/src/components/DescriptionList/description-list.anatomy.stories.tsx +12 -10
- package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
- package/src/components/DescriptionList/description-list.spec.md +3 -3
- package/src/components/DescriptionList/description-list.stories.tsx +7 -6
- package/src/components/Dialog/dialog.anatomy.stories.tsx +1 -0
- package/src/components/Dialog/dialog.spec.md +9 -0
- package/src/components/Dialog/dialog.stories.tsx +66 -5
- package/src/components/Dialog/dialog.tsx +60 -25
- package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +1 -1
- package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +8 -6
- package/src/components/DropdownMenu/dropdown-menu.spec.md +5 -5
- package/src/components/DropdownMenu/dropdown-menu.tsx +18 -9
- package/src/components/Empty/empty.anatomy.stories.tsx +1 -1
- package/src/components/Empty/empty.spec.md +2 -2
- package/src/components/Field/field-context.ts +69 -5
- package/src/components/Field/field-controls.spec.md +62 -8
- package/src/components/Field/field-edit-keys.ts +66 -0
- package/src/components/Field/field-types.ts +58 -9
- package/src/components/Field/field-wrapper.tsx +50 -42
- package/src/components/Field/field.anatomy.stories.tsx +9 -6
- package/src/components/Field/field.spec.md +1 -1
- package/src/components/Field/field.stories.tsx +1 -1
- package/src/components/Field/field.tsx +2 -1
- package/src/components/Field/form-validation.spec.md +3 -3
- package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +6 -6
- package/src/components/FieldControlGroup/field-control-group.spec.md +9 -4
- package/src/components/FieldControlGroup/field-control-group.tsx +1 -1
- package/src/components/FileItem/file-item.anatomy.stories.tsx +1 -1
- package/src/components/FileItem/file-item.spec.md +14 -8
- package/src/components/FileItem/file-item.stories.tsx +36 -25
- package/src/components/FileItem/file-item.tsx +8 -6
- package/src/components/FileUpload/file-upload.anatomy.stories.tsx +6 -6
- package/src/components/FileUpload/file-upload.principles.stories.tsx +5 -5
- package/src/components/FileUpload/file-upload.spec.md +1 -1
- package/src/components/FileUpload/file-upload.tsx +1 -1
- package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +4 -3
- package/src/components/FileViewer/file-viewer.principles.stories.tsx +3 -3
- package/src/components/FileViewer/file-viewer.spec.md +30 -12
- package/src/components/FileViewer/file-viewer.stories.tsx +1 -2
- package/src/components/FileViewer/file-viewer.tsx +12 -4
- package/src/components/FileViewer/image-renderer.tsx +35 -7
- package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -2
- package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -3
- package/src/components/HoverCard/hover-card.spec.md +5 -5
- package/src/components/HoverCard/hover-card.stories.tsx +16 -16
- package/src/components/HoverCard/hover-card.tsx +5 -3
- package/src/components/InlineEdit/index.ts +5 -0
- package/src/components/InlineEdit/inline-edit.spec.md +149 -0
- package/src/components/InlineEdit/inline-edit.stories.tsx +246 -0
- package/src/components/InlineEdit/inline-edit.tsx +287 -0
- package/src/components/Input/input.anatomy.stories.tsx +8 -7
- package/src/components/Input/input.principles.stories.tsx +2 -12
- package/src/components/Input/input.spec.md +13 -18
- package/src/components/Input/input.tsx +69 -22
- package/src/components/LinkInput/link-input.anatomy.stories.tsx +1 -1
- package/src/components/LinkInput/link-input.principles.stories.tsx +2 -2
- package/src/components/LinkInput/link-input.tsx +11 -10
- package/src/components/Menu/menu-item.anatomy.stories.tsx +3 -3
- package/src/components/Menu/menu-item.principles.stories.tsx +1 -1
- package/src/components/Menu/menu-item.spec.md +22 -15
- package/src/components/Menu/menu-item.stories.tsx +39 -11
- package/src/components/Menu/menu-item.tsx +38 -4
- package/src/components/Notice/notice.principles.stories.tsx +1 -1
- package/src/components/Notice/notice.spec.md +16 -3
- package/src/components/NumberInput/number-input.anatomy.stories.tsx +3 -3
- package/src/components/NumberInput/number-input.principles.stories.tsx +1 -1
- package/src/components/NumberInput/number-input.spec.md +4 -4
- package/src/components/NumberInput/number-input.tsx +19 -12
- package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +10 -8
- package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +3 -3
- package/src/components/OverflowIndicator/overflow-indicator.spec.md +4 -2
- package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +71 -63
- package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -8
- package/src/components/Pagination/pagination.spec.md +1 -1
- package/src/components/Pagination/pagination.stories.tsx +2 -6
- package/src/components/Pagination/pagination.tsx +1 -1
- package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +4 -4
- package/src/components/PeoplePicker/people-picker.principles.stories.tsx +2 -2
- package/src/components/PeoplePicker/people-picker.spec.md +6 -6
- package/src/components/PeoplePicker/people-picker.tsx +56 -16
- package/src/components/PeoplePicker/person-display.tsx +32 -16
- package/src/components/Popover/popover.anatomy.stories.tsx +2 -2
- package/src/components/Popover/popover.tsx +3 -1
- package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +12 -23
- package/src/components/ProfileCard/profile-card.spec.md +3 -3
- package/src/components/ProfileCard/profile-card.tsx +6 -6
- package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +3 -1
- package/src/components/ProgressBar/progress-bar.principles.stories.tsx +1 -1
- package/src/components/ProgressBar/progress-bar.stories.tsx +50 -42
- package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +10 -28
- package/src/components/RadioGroup/radio-group.stories.tsx +29 -32
- package/src/components/RadioGroup/radio-group.tsx +41 -15
- package/src/components/Rating/rating.spec.md +11 -3
- package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
- package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
- package/src/components/ScrollArea/scroll-area.spec.md +7 -3
- package/src/components/ScrollArea/scroll-area.stories.tsx +1 -1
- package/src/components/ScrollArea/scroll-area.tsx +17 -4
- package/src/components/Select/select.anatomy.stories.tsx +3 -3
- package/src/components/Select/select.spec.md +27 -17
- package/src/components/Select/select.stories.tsx +33 -0
- package/src/components/Select/select.tsx +190 -36
- package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +4 -4
- package/src/components/SelectMenu/select-menu.spec.md +15 -7
- package/src/components/SelectMenu/select-menu.tsx +16 -3
- package/src/components/SelectionControl/boolean-value.tsx +39 -0
- package/src/components/SelectionControl/index.ts +1 -0
- package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +2 -2
- package/src/components/SelectionControl/selection-item.principles.stories.tsx +2 -2
- package/src/components/SelectionControl/selection-item.spec.md +3 -3
- package/src/components/SelectionControl/selection-item.stories.tsx +3 -3
- package/src/components/Separator/separator.spec.md +2 -2
- package/src/components/Separator/separator.stories.tsx +6 -27
- package/src/components/Sheet/sheet.anatomy.stories.tsx +1 -1
- package/src/components/Sheet/sheet.principles.stories.tsx +1 -1
- package/src/components/Sheet/sheet.spec.md +2 -2
- package/src/components/Sheet/sheet.tsx +9 -5
- package/src/components/Sidebar/sidebar.anatomy.stories.tsx +16 -12
- package/src/components/Sidebar/sidebar.principles.stories.tsx +10 -8
- package/src/components/Sidebar/sidebar.spec.md +13 -15
- package/src/components/Sidebar/sidebar.stories.tsx +8 -7
- package/src/components/Sidebar/sidebar.tsx +37 -25
- package/src/components/Skeleton/skeleton.stories.tsx +4 -11
- package/src/components/Slider/slider.anatomy.stories.tsx +3 -3
- package/src/components/Slider/slider.principles.stories.tsx +2 -2
- package/src/components/Slider/slider.spec.md +5 -5
- package/src/components/Slider/slider.tsx +3 -1
- package/src/components/Steps/steps.anatomy.stories.tsx +4 -4
- package/src/components/Steps/steps.principles.stories.tsx +1 -1
- package/src/components/Steps/steps.spec.md +1 -1
- package/src/components/Switch/switch.anatomy.stories.tsx +7 -7
- package/src/components/Switch/switch.principles.stories.tsx +4 -4
- package/src/components/Switch/switch.spec.md +8 -8
- package/src/components/Switch/switch.stories.tsx +9 -24
- package/src/components/Switch/switch.tsx +17 -13
- package/src/components/Tabs/tabs.anatomy.stories.tsx +10 -7
- package/src/components/Tabs/tabs.spec.md +1 -1
- package/src/components/Tabs/tabs.tsx +21 -1
- package/src/components/Textarea/textarea.anatomy.stories.tsx +1 -1
- package/src/components/Textarea/textarea.principles.stories.tsx +1 -1
- package/src/components/Textarea/textarea.spec.md +4 -4
- package/src/components/Textarea/textarea.tsx +72 -46
- package/src/components/TimePicker/time-columns.tsx +6 -2
- package/src/components/TimePicker/time-picker.principles.stories.tsx +1 -1
- package/src/components/TimePicker/time-picker.spec.md +3 -3
- package/src/components/TimePicker/time-picker.tsx +16 -10
- package/src/components/Toast/toast.stories.tsx +7 -4
- package/src/components/Tooltip/tooltip.anatomy.stories.tsx +4 -4
- package/src/components/Tooltip/tooltip.principles.stories.tsx +3 -3
- package/src/components/Tooltip/tooltip.spec.md +1 -1
- package/src/components/Tooltip/tooltip.stories.tsx +4 -39
- package/src/components/Tooltip/tooltip.tsx +8 -6
- package/src/components/TreeView/tree-view.anatomy.stories.tsx +6 -3
- package/src/components/TreeView/tree-view.spec.md +42 -11
- package/src/components/TreeView/tree-view.stories.tsx +1 -0
- package/src/components/TreeView/tree-view.tsx +322 -17
- package/src/index.ts +584 -60
- package/src/patterns/action-bar/action-bar.spec.md +9 -0
- package/src/patterns/action-bar/action-bar.stories.tsx +6 -3
- package/src/patterns/element-anatomy/inline-action.spec.md +2 -0
- package/src/patterns/element-anatomy/item-anatomy.spec.md +14 -5
- package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -4
- package/src/patterns/element-anatomy/item-anatomy.tsx +7 -6
- package/src/patterns/header-canonical/header-canonical.spec.md +5 -4
- package/src/patterns/overlay-surface/overlay-surface.spec.md +22 -1
- package/src/styles/tokens.css +3 -0
- package/src/tokens/README.md +1 -1
- package/src/tokens/color/color.spec.md +3 -3
- package/src/tokens/color/color.stories.tsx +3 -3
- package/src/tokens/density/density.stories.tsx +16 -3
- package/src/tokens/layoutSpace/layoutSpace.spec.md +3 -1
- package/src/tokens/motion/motion.css +33 -21
- package/src/tokens/motion/motion.spec.md +32 -15
- package/src/tokens/motion/motion.stories.tsx +58 -5
- package/src/tokens/motion/motion.ts +7 -6
- package/src/tokens/motion/overlay-motion.ts +26 -0
- package/src/tokens/orphan-tokens.spec.md +4 -4
- package/src/tokens/token-system.spec.md +1 -0
- package/src/tokens/uiSize/uiSize.spec.md +1 -1
- package/src/tokens/uiSize/uiSize.stories.tsx +4 -2
- package/src/tokens/utility-registry.json +160 -23
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @benchmark-unverified-blanket: file-level retraction per M22 (d) — claims herein not individually URL-cited; treat as unverified visual/usage rumor unless retrofit per-claim. Hook escape preserved.
|
|
2
2
|
import { useState } from 'react'
|
|
3
3
|
import type { Meta } from '@storybook/react'
|
|
4
|
+
import { ChevronUp, ChevronDown, MoreVertical } from 'lucide-react'
|
|
4
5
|
import {
|
|
5
6
|
Dialog, DialogTrigger, DialogContent, DialogHeader, DialogBody, DialogFooter, DialogTitle, DialogClose,
|
|
6
7
|
} from './dialog'
|
|
@@ -47,7 +48,7 @@ function NotificationSettings() {
|
|
|
47
48
|
<DialogHeader>
|
|
48
49
|
<DialogTitle>通知設定</DialogTitle>
|
|
49
50
|
</DialogHeader>
|
|
50
|
-
<DialogBody className="!px-0 !pt-0 !pb-0">
|
|
51
|
+
<DialogBody className="!px-0 !pt-0 !pb-0">{/* @tabs-content-gap-ok: list-as-region canonical(body 撤 chrome padding、list wrapper py-2 own;非 tabs !pt-0 hack)*/}
|
|
51
52
|
<div className="flex flex-col py-2">
|
|
52
53
|
{items.map((n) => (
|
|
53
54
|
// item-anatomy Family 2:[content: title + desc(--item-gap-label-desc-scanning gap)] [ItemSuffix: Switch]
|
|
@@ -239,7 +240,7 @@ export const LongContent = {
|
|
|
239
240
|
{/* Body 放 list canonical(2026-05-01):body 撤 chrome padding(`!px-0 !pt-0 !pb-0`)+ list outer
|
|
240
241
|
wrapper 自帶 `py-2`(menu group 8px breathing)+ item 自帶 `px-loose rounded-md`
|
|
241
242
|
(hover bg flush 到 chrome 邊)。30 筆超出 viewport → 驗證預設高度(填滿)+ body 區捲動。 */}
|
|
242
|
-
<DialogBody className="!px-0 !pt-0 !pb-0">
|
|
243
|
+
<DialogBody className="!px-0 !pt-0 !pb-0">{/* @tabs-content-gap-ok: list-as-region canonical(body 撤 chrome padding、list wrapper py-2 own;非 tabs !pt-0 hack)*/}
|
|
243
244
|
<div role="list" className="flex flex-col py-2">
|
|
244
245
|
{MEMBERS.map((m, i) => (
|
|
245
246
|
<MemberRow key={m.empNum} member={m} index={i} />
|
|
@@ -284,7 +285,7 @@ export const Destructive = {
|
|
|
284
285
|
/**
|
|
285
286
|
* ListBody — body 放 list 的 canonical pattern(Material / Polaris / Atlassian / Linear /
|
|
286
287
|
* GitHub Primer 共識:overlay body 裝 list 時 body 不加 vertical padding,節奏源 = item 自己的 py)。
|
|
287
|
-
* 我方 canonical(2026-05-01):`<DialogBody className="!px-0 !pt-0 !pb-0">` + list wrapper `py-2`
|
|
288
|
+
* 我方 canonical(2026-05-01):`<DialogBody className="!px-0 !pt-0 !pb-0">`(@tabs-content-gap-ok: list-as-region 文件範例,非 tabs !pt-0 hack)+ list wrapper `py-2`
|
|
288
289
|
* + item 自帶 `px-loose rounded-md`。不加 `flush` variant — 加 1 row(search / banner)就破功,
|
|
289
290
|
* 保留 chrome padding 較穩。以下三個範例對應不同 list-item tier(item-anatomy Family 2 / MenuItem)。
|
|
290
291
|
*/
|
|
@@ -301,7 +302,7 @@ export const ListBody = {
|
|
|
301
302
|
<DialogHeader>
|
|
302
303
|
<DialogTitle>成員列表</DialogTitle>
|
|
303
304
|
</DialogHeader>
|
|
304
|
-
<DialogBody className="!px-0 !pt-0 !pb-0">
|
|
305
|
+
<DialogBody className="!px-0 !pt-0 !pb-0">{/* @tabs-content-gap-ok: list-as-region canonical(body 撤 chrome padding、list wrapper py-2 own;非 tabs !pt-0 hack)*/}
|
|
305
306
|
<div role="list" className="flex flex-col py-2">
|
|
306
307
|
{MEMBERS.slice(0, 6).map((m, i) => (
|
|
307
308
|
<MemberRow key={m.empNum} member={m} index={i} />
|
|
@@ -330,7 +331,7 @@ export const ListBody = {
|
|
|
330
331
|
<DialogHeader>
|
|
331
332
|
<DialogTitle>選擇標籤</DialogTitle>
|
|
332
333
|
</DialogHeader>
|
|
333
|
-
<DialogBody className="!px-0 !pt-0 !pb-0">
|
|
334
|
+
<DialogBody className="!px-0 !pt-0 !pb-0">{/* @tabs-content-gap-ok: list-as-region canonical(body 撤 chrome padding、list wrapper py-2 own;非 tabs !pt-0 hack)*/}
|
|
334
335
|
<div role="list" className="flex flex-col py-2">
|
|
335
336
|
{['Bug', 'Feature', 'Improvement', 'Research', 'Documentation', 'Refactor', 'Test'].map((t) => (
|
|
336
337
|
// 小 item 純文字 label → 用 **MenuItem** primitive(世界級 Linear Cmd+K / Polaris OptionList
|
|
@@ -355,6 +356,66 @@ export const ListBody = {
|
|
|
355
356
|
),
|
|
356
357
|
}
|
|
357
358
|
|
|
359
|
+
/**
|
|
360
|
+
* 標頭操作(actions slot,2026-07-08 WM 戰役 codify — 關閉鈕分隔線 SSOT 化)
|
|
361
|
+
*
|
|
362
|
+
* 真實場景:任務詳情 modal(Jira / Linear / Asana 任務檢視)— header 級 prev / next 導覽
|
|
363
|
+
* + ⋮ 溢出選單,操作對象是「dialog 承載的這筆任務」本身(非欄位級、非 confirm/cancel)。
|
|
364
|
+
*
|
|
365
|
+
* - `<DialogHeader actions={…}>`:DS 自動在 actions 與內建 Close X 之間放 `<ButtonDivider>`
|
|
366
|
+
* (action-bar.spec.md:281「最右側為關閉/解除按鈕 → 分隔線必須(誤觸保護)」;
|
|
367
|
+
* 幾何 = mx-1 於 gap-2 cluster → 12px 對稱)。**Consumer 禁自刻 cluster + divider**。
|
|
368
|
+
* - 按鈕 = `variant="text" iconOnly`(text 自動 data-unbounded,不撐高 48px chrome header;
|
|
369
|
+
* 對齊 action-bar「溢出按鈕一律最低視覺重量」)。
|
|
370
|
+
*/
|
|
371
|
+
export const HeaderActions = {
|
|
372
|
+
name: '標頭操作',
|
|
373
|
+
render: () => (
|
|
374
|
+
<Dialog defaultOpen>
|
|
375
|
+
<DialogTrigger asChild>
|
|
376
|
+
<Button variant="tertiary">開啟任務詳情</Button>
|
|
377
|
+
</DialogTrigger>
|
|
378
|
+
<DialogContent autoHeight maxWidth={520}>
|
|
379
|
+
<DialogHeader
|
|
380
|
+
actions={
|
|
381
|
+
<>
|
|
382
|
+
<Button variant="text" iconOnly size="sm" startIcon={ChevronUp} aria-label="上一筆任務" />
|
|
383
|
+
<Button variant="text" iconOnly size="sm" startIcon={ChevronDown} aria-label="下一筆任務" />
|
|
384
|
+
<Button variant="text" iconOnly size="sm" startIcon={MoreVertical} aria-label="更多操作" />
|
|
385
|
+
</>
|
|
386
|
+
}
|
|
387
|
+
>
|
|
388
|
+
<DialogTitle>WM-142 結帳流程改版</DialogTitle>
|
|
389
|
+
</DialogHeader>
|
|
390
|
+
<DialogBody>
|
|
391
|
+
<div className="flex flex-col gap-[var(--layout-space-loose)]">
|
|
392
|
+
<p className="text-body">
|
|
393
|
+
重新設計結帳步驟,將付款方式與發票資訊合併為單一步驟,預期提升行動端轉換率。
|
|
394
|
+
</p>
|
|
395
|
+
<div className="flex flex-col gap-2">
|
|
396
|
+
{[
|
|
397
|
+
['指派人', 'Alan Chen'],
|
|
398
|
+
['狀態', '進行中'],
|
|
399
|
+
['截止日', '2026-07-18'],
|
|
400
|
+
].map(([label, value]) => (
|
|
401
|
+
<div key={label} className="flex items-center gap-3">
|
|
402
|
+
<span className="w-16 shrink-0 text-caption text-fg-secondary">{label}</span>
|
|
403
|
+
<span className="text-body">{value}</span>
|
|
404
|
+
</div>
|
|
405
|
+
))}
|
|
406
|
+
</div>
|
|
407
|
+
</div>
|
|
408
|
+
</DialogBody>
|
|
409
|
+
<DialogFooter>
|
|
410
|
+
<DialogClose asChild>
|
|
411
|
+
<Button variant="tertiary">關閉</Button>
|
|
412
|
+
</DialogClose>
|
|
413
|
+
</DialogFooter>
|
|
414
|
+
</DialogContent>
|
|
415
|
+
</Dialog>
|
|
416
|
+
),
|
|
417
|
+
}
|
|
418
|
+
|
|
358
419
|
/**
|
|
359
420
|
* 標頭內含分頁(2026-05-18 從 patterns/header-canonical/header-canonical.stories.tsx 整合過來
|
|
360
421
|
* per user「應該整合進去 dialog 吧?目前應該不需要獨立的 header canonical 資料夾來說明這些東西」)
|
|
@@ -5,8 +5,10 @@ import { X as XIcon } from "lucide-react"
|
|
|
5
5
|
|
|
6
6
|
import { cn } from "@/lib/utils"
|
|
7
7
|
import { Button } from "@/design-system/components/Button/button"
|
|
8
|
+
import { ButtonDivider } from "@/design-system/components/Button/button-group"
|
|
8
9
|
import { SurfaceHeader, SurfaceFooter, type SurfaceHeaderProps } from "@/design-system/patterns/overlay-surface/overlay-surface"
|
|
9
10
|
import { ScrollArea } from "@/design-system/components/ScrollArea/scroll-area"
|
|
11
|
+
import { surfaceMotion } from "@/design-system/tokens/motion/overlay-motion"
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* Dialog (Modal) — Radix Dialog + 設計系統 token
|
|
@@ -22,7 +24,7 @@ import { ScrollArea } from "@/design-system/components/ScrollArea/scroll-area"
|
|
|
22
24
|
*
|
|
23
25
|
* ── 高度行為 ──
|
|
24
26
|
* 預設:height 填滿 viewport(扣除 inset),body 捲動。防止動態內容跳動。
|
|
25
|
-
*
|
|
27
|
+
* autoHeight(boolean):高度隨內容,超過 viewport 時 max-height 安全帽。
|
|
26
28
|
*/
|
|
27
29
|
|
|
28
30
|
const Dialog = DialogPrimitive.Root
|
|
@@ -106,7 +108,8 @@ const DialogContent = React.forwardRef<
|
|
|
106
108
|
className={cn(
|
|
107
109
|
"fixed left-1/2 top-1/2 z-50 w-full -translate-x-1/2 -translate-y-1/2",
|
|
108
110
|
"flex flex-col bg-surface-raised rounded-lg border border-border",
|
|
109
|
-
|
|
111
|
+
surfaceMotion,
|
|
112
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
110
113
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
111
114
|
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
112
115
|
"data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]",
|
|
@@ -129,35 +132,67 @@ const DialogContent = React.forwardRef<
|
|
|
129
132
|
DialogContent.displayName = DialogPrimitive.Content.displayName
|
|
130
133
|
|
|
131
134
|
// DialogHeader: SurfaceHeader + Close 按鈕(Dialog 特有)
|
|
132
|
-
// justify-between
|
|
135
|
+
// Close 靠右由「第一 child flex-1 grow」達成(justify-between 已移除,見 return 註解);Close 用 Radix DialogPrimitive.Close 包裝。
|
|
133
136
|
// 2026-05-18 audit gap fix:type 用 SurfaceHeaderProps 對齊 — DialogHeader 是 SurfaceHeader
|
|
134
|
-
// 薄包裝,withTabs /
|
|
137
|
+
// 薄包裝,withTabs / tabsSlot props 透過 spread 已 forward,但 TS type 沒 expose
|
|
135
138
|
// 導致 consumer 不能用 `<DialogHeader withTabs>` 而只能寫 `as any` 繞。Type lift 修
|
|
136
139
|
// per header-canonical.spec.md W1 跨 6 consumer 同契約。
|
|
140
|
+
export interface DialogHeaderProps extends SurfaceHeaderProps {
|
|
141
|
+
/**
|
|
142
|
+
* Header 級操作 cluster(2026-07-08 WM 戰役 codify — 關閉鈕分隔線 SSOT 化)。
|
|
143
|
+
*
|
|
144
|
+
* 提供時 render 在 Close X 左側,DS 自動在 actions 與 Close 之間放 `<ButtonDivider>`
|
|
145
|
+
* (action-bar.spec.md:281「最右側為關閉/解除按鈕 → 分隔線必須(誤觸保護)」;
|
|
146
|
+
* 幾何 = ButtonDivider mx-1 於 gap-2 cluster → 12px 對稱,同 spec「分隔線幾何」段)。
|
|
147
|
+
*
|
|
148
|
+
* 用例:任務詳情 prev/next 導覽、header 級溢出選單(⋮)。
|
|
149
|
+
* Consumer 傳 `<Button variant="text" iconOnly …>`(text variant 自動 data-unbounded,
|
|
150
|
+
* 不撐高 chrome header)。**禁**在 children 內自刻 cluster + divider(分隔線落點歸 DS)。
|
|
151
|
+
*/
|
|
152
|
+
actions?: React.ReactNode
|
|
153
|
+
}
|
|
154
|
+
|
|
137
155
|
const DialogHeader = React.forwardRef<
|
|
138
156
|
HTMLDivElement,
|
|
139
|
-
|
|
140
|
-
>(({ className, children, ...props }, ref) =>
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
className={className}
|
|
148
|
-
{...props}
|
|
149
|
-
>
|
|
150
|
-
<div className="flex-1 min-w-0">{children}</div>
|
|
151
|
-
{/* Dismiss X(chrome-slot canonical,v5):Button 本身 native sm(28 md / 32 lg,touch target 亦同),
|
|
152
|
-
但 `dismiss` prop 自動標 `data-unbounded`,SurfaceHeader CSS rule 對其套負 my 讓
|
|
153
|
-
layout 佔位 = 24(`data-dismiss` 僅作 openAutoFocus 排除 marker,與縮位無關),
|
|
154
|
-
header = 24 + 2×tight = 48 / 56 chrome-header-height ✓。
|
|
155
|
-
詳 overlay-surface.spec.md「Chrome dismiss size canonical」*/}
|
|
157
|
+
DialogHeaderProps
|
|
158
|
+
>(({ className, children, actions, ...props }, ref) => {
|
|
159
|
+
// Dismiss X(chrome-slot canonical,v5):Button 本身 native sm(28 md / 32 lg,touch target 亦同),
|
|
160
|
+
// 但 `dismiss` prop 自動標 `data-unbounded`,SurfaceHeader CSS rule 對其套負 my 讓
|
|
161
|
+
// layout 佔位 = 24(`data-dismiss` 僅作 openAutoFocus 排除 marker,與縮位無關),
|
|
162
|
+
// header = 24 + 2×tight = 48 / 56 chrome-header-height ✓。
|
|
163
|
+
// 詳 overlay-surface.spec.md「Chrome dismiss size canonical」
|
|
164
|
+
const closeButton = (
|
|
156
165
|
<DialogPrimitive.Close asChild>
|
|
157
166
|
<Button data-dismiss iconOnly dismiss size="sm" startIcon={XIcon} aria-label="關閉" />
|
|
158
167
|
</DialogPrimitive.Close>
|
|
159
|
-
|
|
160
|
-
|
|
168
|
+
)
|
|
169
|
+
return (
|
|
170
|
+
// 2026-05-18:className 不再硬加 justify-between(冗餘:row 1 是 flex items-center gap-2,
|
|
171
|
+
// 第一 child flex-1 grow 自然 push close X 靠右,跟 justify-between 同視覺)。
|
|
172
|
+
// 並且 column mode(tabsSlot 提供)justify-between 會把 row 1 / row 2 上下推開 = 破裂。
|
|
173
|
+
// tabsSlot via `...props` spread 自動 forward(type 來自 SurfaceHeaderProps)。
|
|
174
|
+
<SurfaceHeader
|
|
175
|
+
ref={ref}
|
|
176
|
+
className={className}
|
|
177
|
+
{...props}
|
|
178
|
+
>
|
|
179
|
+
<div className="flex-1 min-w-0">{children}</div>
|
|
180
|
+
{actions != null ? (
|
|
181
|
+
// actions 提供 → 右側一體 cluster:{actions} + ButtonDivider + Close。
|
|
182
|
+
// 分隔線 = 關閉保護 canonical(action-bar.spec.md:281),由 DS 放,consumer 零自刻。
|
|
183
|
+
// gap-2 + ButtonDivider mx-1 = 兩側 12px 對稱(action-bar.spec.md「分隔線幾何」)。
|
|
184
|
+
<div className="flex items-center gap-2 shrink-0">
|
|
185
|
+
{actions}
|
|
186
|
+
<ButtonDivider />
|
|
187
|
+
{closeButton}
|
|
188
|
+
</div>
|
|
189
|
+
) : (
|
|
190
|
+
// 無 actions → 原結構(Close 直接是 SurfaceHeader child),行為零回歸
|
|
191
|
+
closeButton
|
|
192
|
+
)}
|
|
193
|
+
</SurfaceHeader>
|
|
194
|
+
)
|
|
195
|
+
})
|
|
161
196
|
DialogHeader.displayName = "DialogHeader"
|
|
162
197
|
|
|
163
198
|
// DialogBody: flex-1 ScrollArea + chrome padding(對齊 overlay-surface SSOT + ScrollArea canonical)
|
|
@@ -169,7 +204,7 @@ DialogHeader.displayName = "DialogHeader"
|
|
|
169
204
|
// 不再提供 `flush` variant(2026-05-01 移除,先前曾叫 `variant="list"`)。
|
|
170
205
|
// **canonical pattern** = consumer 自管 list outer wrapper + 用 `className` override 撤掉 chrome padding:
|
|
171
206
|
// ```tsx
|
|
172
|
-
// <DialogBody className="!px-0 !pt-0 !pb-0">
|
|
207
|
+
// <DialogBody className="!px-0 !pt-0 !pb-0"> ← @tabs-content-gap-ok: JSDoc 文件範例(list-as-region canonical,非 tabs !pt-0 hack)
|
|
173
208
|
// <div className="py-2"> {/* list outer wrapper 自帶 py-2(menu group canonical)*/}
|
|
174
209
|
// {items.map(item => <MenuItem className="px-[var(--layout-space-loose)] rounded-md" />)}
|
|
175
210
|
// </div>
|
|
@@ -187,7 +222,7 @@ const DialogBody = React.forwardRef<
|
|
|
187
222
|
HTMLDivElement,
|
|
188
223
|
React.ComponentPropsWithoutRef<typeof ScrollArea>
|
|
189
224
|
>(({ className, children, ...props }, ref) => (
|
|
190
|
-
<ScrollArea ref={ref} data-dialog-body className="flex-1 min-h-0" {...props}>
|
|
225
|
+
<ScrollArea fillX ref={ref} data-dialog-body className="flex-1 min-h-0" {...props}>
|
|
191
226
|
<div
|
|
192
227
|
className={cn(
|
|
193
228
|
"px-[var(--layout-space-loose)] pt-[var(--layout-space-tight)] pb-[var(--layout-space-bottom)]",
|
|
@@ -941,7 +941,7 @@ const StateBehaviorInner = () => {
|
|
|
941
941
|
<span className="text-caption font-medium text-fg-secondary">行為規則</span>
|
|
942
942
|
<ul className="text-caption text-fg-secondary space-y-1.5 ml-4 list-disc">
|
|
943
943
|
<li>`DropdownMenuItem` 點擊即 close——這是「action 觸發即完成」語意。</li>
|
|
944
|
-
<li>`DropdownMenuCheckboxItem` 點擊**不 close
|
|
944
|
+
<li>`DropdownMenuCheckboxItem` 點擊**不 close**——每次勾選即時生效(onCheckedChange 即時 fire),menu 保持開啟只為讓使用者連續多選。</li>
|
|
945
945
|
<li>`DropdownMenuSub` 永遠右側滑入,parent menu 保持展開——提供 breadcrumb 式認知流,使用者知道自己在哪層。</li>
|
|
946
946
|
<li>Escape close 整個選單(含所有展開子層;Radix root close)。ArrowLeft 才逐層收合(焦點回 SubTrigger)。</li>
|
|
947
947
|
<li>Portal render 到 body,`z-50` 確保不被 parent overflow 截斷。</li>
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
// @benchmark-unverified-blanket: file-level retraction per M22 (d) — claims herein not individually URL-cited; treat as unverified visual/usage rumor unless retrofit per-claim. Hook escape preserved.
|
|
2
|
+
// @story-trait-allow: missing-opensnapshot — 原則頁多個 inline dropdown demo 只為承載規則說明(rule note),
|
|
3
|
+
// forced defaultOpen 會讓 ~10 個浮層互疊;overlay open-state 快照由 dropdown-menu.anatomy.stories.tsx
|
|
4
|
+
// StateBehavior(defaultOpen)canonical 涵蓋(對齊 hover-card.principles.stories.tsx 同 rationale)。
|
|
2
5
|
import React from 'react'
|
|
3
6
|
import LinkTo from '@storybook/addon-links/react'
|
|
4
7
|
import type { Meta, StoryObj } from '@storybook/react'
|
|
@@ -17,7 +20,6 @@ import {
|
|
|
17
20
|
DropdownMenuSeparator,
|
|
18
21
|
DropdownMenuGroup,
|
|
19
22
|
DropdownMenuLabel,
|
|
20
|
-
DropdownMenuShortcut,
|
|
21
23
|
} from './dropdown-menu'
|
|
22
24
|
import { Button } from '@/design-system/components/Button/button'
|
|
23
25
|
|
|
@@ -313,17 +315,17 @@ export const SuffixRule: Story = {
|
|
|
313
315
|
render: () => (
|
|
314
316
|
<div>
|
|
315
317
|
<Rule
|
|
316
|
-
title="
|
|
317
|
-
note="使用者熟悉快捷鍵後可跳過選單直接按快捷鍵。shortcut 用 fg-muted 作為輔助資訊色,不搶 label
|
|
318
|
+
title="鍵盤快捷鍵 — canonical shortcut prop(靠右對齊列尾)"
|
|
319
|
+
note="使用者熟悉快捷鍵後可跳過選單直接按快捷鍵。shortcut 用 fg-muted 作為輔助資訊色,不搶 label 注意力。標準場景用 `shortcut` prop(走 MenuItem endContent flex slot,真正靠右對齊列尾);`<DropdownMenuShortcut>` child 僅為相容 shadcn 的 escape-hatch,會 inline 附加在 label 尾、不會靠右。"
|
|
318
320
|
>
|
|
319
321
|
<DropdownMenu>
|
|
320
322
|
<DropdownMenuTrigger asChild>
|
|
321
323
|
<Button variant="tertiary">檔案</Button>
|
|
322
324
|
</DropdownMenuTrigger>
|
|
323
325
|
<DropdownMenuContent>
|
|
324
|
-
<DropdownMenuItem
|
|
325
|
-
<DropdownMenuItem
|
|
326
|
-
<DropdownMenuItem
|
|
326
|
+
<DropdownMenuItem shortcut="⌘N">新增</DropdownMenuItem>
|
|
327
|
+
<DropdownMenuItem shortcut="⌘O">開啟</DropdownMenuItem>
|
|
328
|
+
<DropdownMenuItem shortcut="⌘S">儲存</DropdownMenuItem>
|
|
327
329
|
</DropdownMenuContent>
|
|
328
330
|
</DropdownMenu>
|
|
329
331
|
</Rule>
|
|
@@ -69,8 +69,8 @@ DropdownMenu ← Radix Root,管理開關狀態
|
|
|
69
69
|
|
|
70
70
|
**快捷鍵提示 API(兩條,擇一不混用)**:
|
|
71
71
|
- **Canonical:`<DropdownMenuItem shortcut="⌘C">`** prop —— 渲染進 MenuItem `endContent` 正規後綴 slot(跟 badge / endIcon 同槽,gap / 對齊一致)。**標準場景一律用 prop。**
|
|
72
|
-
- **Escape-hatch:`<DropdownMenuShortcut>` child** ——
|
|
73
|
-
-
|
|
72
|
+
- **Escape-hatch:`<DropdownMenuShortcut>` child** —— 保留以相容 shadcn DropdownMenuShortcut idiom(source:https://ui.shadcn.com/docs/components/dropdown-menu 的 `DropdownMenuShortcut` = `ml-auto` span,npm published API)。⚠️ 本 DS 的 MenuItem 把 children 塞進 ItemContent 的 label `<span>`(非 flex row),故 child 上的 `ml-auto` **不會靠右**——⌘N 只會 inline 附加在 label 文字尾端。要真正靠右對齊列尾的後綴,一律用上方 canonical `shortcut` prop。
|
|
73
|
+
- 兩者**字體樣式統一**(`text-caption` + `tracking-shortcut` + `fg-muted`,與 CommandShortcut 一致),但**位置不等價**(prop 靠右對齊列尾;child inline 附加在 label 尾);**同一 item 只用一種**(見「禁止事項」)。
|
|
74
74
|
- 為何不砍 child 只留 prop:`DropdownMenuShortcut` 是 npm published API(對齊 shadcn,fork repo 可能用),硬砍 = breaking;故保留為 escape-hatch,prop 為 canonical preferred。
|
|
75
75
|
|
|
76
76
|
### DropdownMenuGroup 的自動分隔
|
|
@@ -90,7 +90,7 @@ DropdownMenu ← Radix Root,管理開關狀態
|
|
|
90
90
|
| 邊界 padding 來源 | 每個 Group 自己的 py-2(Command.List 無 py) | Content 的 py-2(Group 不套 py-2 避免 double) |
|
|
91
91
|
| Group 間 gap | 8 + 8 = 16 + border | 0 + 8 + 8 = 16 + border |
|
|
92
92
|
|
|
93
|
-
**為什麼不直接套 `py-2`**:`DropdownMenuContent` 已有 `py-2` 提供 Content 邊界 padding
|
|
93
|
+
**為什麼不直接套 `py-2`**:`DropdownMenuContent` 已有 `py-2` 提供 Content 邊界 padding(純視覺呼吸空間;Radix roving focus 依 collection refs + `element.focus()`,不讀 CSS padding,移除 py-2 不影響鍵盤導覽 / focus offset)。若 Group 再套 `py-2` 會 double padding。改用 `mt-2 pt-2` 只加在第二個 Group 起,視覺等價但不 double。
|
|
94
94
|
|
|
95
95
|
兩種分隔機制的選擇:
|
|
96
96
|
- **用 `DropdownMenuGroup` 包裝同類 items** → 自動分隔(零手動,跟 MenuGroup 理念一致)
|
|
@@ -123,7 +123,7 @@ CheckboxItem 和 RadioItem 雖然涉及「選擇」,但它們控制的是**即
|
|
|
123
123
|
|
|
124
124
|
- prefix:由 `DropdownMenuItem` 的 `startIcon` prop 傳入,經 MenuItem 內部的 prefix 對齊容器(消費 item-anatomy 的 `itemPrefixAlignVariants`,`h-[1lh]` 對齊第一行 label)渲染。icon 跟 label 同色(foreground)
|
|
125
125
|
- label:文字內容,`flex-1`
|
|
126
|
-
- suffix:canonical 走 item prop(`shortcut` / `badge` / `endIcon` → MenuItem `endContent` 正規 slot
|
|
126
|
+
- suffix:canonical 走 item prop(`shortcut` / `badge` / `endIcon` → MenuItem `endContent` 正規 slot,真正靠右對齊列尾);`DropdownMenuShortcut` child 僅相容用 escape-hatch(inline 附加在 label 尾、**不靠右**,見「快捷鍵提示 API」段)。指示型 icon 用 `fg-muted`
|
|
127
127
|
|
|
128
128
|
padding 公式:`py = (field-height - 1lh) / 2`,單行時總高度等於同 size 的 Button / Input。
|
|
129
129
|
|
|
@@ -209,7 +209,7 @@ DropdownMenu 是掃描模式——使用者快速瀏覽選項,所有尺寸使
|
|
|
209
209
|
|
|
210
210
|
## StateBehavior(DropdownMenu 層級特有)
|
|
211
211
|
|
|
212
|
-
Item-level default / hover / focused / selected / disabled **色彩**由 MenuItem primitive SSOT 擁有(`patterns/element-anatomy/item-anatomy.spec.md`「選擇 / 狀態視覺規則」),在本元件 `ColorMatrix` story 承載並直接引用 MenuItem token。**selected × highlighted 疊加(2026-07-04 Q2 拍板)**:selected bg 勝 Radix `data-[highlighted]`(hover + keyboard cursor)— 對齊 MenuItem「selected 勝 hover」canonical(menu-item.spec.md 狀態表),`selected && 'data-[highlighted]:bg-neutral-selected'` override
|
|
212
|
+
Item-level default / hover / focused / selected / disabled **色彩**由 MenuItem primitive SSOT 擁有(`patterns/element-anatomy/item-anatomy.spec.md`「選擇 / 狀態視覺規則」),在本元件 `ColorMatrix` story 承載並直接引用 MenuItem token。**selected × highlighted 疊加(2026-07-04 Q2 拍板)**:selected bg 勝 Radix `data-[highlighted]`(hover + keyboard cursor)— 對齊 MenuItem「selected 勝 hover」canonical(menu-item.spec.md 狀態表),`selected && 'bg-neutral-selected data-[highlighted]:bg-neutral-selected-active'` override(selected×highlighted 加深一階 `bg-neutral-selected-active`);**僅 RadioItem checked 走此 selected-bg 規則**(checked 底色套外層 Radix RadioItem)。CheckboxItem checked **不套 row bg**——checked 由內層 checkbox 控件表達,highlighted 時仍為 neutral-hover。DropdownMenu 的 `StateBehavior` story 展示**浮層層級特有的動態行為**:open / close 動畫(Radix `data-state` 驅動)、Submenu 展開 / 收起、CheckboxItem toggle(多選不 close)——這些是 item primitive 沒有的維度。
|
|
213
213
|
|
|
214
214
|
---
|
|
215
215
|
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
ICON_SIZE as ROW_ICON_SIZE,
|
|
14
14
|
type RowSize,
|
|
15
15
|
} from "@/design-system/patterns/element-anatomy/item-anatomy"
|
|
16
|
+
import { overlayMotion } from "@/design-system/tokens/motion/overlay-motion"
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* DropdownMenu — Radix DropdownMenu + MenuItem visual layer
|
|
@@ -41,7 +42,8 @@ import {
|
|
|
41
42
|
// ── Floating layer 共用樣式 ──
|
|
42
43
|
const floatingLayerClass = [
|
|
43
44
|
'z-50 overflow-hidden rounded-lg border border-border bg-surface-raised',
|
|
44
|
-
|
|
45
|
+
overlayMotion,
|
|
46
|
+
'data-[state=open]:animate-in data-[state=closed]:animate-out',
|
|
45
47
|
'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
|
|
46
48
|
'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',
|
|
47
49
|
'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2',
|
|
@@ -97,8 +99,10 @@ DropdownMenuTrigger.displayName = DropdownMenuPrimitive.Trigger.displayName
|
|
|
97
99
|
// 的 8px,只需在第二個起的 group 加 8+8 = 16px gap + border)
|
|
98
100
|
//
|
|
99
101
|
// **視覺結果等同**:兩種實作的 visual output 一致,只是「padding 住在哪層」
|
|
100
|
-
// 不同。不強制統一 CSS 表達式——DropdownMenuContent 的 py-2
|
|
101
|
-
//
|
|
102
|
+
// 不同。不強制統一 CSS 表達式——DropdownMenuContent 的 py-2 是純視覺 Content
|
|
103
|
+
// 邊界 padding(Radix roving focus 依 collection refs + element.focus(),不讀
|
|
104
|
+
// CSS padding;對齊 spec.md「為什麼不直接套 py-2」段)。Group 若再套 py-2 會
|
|
105
|
+
// double padding,故 Group 用 mt-2/pt-2 只加在第二個起。
|
|
102
106
|
const DropdownMenuGroup = React.forwardRef<
|
|
103
107
|
React.ElementRef<typeof DropdownMenuPrimitive.Group>,
|
|
104
108
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Group>
|
|
@@ -423,7 +427,8 @@ const DropdownMenuSeparator = React.forwardRef<
|
|
|
423
427
|
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
|
|
424
428
|
|
|
425
429
|
// ── RadioItem(單選,排序方式等)──
|
|
426
|
-
// Radix handles checked state;
|
|
430
|
+
// Radix handles checked state;checked 底色套在外層 Radix RadioItem 本身(parent-bg
|
|
431
|
+
// pattern,詳下方 2026-05-31 #10 註解),內層 MenuItem 恆 !bg-transparent 讓它透出。
|
|
427
432
|
interface DropdownMenuRadioItemProps
|
|
428
433
|
extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem> {
|
|
429
434
|
/** Prefix icon(LucideIcon) */
|
|
@@ -467,12 +472,16 @@ const DropdownMenuRadioItem = React.forwardRef<
|
|
|
467
472
|
})
|
|
468
473
|
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
|
|
469
474
|
|
|
470
|
-
// ── Shortcut
|
|
475
|
+
// ── Shortcut(鍵盤快捷鍵提示 child;escape-hatch,不靠右)──
|
|
471
476
|
// **Canonical 是 `<DropdownMenuItem shortcut="⌘C">`** prop —— 走 MenuItem `endContent` 正規後綴 slot
|
|
472
|
-
// (跟 badge / endIcon 同槽、gap
|
|
473
|
-
// DropdownMenuShortcut idiom
|
|
474
|
-
//
|
|
475
|
-
//
|
|
477
|
+
// (跟 badge / endIcon 同槽、gap/對齊一致,真正靠右對齊列尾)。本 child 是 **composition
|
|
478
|
+
// escape-hatch**(相容 shadcn DropdownMenuShortcut idiom = `ml-auto` span,source:
|
|
479
|
+
// https://ui.shadcn.com/docs/components/dropdown-menu;npm published API 不砍)。⚠️ 在
|
|
480
|
+
// DropdownMenuItem 內 children 會進 MenuItem ItemContent 的 label `<span>`(inline context,
|
|
481
|
+
// 非 flex row),故 `ml-auto` **不生效、不會靠右**——只會 inline 附加在 label 文字尾;`ml-auto`
|
|
482
|
+
// 僅在 consumer 自組 flex row 時生效。要靠右一律用 canonical `shortcut` prop。**同一 item
|
|
483
|
+
// 只用一種,勿混用**(見 spec.md「快捷鍵提示 API」+ 禁止事項)。
|
|
484
|
+
// 字體樣式統一:text-caption + tracking-shortcut + fg-muted(對齊 prop 後綴 + CommandShortcut);位置不等價。
|
|
476
485
|
const DropdownMenuShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => (
|
|
477
486
|
<span
|
|
478
487
|
className={cn('ml-auto text-caption text-fg-muted tracking-shortcut', className)}
|
|
@@ -146,7 +146,7 @@ export const ScenarioMatrix: Story = {
|
|
|
146
146
|
<div>
|
|
147
147
|
<H3>Table 空資料</H3>
|
|
148
148
|
<div className="border border-border rounded-lg p-8">
|
|
149
|
-
<Empty description="
|
|
149
|
+
<Empty description="還沒有訂單" className="py-12" />
|
|
150
150
|
</div>
|
|
151
151
|
</div>
|
|
152
152
|
|
|
@@ -132,8 +132,8 @@ Empty 是 **non-interactive layout primitive**——本身無 ARIA role(讓 cons
|
|
|
132
132
|
## 消費範例
|
|
133
133
|
|
|
134
134
|
```tsx
|
|
135
|
-
// Table 空狀態(最簡)
|
|
136
|
-
<Empty description="
|
|
135
|
+
// Table 空狀態(最簡)——文案仍點出「缺什麼資料」,避免抽象的「無資料」(見「禁止事項」)
|
|
136
|
+
<Empty description="還沒有訂單" />
|
|
137
137
|
|
|
138
138
|
// SelectMenu 無結果
|
|
139
139
|
<Empty icon={SearchX} description="找不到符合的結果" />
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
import type { FieldMode, FieldVariant } from './field-types'
|
|
2
|
+
import type { FieldMode, FieldVariant, FieldVariantInternal, FieldWidth } from './field-types'
|
|
3
|
+
import { EMPTY_DISPLAY } from './field-wrapper'
|
|
3
4
|
|
|
4
5
|
// ── Types ──
|
|
5
|
-
export type { FieldMode, FieldVariant }
|
|
6
|
+
export type { FieldMode, FieldVariant, FieldVariantInternal, FieldWidth }
|
|
6
7
|
export type FieldOrientation = 'vertical' | 'horizontal'
|
|
7
8
|
export type FieldSize = 'sm' | 'md' | 'lg'
|
|
8
9
|
export type FieldControlLayout = 'inline' | 'block'
|
|
@@ -29,7 +30,8 @@ export interface FieldContextValue {
|
|
|
29
30
|
descriptionId: string
|
|
30
31
|
errorId: string
|
|
31
32
|
mode: FieldMode
|
|
32
|
-
/** 視覺外殼透傳(2026-05-05)。default = 含 border+bg;
|
|
33
|
+
/** 視覺外殼透傳(2026-05-05)。default = 含 border+bg;naked = cell-as-input(edit×naked 自畫 border-based state machine;display/readonly/disabled×naked 用 transparent border 由 host cell 供邊框);`bare` 2026-07-09 退役;naked 2026-07-14 型別收窄至
|
|
34
|
+
* FieldVariantInternal(@internal)— 公開 `<Field variant>` 只收 default,故本欄位維持 FieldVariant。
|
|
33
35
|
* child Field control 自動繼承,per-control prop override 可覆寫。詳 field-types.ts。 */
|
|
34
36
|
variant: FieldVariant
|
|
35
37
|
disabled: boolean
|
|
@@ -202,10 +204,12 @@ export function useResolvedFieldMode({
|
|
|
202
204
|
}
|
|
203
205
|
|
|
204
206
|
/**
|
|
205
|
-
* Resolve Field control 的 **variant**(default / bare
|
|
207
|
+
* Resolve Field control 的 **variant**(default / naked 視覺外殼;`bare` 2026-07-09 退役)— 2026-06-08 SSOT。
|
|
206
208
|
* 優先序:顯式 prop > FieldContext.variant > 'default'。與既有各控件公式一字不差(Δ=0),統一以利 gate 強制。
|
|
209
|
+
* 2026-07-14 API 策展 E:入參 / 回傳 widen 為 FieldVariantInternal — naked 僅 DataTable cell-registry
|
|
210
|
+
* 經 @internal 通道傳入(公開 prop 型別 = FieldVariant,不含 naked)。
|
|
207
211
|
*/
|
|
208
|
-
export function useResolvedFieldVariant(variantProp?:
|
|
212
|
+
export function useResolvedFieldVariant(variantProp?: FieldVariantInternal | null): FieldVariantInternal {
|
|
209
213
|
const fieldCtx = React.useContext(FieldContext)
|
|
210
214
|
return variantProp ?? fieldCtx?.variant ?? 'default'
|
|
211
215
|
}
|
|
@@ -232,3 +236,63 @@ export function FieldSurfaceSizeProvider({
|
|
|
232
236
|
}): React.ReactElement {
|
|
233
237
|
return React.createElement(FieldSurfaceSizeContext.Provider, { value: size }, children)
|
|
234
238
|
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Table-cell 可編輯訊號(2026-07-08 user 拍板)— 獨立於 FieldSurfaceContext / FieldSurfaceSizeContext
|
|
242
|
+
* 的純 boolean context,由 host(DataTable cell registry)注入該 cell 是否可編輯,讓 useFieldEmptyDisplay
|
|
243
|
+
* 分流「可編輯 cell 空 display → 空白」vs「不可編輯 cell 空 display → '-'」。
|
|
244
|
+
* value = boolean primitive(stable when unchanged),不破壞 cell memo identity(同 TableScrollContext /
|
|
245
|
+
* FieldSurfaceSizeContext L119-121 canonical);絕不污染 FieldContext(useFieldContext() 在 cell 內仍 null)。
|
|
246
|
+
*/
|
|
247
|
+
const FieldSurfaceEditableContext = React.createContext<boolean>(false)
|
|
248
|
+
|
|
249
|
+
export function FieldSurfaceEditableProvider({
|
|
250
|
+
isEditable,
|
|
251
|
+
children,
|
|
252
|
+
}: {
|
|
253
|
+
isEditable: boolean
|
|
254
|
+
children: React.ReactNode
|
|
255
|
+
}): React.ReactElement {
|
|
256
|
+
return React.createElement(FieldSurfaceEditableContext.Provider, { value: isEditable }, children)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* 空值顯示分流(2026-07-08 user 拍板,verbatim「...都用"-"...我從頭到尾哪裡有說要用全形的」):
|
|
261
|
+
*
|
|
262
|
+
* | 情境 | 空值顯示 |
|
|
263
|
+
* |------------------------------------------------|----------|
|
|
264
|
+
* | table-cell **可編輯** 的 display 靜止態 | **空白 `''`**(不佔位,affordance = hover outline)|
|
|
265
|
+
* | table-cell **不可編輯**(readonly cell) | **半形 `-`** |
|
|
266
|
+
* | standalone display / readonly / form / toolbar | **半形 `-`** |
|
|
267
|
+
*
|
|
268
|
+
* 收斂式:`surface==='table-cell' && isEditable ? '' : EMPTY_DISPLAY`。
|
|
269
|
+
* 可編輯 form / edit 輸入框走 native placeholder(不經此 hook)。boolean → unchecked / disabled →
|
|
270
|
+
* 同上文字 + text-fg-disabled(M24),各控件自理。
|
|
271
|
+
* 世界級對照:table-cell blank = MUI X / AG Grid / Ant core / Notion / Airtable grid 域共識;
|
|
272
|
+
* 非 table `-` = Ant ProTable `columnEmptyText`(見 field-wrapper.tsx EMPTY_DISPLAY 註)。
|
|
273
|
+
* SSOT 條文 → field-controls.spec.md「null / undefined 值」;全 Field family display/readonly/disabled
|
|
274
|
+
* 空值渲染必經此 hook,禁直接引 EMPTY_DISPLAY 常數(genre 分流會漏)。
|
|
275
|
+
*/
|
|
276
|
+
export function useFieldEmptyDisplay(): string {
|
|
277
|
+
const surface = useFieldSurface()
|
|
278
|
+
const isEditable = React.useContext(FieldSurfaceEditableContext)
|
|
279
|
+
return surface === 'table-cell' && isEditable ? '' : EMPTY_DISPLAY
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* 空值符號「-」顏色分流(2026-07-09 user 拍板 verbatim「「-」代表的是不可編輯只拿來供檢視的值
|
|
284
|
+
* 所以應該跟readonly 的value同樣顏色吧」):
|
|
285
|
+
*
|
|
286
|
+
* 「-」是「不可編輯、供檢視的值」→ 同 readonly value 色 = `text-foreground`
|
|
287
|
+
* (field-wrapper.tsx base `text-foreground`),**非** `text-fg-muted`(muted 是「可編輯 placeholder
|
|
288
|
+
* 提示」的裝飾語意;空值符號不是提示、是被檢視的值狀態)。
|
|
289
|
+
* disabled 態維持 `text-fg-disabled`(M24 disabled 顯著性 > foreground/muted,不可被蓋)。
|
|
290
|
+
*
|
|
291
|
+
* SSOT:全 Field family display/readonly/disabled 空值 span 消費此 helper,傳入已 resolve 的
|
|
292
|
+
* resolvedMode。純函式(非 hook)—— resolvedMode 已由 useResolvedFieldMode 解析(含控件自身
|
|
293
|
+
* disabled prop,context hook 讀不到);故以 resolvedMode 為入參,可條件呼叫、不受 Rules of Hooks 限制。
|
|
294
|
+
* 世界級對照:Ant read-only / Carbon read-only value = 正常前景色;placeholder 才 muted。
|
|
295
|
+
*/
|
|
296
|
+
export function fieldEmptyColorClass(resolvedMode: FieldMode): string {
|
|
297
|
+
return resolvedMode === 'disabled' ? 'text-fg-disabled' : 'text-foreground'
|
|
298
|
+
}
|