@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
|
@@ -6,7 +6,7 @@ import * as React from 'react'
|
|
|
6
6
|
import { cn } from '@/lib/utils'
|
|
7
7
|
import { HoverCard, HoverCardTrigger, HoverCardContent } from '@/design-system/components/HoverCard/hover-card'
|
|
8
8
|
import { tagVariants } from '@/design-system/components/Tag/tag'
|
|
9
|
-
import {
|
|
9
|
+
import { MOTION_DELAY_PLAIN_MS, MOTION_DELAY_CLOSE_MS } from '@/design-system/tokens/motion/motion'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* OverflowIndicator — +N 觸發器 + HoverCard 顯示溢出內容
|
|
@@ -96,13 +96,16 @@ const OverflowIndicator = React.forwardRef<HTMLSpanElement, OverflowIndicatorPro
|
|
|
96
96
|
) {
|
|
97
97
|
if (count <= 0) return null
|
|
98
98
|
|
|
99
|
+
// a11y(2026-07-14 dim-6):拆 role="button" + aria-haspopup="dialog" —— trigger 無
|
|
100
|
+
// activation 行為(無 Enter/Space handler,HoverCard 靠 hover/focus 自動開),宣告了
|
|
101
|
+
// button/haspopup 卻按 Enter 無反應 = 對 AT 空承諾。對齊 Avatar hoverCard 同款拆除
|
|
102
|
+
// (avatar.tsx 2026-07-06 + hover-card.spec.md「A11y 預設」:Radix 官方零 role/aria 定位)。
|
|
103
|
+
// trigger 有可見 "+N" 文字,無需 aria-label / role;保留 tabIndex=0 + focus ring(WCAG 2.1.1)。
|
|
99
104
|
const trigger = shape === 'tag' ? (
|
|
100
105
|
<span
|
|
101
106
|
ref={ref}
|
|
102
107
|
data-overflow-indicator=""
|
|
103
108
|
tabIndex={0}
|
|
104
|
-
role="button"
|
|
105
|
-
aria-haspopup="dialog"
|
|
106
109
|
className={cn(tagVariants({ color: 'neutral', size }), 'cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1', className)}
|
|
107
110
|
{...props}
|
|
108
111
|
>
|
|
@@ -113,8 +116,6 @@ const OverflowIndicator = React.forwardRef<HTMLSpanElement, OverflowIndicatorPro
|
|
|
113
116
|
ref={ref}
|
|
114
117
|
data-overflow-indicator=""
|
|
115
118
|
tabIndex={0}
|
|
116
|
-
role="button"
|
|
117
|
-
aria-haspopup="dialog"
|
|
118
119
|
className={cn(
|
|
119
120
|
'shrink-0 rounded-full inline-grid place-content-center',
|
|
120
121
|
'bg-muted text-foreground font-medium leading-none cursor-pointer',
|
|
@@ -130,11 +131,11 @@ const OverflowIndicator = React.forwardRef<HTMLSpanElement, OverflowIndicatorPro
|
|
|
130
131
|
)
|
|
131
132
|
|
|
132
133
|
// 2026-05-18 fix(per user audit「所有 hovercard 應消費 hover delay token」+ motion.spec.md SSOT):
|
|
133
|
-
// plain tier(純列表展開、無 fetch)=
|
|
134
|
-
// close =
|
|
134
|
+
// plain tier(純列表展開、無 fetch)= MOTION_DELAY_PLAIN_MS,per motion.spec.md 對照表 row;
|
|
135
|
+
// close = MOTION_DELAY_CLOSE_MS。2026-06-11 修:2026-05-18 token 遷移誤挑 rich(原 hardcode 200/300
|
|
135
136
|
// 兩 tier 皆非,遷移未對照 spec 表)— popup 可互動性由 close 緩衝保障,與 open tier 無關。
|
|
136
137
|
return (
|
|
137
|
-
<HoverCard openDelay={
|
|
138
|
+
<HoverCard openDelay={MOTION_DELAY_PLAIN_MS} closeDelay={MOTION_DELAY_CLOSE_MS}>
|
|
138
139
|
<HoverCardTrigger asChild>
|
|
139
140
|
{trigger}
|
|
140
141
|
</HoverCardTrigger>
|
|
@@ -64,7 +64,7 @@ Pagination 是「大量資料切成多頁後的位置導覽」——顯示當前
|
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
- **格位配置**:boundary 1 + sibling 1(= MUI `boundaryCount` / `siblingCount` 預設 1/1;內部常數,v1 不開 props——未來若開放,命名必沿用 MUI)。最大格位 = 首尾各 1 + 當前頁左右各 1 + 當前頁 + 2 顆 ellipsis = **7 格**,超過即摺疊。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
|
|
67
|
-
- **Ellipsis 非互動**:純指示符號(`MoreHorizontal` icon + `aria-hidden`),不可點——對齊 Ant /
|
|
67
|
+
- **Ellipsis 非互動**:純指示符號(`MoreHorizontal` icon + `aria-hidden`),不可點——對齊 MUI / shadcn(非互動 ellipsis)。**Ant 為可點 jump-5 派**(rc-pagination 預設把省略格渲染成 `jump-prev` / `jump-next`:hover 顯 «/»、click 跳 5 頁,`https://github.com/react-component/pagination`);本 DS 選非互動,快速跳頁留給未來 `showQuickJumper`。Breadcrumb 的可點 ellipsis 是 collapse dropdown 場景,語意不同。
|
|
68
68
|
- **上下頁按鈕**:iconOnly(`ChevronLeft` / `ChevronRight`),在第一頁 / 最後一頁時 `disabled`。
|
|
69
69
|
- 頁碼格位由內部演算法產生;兩顆省略號各自身分穩定,翻頁時不互相 remount(演算法簽名與 React key 等實作細節由 `pagination.tsx` 檔內註解單一持有,spec 不重述——職責分離)。
|
|
70
70
|
|
|
@@ -18,9 +18,7 @@ export const Default: Story = {
|
|
|
18
18
|
return (
|
|
19
19
|
<div className="flex flex-col gap-3">
|
|
20
20
|
<p className="text-caption text-fg-muted">
|
|
21
|
-
|
|
22
|
-
Ant 同款資料模型)。當前頁 `aria-current="page"`,選中 = 主色描邊+染字不染底;
|
|
23
|
-
選中之上 hover 升 hover 階、按壓 active 階。
|
|
21
|
+
客服工單佇列:共 128 筆、每頁 20 筆 → 7 頁。
|
|
24
22
|
</p>
|
|
25
23
|
<Pagination total={128} page={page} onPageChange={setPage} />
|
|
26
24
|
</div>
|
|
@@ -36,9 +34,7 @@ export const FullBar: Story = {
|
|
|
36
34
|
return (
|
|
37
35
|
<div className="flex flex-col gap-3">
|
|
38
36
|
<p className="text-caption text-fg-muted">
|
|
39
|
-
|
|
40
|
-
pageSizeOptions(「N 筆/頁」選單)—— 分頁完整功能 own 在本元件(SSOT),layout =
|
|
41
|
-
資訊左、操作群(頁碼+每頁筆數)右,對齊 Ant 源碼結構;換每頁筆數自動回第 1 頁。
|
|
37
|
+
搜尋結果頁:顯示總筆數 + 每頁筆數選單,左資訊右操作;換每頁筆數會自動回第 1 頁。
|
|
42
38
|
</p>
|
|
43
39
|
<Pagination
|
|
44
40
|
total={85}
|
|
@@ -172,7 +172,7 @@ const Pagination = React.forwardRef<HTMLElement, PaginationProps>(
|
|
|
172
172
|
</Button>
|
|
173
173
|
</li>
|
|
174
174
|
) : (
|
|
175
|
-
// Ellipsis 純指示不可點(
|
|
175
|
+
// Ellipsis 純指示不可點(MUI / shadcn 同;Ant 為可點 jump-5 派,見 spec);寬度對齊數字鈕保持節奏
|
|
176
176
|
<li
|
|
177
177
|
key={slot}
|
|
178
178
|
aria-hidden
|
|
@@ -66,7 +66,7 @@ export const Overview: Story = {
|
|
|
66
66
|
<tbody>
|
|
67
67
|
{[
|
|
68
68
|
['mode', "'edit' | 'display' | 'readonly' | 'disabled'", "'edit'", 'Field mode'],
|
|
69
|
-
['variant', "'default'
|
|
69
|
+
['variant', "'default'", "'default'", 'Field chrome variant(對齊 Select / Combobox;naked = @internal cell-as-input,2026-07-14 型別收窄至 FieldVariantInternal)'],
|
|
70
70
|
['size', "'sm' | 'md' | 'lg'", "'md'", '對齊 field-height tier'],
|
|
71
71
|
['value', 'PersonValue | PersonValue[] | null', '—', '單選 / 多選(類型決定模式)'],
|
|
72
72
|
['onChange', '(value: PersonValue[]) => void', '—', '值變更 callback(永遠 emit array)'],
|
|
@@ -78,7 +78,7 @@ export const Overview: Story = {
|
|
|
78
78
|
['pillShowAvatar', 'boolean', 'true', "multiDisplay='pill' 時是否顯示 avatar prefix"],
|
|
79
79
|
['pillWrap', 'boolean', 'true', 'pill 模式是否允許換行'],
|
|
80
80
|
['searchIn', "'menu' | 'trigger'", "'menu'", '搜尋型態(menu 浮層內 / trigger inline;multi 才有意義)'],
|
|
81
|
-
['showDisplayEndIcon', 'boolean', 'false', 'display 模式渲 ChevronDown + naked wrapper(DataTable
|
|
81
|
+
['showDisplayEndIcon', 'boolean', 'false', 'display 模式渲 ChevronDown + naked wrapper(opt-in 逃生門;2026-07-08 A 案後 DataTable 預設不傳)'],
|
|
82
82
|
['defaultOpen', 'boolean', 'false', 'uncontrolled 初始開啟狀態'],
|
|
83
83
|
['onOpenChange', '(open: boolean) => void', '—', 'open 狀態變更 callback'],
|
|
84
84
|
['disabled', 'boolean', 'false', '停用'],
|
|
@@ -97,7 +97,7 @@ export const Overview: Story = {
|
|
|
97
97
|
export const Inspector: Story = {
|
|
98
98
|
name: '元件檢閱器',
|
|
99
99
|
parameters: {
|
|
100
|
-
docs: { description: { story: '右側 Controls 切 props 即時 render,取代 Figma inspect。切 `mode` 看 edit / display / readonly / disabled 視覺差異,切 `size` 對照 field-height tier,切 `variant` 看 default /
|
|
100
|
+
docs: { description: { story: '右側 Controls 切 props 即時 render,取代 Figma inspect。切 `mode` 看 edit / display / readonly / disabled 視覺差異,切 `size` 對照 field-height tier,切 `variant` 看 default / naked chrome 差異。' } },
|
|
101
101
|
},
|
|
102
102
|
args: {
|
|
103
103
|
mode: 'edit',
|
|
@@ -112,7 +112,7 @@ export const Inspector: Story = {
|
|
|
112
112
|
},
|
|
113
113
|
argTypes: {
|
|
114
114
|
mode: { control: 'radio', options: ['edit', 'display', 'readonly', 'disabled'] },
|
|
115
|
-
variant: { control: 'radio', options: ['default', '
|
|
115
|
+
variant: { control: 'radio', options: ['default', 'naked'] },
|
|
116
116
|
size: { control: 'radio', options: ['sm', 'md', 'lg'] },
|
|
117
117
|
disabled: { control: 'boolean' },
|
|
118
118
|
showDisplayEndIcon: { control: 'boolean' },
|
|
@@ -175,13 +175,13 @@ export const EmptyStateRule: Story = {
|
|
|
175
175
|
<div>
|
|
176
176
|
<Rule
|
|
177
177
|
title="edit 模式 — 未選時顯示「請選擇人員」佔位提示"
|
|
178
|
-
note="跟 Select / Combobox 的 placeholder
|
|
178
|
+
note="跟 Select / Combobox 的 placeholder 行為一致。不用半形連字號,因為 edit mode 是可操作的"
|
|
179
179
|
>
|
|
180
180
|
<PeoplePicker value={null} onChange={() => {}} people={team} />
|
|
181
181
|
</Rule>
|
|
182
182
|
|
|
183
183
|
<Rule
|
|
184
|
-
title="readonly —
|
|
184
|
+
title="readonly — 未填時顯示半形連字號(-)"
|
|
185
185
|
note="跟所有 Field readonly 空值呈現一致。table cell 場景特別常見(未指派 assignee)"
|
|
186
186
|
>
|
|
187
187
|
<PeoplePicker mode="readonly" value={null} />
|
|
@@ -76,7 +76,7 @@ Multi mode 公開 `multiDisplay` / `pillShowAvatar` / `pillWrap` 三個顯示 pr
|
|
|
76
76
|
|
|
77
77
|
PeoplePicker 永遠支援搜尋(內部使用 `Command` / cmdk)——因為人員清單通常規模較大且使用者記得人名關鍵字(符合 Select spec「Searchable 開啟判斷」的「label 性質」主判準:人名是獨特關鍵字)。
|
|
78
78
|
|
|
79
|
-
- **搜尋 placeholder**:預設「搜尋人員…」,可透過 `searchPlaceholder`
|
|
79
|
+
- **搜尋 placeholder**:預設「搜尋人員…」,可透過 `searchPlaceholder` 覆寫。**僅 multi 模式 panel-top search(`searchIn='menu'`,default)生效**——single mode wrap `<Select searchable>` 走 inline-trigger 搜尋,提示取自 `placeholder`(Select 無 searchPlaceholder prop);multi `searchIn='trigger'` inline 搜尋同理走 placeholder 規則(見「Trigger display SSOT canonical table」§E)
|
|
80
80
|
- **空狀態**:預設「沒有符合的人員」,透過 `emptyText` 覆寫
|
|
81
81
|
|
|
82
82
|
---
|
|
@@ -96,8 +96,8 @@ PeoplePicker 永遠支援搜尋(內部使用 `Command` / cmdk)——因為
|
|
|
96
96
|
| 型態 | 使用情境 | 元件 API |
|
|
97
97
|
|---|---|---|
|
|
98
98
|
| **none** | 短列表 (< 7 選項) / 自然語言 label 可用 native type-ahead | 不傳 `searchable` |
|
|
99
|
-
| **inline-trigger** | 單選 + 需快速 type-and-pick;trigger 變 input | `<Select searchable />` / `<Combobox searchable searchIn='trigger' />` / `<PeoplePicker />`
|
|
100
|
-
| **panel-top** | 多選 + 連續 type-and-select(關鍵字保留在 menu 不被 chip 切走) | `<Combobox searchable searchIn='menu' />` / `<PeoplePicker
|
|
99
|
+
| **inline-trigger** | 單選 + 需快速 type-and-pick;trigger 變 input | `<Select searchable />` / `<Combobox searchable searchIn='trigger' />` / `<PeoplePicker value={person} />`(single = value 非陣列)/ `<PeoplePicker value={[...]} searchIn='trigger' />`(multi opt-in;無 `multi` prop — 單/多選由 value 是否為陣列決定,見「單選 vs 多選」)|
|
|
100
|
+
| **panel-top** | 多選 + 連續 type-and-select(關鍵字保留在 menu 不被 chip 切走) | `<Combobox searchable searchIn='menu' />` / `<PeoplePicker value={[...]} />`(multi default menu)|
|
|
101
101
|
|
|
102
102
|
### Trigger display SSOT canonical table(2026-05-15 v3 user verbatim 整理)
|
|
103
103
|
|
|
@@ -209,8 +209,8 @@ interface PersonData {
|
|
|
209
209
|
## readonly / disabled
|
|
210
210
|
|
|
211
211
|
與其他 Field 一致:
|
|
212
|
-
- **readonly**:顯示選中人員(Avatar + Name),無 dropdown trigger
|
|
213
|
-
- **disabled**:灰化整個 field
|
|
212
|
+
- **readonly**:顯示選中人員(Avatar + Name),無 dropdown trigger、無搜尋;avatar hover ProfileCard 保留(純展示仍可查閱人員資訊)
|
|
213
|
+
- **disabled**:灰化整個 field,不可互動——含 avatar dim(host-controlled opacity)+ 抑制 avatar ProfileCard hoverCard(無 HoverCard wrapper / 無 tab stop;2026-07-14 修,原 hoverCard 未抑制 falsify「不可互動」)
|
|
214
214
|
|
|
215
215
|
---
|
|
216
216
|
|
|
@@ -237,7 +237,7 @@ PeoplePicker 是 **composite Field Control**(Field shell + Avatar + SelectMenu),
|
|
|
237
237
|
|
|
238
238
|
## shadcn passthrough 例外說明
|
|
239
239
|
|
|
240
|
-
PeoplePicker 是 **composite 元件**(內部 wrap `<Select>`(single)/ `<Combobox>`(multi)),其主 API 為 declarative(value / onChange / size / mode /
|
|
240
|
+
PeoplePicker 是 **composite 元件**(內部 wrap `<Select>`(single)/ `<Combobox>`(multi)),其主 API 為 declarative(value / onChange / size / mode / people...)。**有套 `forwardRef` + HTML root props spread**(codex P2 fix 2026-05-07 v15.10,`people-picker.tsx:111` / L53 / L131 `...rest`):
|
|
241
241
|
|
|
242
242
|
- **forwardRef + 單一 root**:`PeoplePickerProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'>`,ref 與 `...rest`(`id` / `data-testid` / `onBlur` / `onFocus` / `aria-*` 等 HTML root props)forward 到內部 trigger 容器(readonly/disabled root div、或 wrapped Select / Combobox 的 root),對齊 DS 既有 Combobox / Select 慣例
|
|
243
243
|
- **`onChange` 走 Omit**:本元件 onChange 用 `(value: PersonValue[]) => void` custom signature,跟 HTMLAttributes onChange 衝突,故 Omit
|
|
@@ -4,20 +4,29 @@
|
|
|
4
4
|
import * as React from 'react'
|
|
5
5
|
import { ChevronDown } from 'lucide-react'
|
|
6
6
|
import { cn } from '@/lib/utils'
|
|
7
|
-
import type { FieldMode, FieldVariant } from '@/design-system/components/Field/field-types'
|
|
8
|
-
import { fieldWrapperStyles,
|
|
7
|
+
import type { FieldMode, FieldVariant, FieldVariantInternal, FieldWidth } from '@/design-system/components/Field/field-types'
|
|
8
|
+
import { fieldWrapperStyles, nakedCellRowModeAlign } from '@/design-system/components/Field/field-wrapper'
|
|
9
|
+
import { useFieldEmptyDisplay, fieldEmptyColorClass } from '@/design-system/components/Field/field-context'
|
|
9
10
|
import { ItemSuffix } from '@/design-system/patterns/element-anatomy/item-anatomy'
|
|
10
11
|
import { useFieldSurface, useResolvedFieldSize, useResolvedFieldDisabled, useResolvedFieldMode, useResolvedFieldVariant } from '@/design-system/components/Field/field-context'
|
|
11
12
|
import { Avatar } from '@/design-system/components/Avatar/avatar'
|
|
12
13
|
import { Tag } from '@/design-system/components/Tag/tag'
|
|
13
|
-
import { Select } from '@/design-system/components/Select/select'
|
|
14
|
-
import { Combobox } from '@/design-system/components/Combobox/combobox'
|
|
14
|
+
import { Select as SelectPublic } from '@/design-system/components/Select/select'
|
|
15
|
+
import { Combobox as ComboboxPublic } from '@/design-system/components/Combobox/combobox'
|
|
15
16
|
import { PersonDisplay, MultiPersonDisplay, PersonAvatarTag, buildPersonProfileCard, resolvePerson, type PersonValue } from './person-display'
|
|
16
17
|
import {
|
|
17
18
|
getAvatarStackVisibleCount,
|
|
18
19
|
AVATAR_STACK_AVATAR_PX,
|
|
19
20
|
AVATAR_STACK_OVERFLOW_CHIP_PX,
|
|
20
21
|
} from './avatar-stack-overflow'
|
|
22
|
+
import type { WithFieldVariantInternal } from '@/design-system/components/Field/field-types'
|
|
23
|
+
|
|
24
|
+
// ── @internal naked variant forward 通道(2026-07-14 API 策展 E)──────────────────────────
|
|
25
|
+
// naked 已從公開 FieldVariant 拆出(field-types.ts FieldVariantInternal)。PeoplePicker 是
|
|
26
|
+
// Select / Combobox 的 wrapper:cell-registry 傳入的 naked 需原樣 forward 給 primitive
|
|
27
|
+
// (M30 wrapper forward 全 primitive surface)。型別層 widen,純型別、零 runtime。
|
|
28
|
+
const Select = SelectPublic as WithFieldVariantInternal<typeof SelectPublic>
|
|
29
|
+
const Combobox = ComboboxPublic as WithFieldVariantInternal<typeof ComboboxPublic>
|
|
21
30
|
// Pure helpers extracted to sibling for file-size budget(2026-05-18,P1 ≤ 500 lines)。
|
|
22
31
|
// 不消費 component closure 的純 constant / 純 mapping function 全部搬走,主檔保留 SSOT-bearing
|
|
23
32
|
// render logic(消費 Combobox / Select / state 等 closure 的部分)。
|
|
@@ -55,6 +64,9 @@ export interface PeoplePickerProps extends Omit<React.HTMLAttributes<HTMLDivElem
|
|
|
55
64
|
mode?: FieldMode
|
|
56
65
|
/** Field chrome variant(對齊 Select / Combobox)*/
|
|
57
66
|
variant?: FieldVariant
|
|
67
|
+
/** 寬度軸 — `fill` 填滿容器(default)/ `hug` 依內容收縮(value 寬 + slot 寬 + gap + 內 padding);
|
|
68
|
+
* chrome 與互動不變。SSOT → field-controls.spec.md「寬度軸(width: fill / hug)」。 */
|
|
69
|
+
width?: FieldWidth
|
|
58
70
|
size?: 'sm' | 'md' | 'lg'
|
|
59
71
|
/** 當前已選的人(單選 PersonValue,多選 PersonValue[])*/
|
|
60
72
|
value?: PersonValue | PersonValue[] | null
|
|
@@ -65,7 +77,10 @@ export interface PeoplePickerProps extends Omit<React.HTMLAttributes<HTMLDivElem
|
|
|
65
77
|
/** 2026-05-12 Stream C Issue 4 fix(codex Q3 Cluster C):trigger empty placeholder。
|
|
66
78
|
* Default '請選擇人員'。**禁** 將 `emptyText`(search-empty)當 trigger placeholder 傳。 */
|
|
67
79
|
placeholder?: string
|
|
68
|
-
/** 搜尋框 placeholder
|
|
80
|
+
/** 搜尋框 placeholder — **僅 multi 模式 panel-top search(`searchIn='menu'`,default)生效**。
|
|
81
|
+
* single mode wrap `<Select searchable>` 走 inline-trigger 搜尋,提示取自 `placeholder`
|
|
82
|
+
* (Select 無 searchPlaceholder prop);multi `searchIn='trigger'` inline 搜尋同理走
|
|
83
|
+
* placeholder 規則(spec「Trigger display SSOT canonical table」)。 */
|
|
69
84
|
searchPlaceholder?: string
|
|
70
85
|
/** 搜尋無結果訊息(filtered menu empty)。**僅**用於 SelectMenu `emptyText`(菜單空狀態,
|
|
71
86
|
* 2026-07-04 Q4 接線完成),不轉 trigger placeholder(2026-05-12 Issue 4 semantic fix)。 */
|
|
@@ -111,6 +126,7 @@ export interface PeoplePickerProps extends Omit<React.HTMLAttributes<HTMLDivElem
|
|
|
111
126
|
const PeoplePicker = React.forwardRef<HTMLDivElement, PeoplePickerProps>(function PeoplePicker({
|
|
112
127
|
mode: modeProp,
|
|
113
128
|
variant: variantProp,
|
|
129
|
+
width,
|
|
114
130
|
size: sizeProp,
|
|
115
131
|
value,
|
|
116
132
|
onChange,
|
|
@@ -131,11 +147,12 @@ const PeoplePicker = React.forwardRef<HTMLDivElement, PeoplePickerProps>(functio
|
|
|
131
147
|
...rest
|
|
132
148
|
}, ref) {
|
|
133
149
|
const surface = useFieldSurface()
|
|
150
|
+
const emptyDisplay = useFieldEmptyDisplay()
|
|
134
151
|
const size = useResolvedFieldSize(sizeProp) // B 組 cascade fix
|
|
135
152
|
const disabled = useResolvedFieldDisabled(disabledProp)
|
|
136
153
|
// 2026-06-08 SSOT:mode/disabled/variant 統一經 helper;修 <Field disabled> 漏 cascade(原只讀 fieldCtx.mode)
|
|
137
154
|
const resolvedMode: FieldMode = useResolvedFieldMode({ mode: modeProp, disabled })
|
|
138
|
-
const resolvedVariant:
|
|
155
|
+
const resolvedVariant: FieldVariantInternal = useResolvedFieldVariant(variantProp)
|
|
139
156
|
const isMulti = Array.isArray(value)
|
|
140
157
|
const isEmpty = !value || (isMulti && value.length === 0)
|
|
141
158
|
|
|
@@ -195,7 +212,7 @@ const PeoplePicker = React.forwardRef<HTMLDivElement, PeoplePickerProps>(functio
|
|
|
195
212
|
// 與 edit (Select / Combobox wrapped) 同 DOM 結構消除 cell display↔edit 像素偏移。
|
|
196
213
|
if (resolvedMode === 'display') {
|
|
197
214
|
if (!showDisplayEndIcon) {
|
|
198
|
-
if (isEmpty) return <span className=
|
|
215
|
+
if (isEmpty) return <span className={fieldEmptyColorClass(resolvedMode)}>{emptyDisplay}</span>
|
|
199
216
|
return isMulti
|
|
200
217
|
? <MultiPersonDisplay value={value as PersonValue[]} size={size} measured />
|
|
201
218
|
: <PersonDisplay value={value as PersonValue} size={size} />
|
|
@@ -204,12 +221,12 @@ const PeoplePicker = React.forwardRef<HTMLDivElement, PeoplePickerProps>(functio
|
|
|
204
221
|
const iconSize = ICON_SIZE[size as 'sm' | 'md' | 'lg']
|
|
205
222
|
return (
|
|
206
223
|
<div
|
|
207
|
-
className={cn(fieldWrapperStyles({ mode: 'display', variant: resolvedVariant, size }), className)}
|
|
224
|
+
className={cn(fieldWrapperStyles({ mode: 'display', variant: resolvedVariant, width, size }), className)}
|
|
208
225
|
data-field-mode="display"
|
|
209
226
|
>
|
|
210
227
|
<span className={cn('flex-1 min-w-0 inline-flex items-center', nakedCellRowModeAlign)}>
|
|
211
228
|
{isEmpty
|
|
212
|
-
? <span className=
|
|
229
|
+
? <span className={fieldEmptyColorClass(resolvedMode)}>{emptyDisplay}</span>
|
|
213
230
|
: isMulti
|
|
214
231
|
? <MultiPersonDisplay value={value as PersonValue[]} size={size} measured />
|
|
215
232
|
: <PersonDisplay value={value as PersonValue} size={size} />}
|
|
@@ -226,18 +243,20 @@ const PeoplePicker = React.forwardRef<HTMLDivElement, PeoplePickerProps>(functio
|
|
|
226
243
|
return (
|
|
227
244
|
<div
|
|
228
245
|
ref={ref}
|
|
229
|
-
className={cn(fieldWrapperStyles({ mode: resolvedMode, variant: resolvedVariant, size }), className)}
|
|
246
|
+
className={cn(fieldWrapperStyles({ mode: resolvedMode, variant: resolvedVariant, width, size }), className)}
|
|
230
247
|
data-field-mode={resolvedMode}
|
|
231
248
|
aria-disabled={resolvedMode === 'disabled' ? true : undefined}
|
|
232
249
|
aria-label={ariaLabel}
|
|
233
250
|
{...rest}
|
|
234
251
|
>
|
|
235
252
|
<span className={cn('flex-1 min-w-0 inline-flex items-center', nakedCellRowModeAlign, resolvedMode === 'disabled' && 'text-fg-disabled')}>
|
|
253
|
+
{/* 2026-07-14 deep-audit 修:disabled 傳入 → 抑制 Avatar ProfileCard hoverCard + avatar dim
|
|
254
|
+
(spec「disabled:灰化整個 field,不可互動」原被 hoverCard falsify);readonly 保留 hoverCard(純展示仍可查閱) */}
|
|
236
255
|
{isEmpty
|
|
237
|
-
? <span className=
|
|
256
|
+
? <span className={fieldEmptyColorClass(resolvedMode)}>{emptyDisplay}</span>
|
|
238
257
|
: isMulti
|
|
239
|
-
? <MultiPersonDisplay value={value as PersonValue[]} size={size} measured />
|
|
240
|
-
: <PersonDisplay value={value as PersonValue} size={size} />}
|
|
258
|
+
? <MultiPersonDisplay value={value as PersonValue[]} size={size} measured disabled={resolvedMode === 'disabled'} />
|
|
259
|
+
: <PersonDisplay value={value as PersonValue} size={size} disabled={resolvedMode === 'disabled'} />}
|
|
241
260
|
</span>
|
|
242
261
|
{/* 2026-06-26 類型身份 indicator:edit 顯示 / readonly 不顯示 / disabled 保留(fg-disabled,對齊原生 <select disabled>);naked cell 依 showDisplayEndIcon */}
|
|
243
262
|
{(resolvedVariant === 'naked' ? showDisplayEndIcon : resolvedMode === 'disabled') && (
|
|
@@ -258,6 +277,9 @@ const PeoplePicker = React.forwardRef<HTMLDivElement, PeoplePickerProps>(functio
|
|
|
258
277
|
return (
|
|
259
278
|
<Select
|
|
260
279
|
ref={ref as React.Ref<HTMLDivElement>}
|
|
280
|
+
// 2026-07-14 deep-audit fix:width 補 forward(原漏傳 → single edit path 忽略公開 width prop;
|
|
281
|
+
// multi pill / stack 皆有傳,對齊 M30 wrapper forward 全 primitive surface)
|
|
282
|
+
width={width}
|
|
261
283
|
size={size}
|
|
262
284
|
variant={resolvedVariant}
|
|
263
285
|
options={people.map(personToSelectOption)}
|
|
@@ -273,9 +295,11 @@ const PeoplePicker = React.forwardRef<HTMLDivElement, PeoplePickerProps>(functio
|
|
|
273
295
|
className={className}
|
|
274
296
|
aria-label={ariaLabel}
|
|
275
297
|
selectedItemRenderer={(opt) => <PersonDisplay value={findPerson(people, opt.value)} size={size} />}
|
|
276
|
-
// **codex P2 forward**:Select
|
|
277
|
-
//
|
|
278
|
-
// (`onCopy` / `onChange` 等)。
|
|
298
|
+
// **codex P2 forward**:Select 原生屬性走 allowlist(`Pick<SelectHTMLAttributes>`,
|
|
299
|
+
// 2026-07-14 API 策展 D,見 select.tsx SelectProps docblock),event handler element
|
|
300
|
+
// 型別跟 PeoplePicker `HTMLAttributes<HTMLDivElement>` 不一致(`onCopy` / `onChange` 等)。
|
|
301
|
+
// Runtime spread 等效 — DOM 收到 attrs 不挑剔(非 allowlist attrs 落 CustomSelect rest,
|
|
302
|
+
// 續 spread 到 trigger div,runtime 行為不變)。
|
|
279
303
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
280
304
|
// any-allow: rest 含 `onChange: FormEventHandler` 跟 Select onChange signature 衝突 — DOM runtime spread 安全(per codex P2 forward)
|
|
281
305
|
{...(rest as any)}
|
|
@@ -290,6 +314,7 @@ const PeoplePicker = React.forwardRef<HTMLDivElement, PeoplePickerProps>(functio
|
|
|
290
314
|
}
|
|
291
315
|
return (
|
|
292
316
|
<Combobox
|
|
317
|
+
width={width}
|
|
293
318
|
ref={ref as React.Ref<HTMLDivElement>}
|
|
294
319
|
size={size}
|
|
295
320
|
variant={resolvedVariant}
|
|
@@ -297,6 +322,9 @@ const PeoplePicker = React.forwardRef<HTMLDivElement, PeoplePickerProps>(functio
|
|
|
297
322
|
value={selectedNames}
|
|
298
323
|
onChange={handleMultiChange}
|
|
299
324
|
searchable
|
|
325
|
+
// 2026-07-14 deep-audit fix:searchIn 補 forward(原漏傳 → pill 模式永遠 Combobox default 'menu',
|
|
326
|
+
// documented multi opt-in `searchIn='trigger'` silently 無效;stack branch 已傳,對齊 M30 forward 全 surface)
|
|
327
|
+
searchIn={searchIn}
|
|
300
328
|
searchPlaceholder={searchPlaceholder}
|
|
301
329
|
// 2026-05-12 Stream C Issue 4(codex Q3):placeholder = trigger empty hint('請選擇人員')
|
|
302
330
|
// — semantic clean separation。2026-07-04 Q4 拍板完成 1-cycle 承諾:emptyPlaceholder forward
|
|
@@ -353,6 +381,7 @@ const PeoplePicker = React.forwardRef<HTMLDivElement, PeoplePickerProps>(functio
|
|
|
353
381
|
|
|
354
382
|
return (
|
|
355
383
|
<Combobox
|
|
384
|
+
width={width}
|
|
356
385
|
ref={mergedStackRef}
|
|
357
386
|
size={size}
|
|
358
387
|
variant={resolvedVariant}
|
|
@@ -472,3 +501,14 @@ export const peoplePickerMeta = {
|
|
|
472
501
|
} as const
|
|
473
502
|
|
|
474
503
|
export { PeoplePicker }
|
|
504
|
+
// 2026-07-10 C14 export 缺口修(R2 同類:定義存在但無 export 面,consumer 想守 PersonValue 鏈
|
|
505
|
+
// import 不到 → 被逼手刻)。person-display 表面隨 PeoplePicker subpath + root barrel 一併公開。
|
|
506
|
+
export {
|
|
507
|
+
PersonDisplay,
|
|
508
|
+
MultiPersonDisplay,
|
|
509
|
+
PersonAvatarTag,
|
|
510
|
+
buildPersonProfileCard,
|
|
511
|
+
resolvePerson,
|
|
512
|
+
type PersonValue,
|
|
513
|
+
type PersonData,
|
|
514
|
+
} from './person-display'
|
|
@@ -1,7 +1,8 @@
|
|
|
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 * as React from 'react'
|
|
3
3
|
import { X } from 'lucide-react'
|
|
4
|
-
import {
|
|
4
|
+
import { cn } from '@/lib/utils'
|
|
5
|
+
import { useFieldEmptyDisplay } from '@/design-system/components/Field/field-context'
|
|
5
6
|
import { Tag } from '@/design-system/components/Tag/tag'
|
|
6
7
|
import { OverflowIndicator } from '@/design-system/components/OverflowIndicator/overflow-indicator'
|
|
7
8
|
import { Avatar } from '@/design-system/components/Avatar/avatar'
|
|
@@ -16,10 +17,11 @@ import {
|
|
|
16
17
|
|
|
17
18
|
// ── Types ───────────────────────────────────────────────────────────────────
|
|
18
19
|
|
|
19
|
-
// PersonData 承載 ProfileCard 所需的完整資訊。DS 全域 person avatar 的 hoverCard ProfileCard
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
20
|
+
// PersonData 承載 ProfileCard 所需的完整資訊。DS 全域 person avatar 的 hoverCard ProfileCard 顯示
|
|
21
|
+
// 同一組 sections(name + subtitle + status + 2 default fields(id + employeeNumber,見下方
|
|
22
|
+
// NAMECARD_DEFAULT_FIELD_KEYS 對齊註解)+ 自訂 fields + actions + View more)— 缺資料顯 placeholder;
|
|
23
|
+
// **例外:status undefined 時整 status block 省略(collapse,= loading transient,見 status jsDoc)**。
|
|
24
|
+
// 對齊 avatar.spec.md「person avatar hover → ProfileCard」DS-wide canonical。
|
|
23
25
|
export interface PersonData {
|
|
24
26
|
name: string
|
|
25
27
|
avatarUrl?: string
|
|
@@ -109,23 +111,30 @@ function PersonAvatar({
|
|
|
109
111
|
size = 'md',
|
|
110
112
|
className = '',
|
|
111
113
|
style,
|
|
114
|
+
disabled = false,
|
|
112
115
|
}: {
|
|
113
116
|
person: PersonData
|
|
114
117
|
size?: 'sm' | 'md' | 'lg'
|
|
115
118
|
className?: string
|
|
116
119
|
style?: React.CSSProperties
|
|
120
|
+
/** disabled field context(2026-07-14 deep-audit 修):抑制 ProfileCard hoverCard(Avatar 收
|
|
121
|
+
* undefined → 無 HoverCard wrapper / 無 tabIndex,真不可互動)+ avatar 自身 dim(host-controlled
|
|
122
|
+
* opacity — avatar.spec.md「Avatar 在 disabled 元件內 host-controlled opacity」canonical;
|
|
123
|
+
* PeoplePicker disabled 分支無 fieldCtx,Avatar self-dim 搆不到,host 補)。
|
|
124
|
+
* 對齊 people-picker.spec.md「disabled:灰化整個 field,不可互動」。 */
|
|
125
|
+
disabled?: boolean
|
|
117
126
|
}) {
|
|
118
127
|
const isTableScrolling = useTableIsScrolling()
|
|
119
128
|
const nameCard = React.useMemo(
|
|
120
|
-
() => (isTableScrolling ? undefined : buildPersonProfileCard(person)),
|
|
121
|
-
[person, isTableScrolling]
|
|
129
|
+
() => (isTableScrolling || disabled ? undefined : buildPersonProfileCard(person)),
|
|
130
|
+
[person, isTableScrolling, disabled]
|
|
122
131
|
)
|
|
123
132
|
return (
|
|
124
133
|
<Avatar
|
|
125
134
|
src={person.avatarUrl}
|
|
126
135
|
alt={person.name}
|
|
127
136
|
size={AVATAR_PX[size]}
|
|
128
|
-
className={className}
|
|
137
|
+
className={cn(className, disabled && 'opacity-disabled')}
|
|
129
138
|
style={style}
|
|
130
139
|
hoverCard={nameCard}
|
|
131
140
|
/>
|
|
@@ -138,8 +147,9 @@ function PersonAvatar({
|
|
|
138
147
|
// outer 改 items-start + Avatar 外包 ItemPrefix primitive consumption。單行視覺 = items-center 等效;
|
|
139
148
|
// 多行(autoRowHeight cell)避免 avatar+name center 整 row 不對齊 first-line text top。M1 消費既有
|
|
140
149
|
// 對齊 TreeView / MenuItem / SelectionItem 共用 ItemPrefix wrap chevron/icon/avatar canonical。
|
|
141
|
-
function PersonDisplay({ value, size = 'md' }: { value?: PersonValue | null; size?: 'sm' | 'md' | 'lg' }) {
|
|
142
|
-
|
|
150
|
+
function PersonDisplay({ value, size = 'md', disabled = false }: { value?: PersonValue | null; size?: 'sm' | 'md' | 'lg'; /** 見 PersonAvatar.disabled jsDoc(抑制 hoverCard + dim) */ disabled?: boolean }) {
|
|
151
|
+
const emptyDisplay = useFieldEmptyDisplay()
|
|
152
|
+
if (!value) return <span className="text-foreground">{emptyDisplay}</span>
|
|
143
153
|
|
|
144
154
|
const person = resolvePerson(value)
|
|
145
155
|
|
|
@@ -150,7 +160,7 @@ function PersonDisplay({ value, size = 'md' }: { value?: PersonValue | null; siz
|
|
|
150
160
|
// 對齊 GitHub Primer ActionList / Slack users_select / Atlassian UserPicker truncation canonical。
|
|
151
161
|
return (
|
|
152
162
|
<span className="flex items-start gap-2 min-w-0 w-full">
|
|
153
|
-
<ItemPrefix><PersonAvatar person={person} size={size} /></ItemPrefix>
|
|
163
|
+
<ItemPrefix><PersonAvatar person={person} size={size} disabled={disabled} /></ItemPrefix>
|
|
154
164
|
<span className="truncate flex-1 min-w-0">{person.name}</span>
|
|
155
165
|
</span>
|
|
156
166
|
)
|
|
@@ -168,6 +178,7 @@ function MultiPersonDisplay({
|
|
|
168
178
|
max,
|
|
169
179
|
measured = false,
|
|
170
180
|
onRemove,
|
|
181
|
+
disabled = false,
|
|
171
182
|
}: {
|
|
172
183
|
value?: PersonValue[] | null
|
|
173
184
|
size?: 'sm' | 'md' | 'lg'
|
|
@@ -182,7 +193,10 @@ function MultiPersonDisplay({
|
|
|
182
193
|
measured?: boolean
|
|
183
194
|
/** 傳入時啟用 dismiss(edit mode),callback 接收被移除的 person */
|
|
184
195
|
onRemove?: (person: PersonValue) => void
|
|
196
|
+
/** 見 PersonAvatar.disabled jsDoc(抑制全 stack ProfileCard hoverCard + avatar dim) */
|
|
197
|
+
disabled?: boolean
|
|
185
198
|
}) {
|
|
199
|
+
const emptyDisplay = useFieldEmptyDisplay()
|
|
186
200
|
// 2026-07-05 D3 P1 修(React #310 家族):3 hooks 原在 empty early return 之後 — value 非空↔空
|
|
187
201
|
// 切換時 hook 數 0↔3 變動必 crash(現靠 consumer 三元切換 element type 偶然避開)。hoist 到 return 前。
|
|
188
202
|
// 2026-05-15 Bug 3 fix(Claude+Codex Step 5 比稿 consensus):消費 shared `avatar-stack-overflow`
|
|
@@ -211,7 +225,7 @@ function MultiPersonDisplay({
|
|
|
211
225
|
return () => ro.disconnect()
|
|
212
226
|
}, [measured, size, value])
|
|
213
227
|
|
|
214
|
-
if (!value || value.length === 0) return <span className="text-
|
|
228
|
+
if (!value || value.length === 0) return <span className="text-foreground">{emptyDisplay}</span>
|
|
215
229
|
|
|
216
230
|
const resolvedMax = measured && measuredCount !== null ? measuredCount : (max ?? 3)
|
|
217
231
|
const people = value.map(resolvePerson)
|
|
@@ -221,7 +235,7 @@ function MultiPersonDisplay({
|
|
|
221
235
|
|
|
222
236
|
// 單人回退到 PersonDisplay(顯示名字)
|
|
223
237
|
if (people.length === 1) {
|
|
224
|
-
return <PersonDisplay value={value[0]} size={size} />
|
|
238
|
+
return <PersonDisplay value={value[0]} size={size} disabled={disabled} />
|
|
225
239
|
}
|
|
226
240
|
|
|
227
241
|
// 2026-05-14 item-anatomy SSOT fix(per codex+Layer A 共識):outer items-start + avatar stack
|
|
@@ -241,6 +255,7 @@ function MultiPersonDisplay({
|
|
|
241
255
|
person={person}
|
|
242
256
|
size={size}
|
|
243
257
|
className="ring-2 ring-[var(--surface)]"
|
|
258
|
+
disabled={disabled}
|
|
244
259
|
/>
|
|
245
260
|
{handleDismiss && <AvatarDismissOverlay onRemove={handleDismiss} label={person.name} />}
|
|
246
261
|
</span>
|
|
@@ -266,7 +281,8 @@ function MultiPersonDisplay({
|
|
|
266
281
|
src={person.avatarUrl}
|
|
267
282
|
alt={person.name}
|
|
268
283
|
size={16}
|
|
269
|
-
hoverCard
|
|
284
|
+
// disabled field:同 PersonAvatar — 抑制 ProfileCard hoverCard(不可互動)
|
|
285
|
+
hoverCard={disabled ? undefined : buildPersonProfileCard(person)}
|
|
270
286
|
/>
|
|
271
287
|
}
|
|
272
288
|
onRemove={onRemove ? () => onRemove(value![resolvedMax + i]) : undefined}
|
|
@@ -293,8 +309,8 @@ MultiPersonDisplay.displayName = 'MultiPersonDisplay'
|
|
|
293
309
|
// sm/md stroke 規格;2026-06-12 同步 checkbox 2026-05-18 簡化 3.5→3,SSOT →
|
|
294
310
|
// .claude/references/ui-dev-rules.md「小尺寸 icon stroke 補償」)
|
|
295
311
|
// - **text-on-emphasis**(白 X,確保飽和色底對比)
|
|
296
|
-
// - **位置 `absolute top-
|
|
297
|
-
//
|
|
312
|
+
// - **位置 `absolute -top-px -right-1`**(top -1px / right -4px,右緣凸出 avatar 外 4px —
|
|
313
|
+
// v15.15 user-confirmed asymmetric canonical,rationale 見下方 className 內註解)
|
|
298
314
|
//
|
|
299
315
|
// **a11y**(codex P1 fix):`opacity-0` 而非 `display:none` — element 在 DOM/tab-order,
|
|
300
316
|
// keyboard tab 可達,觸控 focus-within 也顯。Hover / focus-within / focus-visible
|
|
@@ -19,7 +19,7 @@ export const Overview: Story = {
|
|
|
19
19
|
<div className="flex flex-col gap-10">
|
|
20
20
|
<div>
|
|
21
21
|
<H3>Anatomy</H3>
|
|
22
|
-
<Desc>Popover
|
|
22
|
+
<Desc>Popover 是點擊觸發的浮層容器,提供定位 / 動畫 / 焦點管理 / click-outside 關閉。內容完全由 consumer 決定(可放任何 React 元素)。本 DS 在 Radix Popover 上橋接 elevation / radius / border token,並覆寫兩處 a11y 行為(非全等 Radix,詳「A11y 預設」段 DS 覆寫):開啟焦點落在 body 首個互動元素(而非 Radix 預設 close X)、以及自動接線 aria-labelledby(有 PopoverTitle 時)。</Desc>
|
|
23
23
|
<div className="flex items-center gap-4">
|
|
24
24
|
<Popover>
|
|
25
25
|
<PopoverTrigger asChild>
|
|
@@ -45,7 +45,7 @@ export const Overview: Story = {
|
|
|
45
45
|
|
|
46
46
|
<div>
|
|
47
47
|
<H3>Props 速查</H3>
|
|
48
|
-
<Desc>Popover / PopoverTrigger / PopoverContent
|
|
48
|
+
<Desc>Popover / PopoverTrigger / PopoverContent 沿用 Radix Popover 的同名 prop(定位 / 開關 / modal 等 props 與 Radix 一致),並接上設計系統 token。**例外**:PopoverContent 覆寫兩處 a11y 行為(`onOpenAutoFocus` 讓開啟焦點落 body 首個互動元素、自動接線 `aria-labelledby`),故行為非全等 Radix,詳「A11y 預設」段。Props 依宣告元件分兩類——定位類(align / side / sideOffset / collisionPadding)寫在 {'<PopoverContent>'} 上,開關 / modal 類(open / onOpenChange / defaultOpen / modal)寫在最外層 {'<Popover>'}(Root)上;寫錯元件不會生效(見「所屬元件」欄)。完整 API 見 <a href="https://www.radix-ui.com/primitives/docs/components/popover" className="underline" target="_blank" rel="noreferrer">Radix Popover 官方文件</a>。</Desc>
|
|
49
49
|
<div className="overflow-x-auto">
|
|
50
50
|
{/* @anatomy-exempt-next: Props 速查表為純文件對照(prop/type/default),非元件資料展示;DataTable 過重 */}
|
|
51
51
|
<table className="text-caption border-collapse">
|
|
@@ -7,6 +7,7 @@ import { cn } from "@/lib/utils"
|
|
|
7
7
|
import { SurfaceHeader, SurfaceBody, SurfaceFooter, COMPACT_HEADER_SLOT } from "@/design-system/patterns/overlay-surface/overlay-surface"
|
|
8
8
|
import { Button } from "@/design-system/components/Button/button"
|
|
9
9
|
import { OVERLAY_SIDE_OFFSET, OVERLAY_COLLISION_PADDING } from "@/design-system/tokens/elevation/overlay-geometry"
|
|
10
|
+
import { overlayMotion } from "@/design-system/tokens/motion/overlay-motion"
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Popover — Radix Popover + 設計系統 token
|
|
@@ -100,7 +101,8 @@ const PopoverContent = React.forwardRef<
|
|
|
100
101
|
// 2026-05-04 viewport-aware max-h SSOT(從 ProfileCard 升 DS-wide):header/footer 永遠 in-viewport,body 壓縮 scroll
|
|
101
102
|
// 2026-05-05 audit dim 35 補:加 `min-h-0` 完成 M25 chain invariant(flex item default min-h: auto 阻 shrink)
|
|
102
103
|
"max-h-[var(--radix-popover-content-available-height,100vh)] flex flex-col overflow-hidden min-h-0",
|
|
103
|
-
|
|
104
|
+
overlayMotion,
|
|
105
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
104
106
|
"data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
105
107
|
"origin-[var(--radix-popover-content-transform-origin)]",
|
|
106
108
|
className
|