@qijenchen/design-system 0.1.0-beta.61 → 0.1.0-beta.63
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 +6 -6
- package/dist/components/Accordion/accordion.d.ts +1 -1
- package/dist/components/Accordion/accordion.js +1 -1
- package/dist/components/Accordion/accordion.js.map +1 -1
- package/dist/components/Alert/alert.d.ts +2 -2
- package/dist/components/Alert/alert.js +4 -3
- package/dist/components/Alert/alert.js.map +1 -1
- package/dist/components/AppShell/app-shell.d.ts.map +1 -1
- package/dist/components/AppShell/app-shell.js +4 -3
- package/dist/components/AppShell/app-shell.js.map +1 -1
- package/dist/components/Avatar/avatar.d.ts +1 -1
- package/dist/components/Avatar/avatar.js +2 -1
- package/dist/components/Avatar/avatar.js.map +1 -1
- package/dist/components/Badge/badge.d.ts +1 -1
- package/dist/components/Badge/badge.js +2 -1
- package/dist/components/Badge/badge.js.map +1 -1
- package/dist/components/Breadcrumb/breadcrumb.d.ts +1 -1
- package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
- package/dist/components/BulkActionBar/bulk-action-bar.js.map +1 -1
- package/dist/components/Button/button.d.ts +5 -5
- package/dist/components/Button/button.d.ts.map +1 -1
- package/dist/components/Button/button.js +4 -3
- package/dist/components/Button/button.js.map +1 -1
- package/dist/components/Calendar/calendar.d.ts +1 -1
- package/dist/components/Calendar/calendar.d.ts.map +1 -1
- package/dist/components/Calendar/calendar.js +80 -69
- 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 +5 -3
- package/dist/components/Carousel/carousel.js.map +1 -1
- package/dist/components/Checkbox/checkbox-group.d.ts +2 -1
- package/dist/components/Checkbox/checkbox-group.d.ts.map +1 -1
- package/dist/components/Checkbox/checkbox-group.js.map +1 -1
- package/dist/components/Checkbox/checkbox.d.ts +9 -3
- package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox/checkbox.js +8 -3
- package/dist/components/Checkbox/checkbox.js.map +1 -1
- package/dist/components/Chip/chip.d.ts +2 -2
- package/dist/components/Chip/chip.js +3 -2
- package/dist/components/Chip/chip.js.map +1 -1
- package/dist/components/CircularProgress/circular-progress.d.ts +1 -1
- package/dist/components/CircularProgress/circular-progress.js +2 -1
- package/dist/components/CircularProgress/circular-progress.js.map +1 -1
- package/dist/components/Coachmark/coachmark.d.ts +4 -4
- package/dist/components/Coachmark/coachmark.js +2 -1
- package/dist/components/Coachmark/coachmark.js.map +1 -1
- package/dist/components/Combobox/combobox.d.ts.map +1 -1
- package/dist/components/Combobox/combobox.js +17 -13
- package/dist/components/Combobox/combobox.js.map +1 -1
- package/dist/components/Command/command.d.ts +4 -0
- package/dist/components/Command/command.d.ts.map +1 -1
- package/dist/components/Command/command.js.map +1 -1
- package/dist/components/DataTable/data-table.d.ts.map +1 -1
- package/dist/components/DataTable/data-table.js.map +1 -1
- package/dist/components/DateGrid/date-grid.d.ts +8 -4
- package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
- package/dist/components/DateGrid/date-grid.js +2 -2
- package/dist/components/DateGrid/date-grid.js.map +1 -1
- package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
- package/dist/components/DatePicker/date-picker.js +6 -4
- package/dist/components/DatePicker/date-picker.js.map +1 -1
- package/dist/components/DescriptionList/description-list.js +1 -1
- package/dist/components/DescriptionList/description-list.js.map +1 -1
- package/dist/components/Dialog/dialog.d.ts.map +1 -1
- package/dist/components/Dialog/dialog.js.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.d.ts +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.js +0 -1
- package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
- package/dist/components/Empty/empty.d.ts +1 -1
- package/dist/components/Empty/empty.js.map +1 -1
- package/dist/components/Field/field-wrapper.js +1 -1
- package/dist/components/Field/field-wrapper.js.map +1 -1
- package/dist/components/Field/field.d.ts.map +1 -1
- package/dist/components/Field/field.js +1 -0
- package/dist/components/Field/field.js.map +1 -1
- package/dist/components/FieldControlGroup/field-control-group.d.ts.map +1 -1
- package/dist/components/FieldControlGroup/field-control-group.js +1 -1
- package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
- package/dist/components/FileUpload/file-upload.d.ts +8 -1
- package/dist/components/FileUpload/file-upload.d.ts.map +1 -1
- package/dist/components/FileUpload/file-upload.js +7 -3
- package/dist/components/FileUpload/file-upload.js.map +1 -1
- package/dist/components/FileViewer/file-viewer.d.ts +1 -1
- package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
- package/dist/components/FileViewer/file-viewer.js +25 -14
- package/dist/components/FileViewer/file-viewer.js.map +1 -1
- package/dist/components/HoverCard/hover-card.d.ts +5 -1
- package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
- package/dist/components/HoverCard/hover-card.js +2 -1
- package/dist/components/HoverCard/hover-card.js.map +1 -1
- package/dist/components/Menu/menu-item.d.ts +6 -2
- package/dist/components/Menu/menu-item.d.ts.map +1 -1
- package/dist/components/Menu/menu-item.js.map +1 -1
- package/dist/components/Notice/notice.d.ts +5 -1
- package/dist/components/Notice/notice.d.ts.map +1 -1
- package/dist/components/Notice/notice.js +2 -1
- package/dist/components/Notice/notice.js.map +1 -1
- package/dist/components/OverflowIndicator/overflow-indicator.d.ts +4 -0
- package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
- package/dist/components/OverflowIndicator/overflow-indicator.js +2 -2
- package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
- package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
- package/dist/components/PeoplePicker/people-picker.js +6 -2
- package/dist/components/PeoplePicker/people-picker.js.map +1 -1
- package/dist/components/Popover/popover.d.ts +1 -1
- package/dist/components/Popover/popover.js +2 -1
- package/dist/components/Popover/popover.js.map +1 -1
- package/dist/components/ProfileCard/profile-card.d.ts +9 -4
- package/dist/components/ProfileCard/profile-card.d.ts.map +1 -1
- package/dist/components/ProfileCard/profile-card.js.map +1 -1
- package/dist/components/RadioGroup/radio-group.d.ts +6 -0
- package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
- package/dist/components/RadioGroup/radio-group.js +4 -0
- package/dist/components/RadioGroup/radio-group.js.map +1 -1
- package/dist/components/ScrollArea/scroll-area.js +1 -1
- package/dist/components/ScrollArea/scroll-area.js.map +1 -1
- package/dist/components/Select/select.d.ts.map +1 -1
- package/dist/components/Select/select.js +14 -4
- package/dist/components/Select/select.js.map +1 -1
- package/dist/components/SelectMenu/select-menu.d.ts +4 -0
- package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
- package/dist/components/SelectMenu/select-menu.js +6 -3
- package/dist/components/SelectMenu/select-menu.js.map +1 -1
- package/dist/components/SelectionControl/selection-item.d.ts +5 -1
- package/dist/components/SelectionControl/selection-item.d.ts.map +1 -1
- package/dist/components/SelectionControl/selection-item.js +3 -1
- package/dist/components/SelectionControl/selection-item.js.map +1 -1
- package/dist/components/Sheet/sheet.d.ts +6 -5
- package/dist/components/Sheet/sheet.d.ts.map +1 -1
- package/dist/components/Sheet/sheet.js.map +1 -1
- package/dist/components/Sidebar/sidebar.d.ts +1 -1
- package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
- package/dist/components/Sidebar/sidebar.js +3 -2
- package/dist/components/Sidebar/sidebar.js.map +1 -1
- package/dist/components/Skeleton/skeleton.d.ts +1 -1
- package/dist/components/Skeleton/skeleton.js +2 -1
- package/dist/components/Skeleton/skeleton.js.map +1 -1
- package/dist/components/Slider/slider.d.ts +1 -1
- package/dist/components/Slider/slider.d.ts.map +1 -1
- package/dist/components/Slider/slider.js +7 -3
- package/dist/components/Slider/slider.js.map +1 -1
- package/dist/components/Steps/steps.d.ts +1 -1
- package/dist/components/Steps/steps.d.ts.map +1 -1
- package/dist/components/Steps/steps.js +9 -6
- package/dist/components/Steps/steps.js.map +1 -1
- package/dist/components/Switch/switch.d.ts +5 -5
- package/dist/components/Switch/switch.js +3 -3
- package/dist/components/Switch/switch.js.map +1 -1
- package/dist/components/Tabs/tabs.js +1 -1
- package/dist/components/Tabs/tabs.js.map +1 -1
- package/dist/components/Textarea/textarea.js +1 -1
- package/dist/components/Textarea/textarea.js.map +1 -1
- package/dist/components/TimePicker/time-columns.js +1 -1
- 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 +2 -1
- package/dist/components/TimePicker/time-picker.js.map +1 -1
- package/dist/components/Toast/toast.js.map +1 -1
- package/dist/components/Tooltip/tooltip.d.ts +1 -1
- package/dist/components/Tooltip/tooltip.js +2 -1
- package/dist/components/Tooltip/tooltip.js.map +1 -1
- package/dist/components/TreeView/tree-view.d.ts +4 -4
- package/dist/components/TreeView/tree-view.d.ts.map +1 -1
- package/dist/components/TreeView/tree-view.js +3 -3
- package/dist/components/TreeView/tree-view.js.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.d.ts +3 -3
- package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
- package/dist/patterns/header-canonical/chrome-header.d.ts +3 -2
- package/dist/patterns/header-canonical/chrome-header.d.ts.map +1 -1
- package/dist/patterns/header-canonical/chrome-header.js.map +1 -1
- package/dist/patterns/overlay-surface/overlay-surface.d.ts +3 -2
- package/dist/patterns/overlay-surface/overlay-surface.d.ts.map +1 -1
- package/dist/patterns/overlay-surface/overlay-surface.js.map +1 -1
- package/ds-canonical/hooks/_log-fire.sh +3 -1
- package/ds-canonical/hooks/check_audit_post_report_validator.sh +21 -1
- package/ds-canonical/hooks/check_audit_sample_escape.sh +6 -3
- package/ds-canonical/hooks/check_chrome_header_avatar_canonical.sh +8 -0
- package/ds-canonical/hooks/check_consumer_app_invariants.sh +321 -0
- package/ds-canonical/hooks/check_datatable_invariants.sh +75 -12
- package/ds-canonical/hooks/check_escape_marker_abuse.sh +15 -1
- package/ds-canonical/hooks/check_field_family_invariants.sh +12 -2
- package/ds-canonical/hooks/check_plugin_fork_health.sh +137 -0
- package/ds-canonical/hooks/check_propose_discipline.sh +147 -0
- package/ds-canonical/hooks/check_solo_workflow.sh +11 -1
- package/ds-canonical/hooks/check_story_invariants.sh +63 -9
- package/ds-canonical/hooks/check_storybook_addon_packaging.sh +151 -0
- package/ds-canonical/hooks/check_tailwind_wildcard_in_docs.sh +8 -2
- package/ds-canonical/hooks/lib/_overlay_handcraft.sh +25 -4
- package/ds-canonical/hooks/lib/_token_hygiene.sh +9 -1
- package/ds-canonical/hooks/session_start_governance_check.sh +7 -2
- package/ds-canonical/hooks/stop_self_audit.sh +2 -2
- package/ds-canonical/hooks/tests/test_check_addon_subdir_ship.sh +3 -2
- package/ds-canonical/hooks/tests/test_check_consumer_app_invariants.sh +12 -0
- package/ds-canonical/hooks/tests/test_check_consumer_app_story_title.sh +3 -2
- package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +6 -4
- package/ds-canonical/hooks/tests/test_check_consumer_no_ds_catalog.sh +7 -4
- package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +6 -4
- package/ds-canonical/hooks/tests/test_check_data_table_size_num_to_meta_width.sh +3 -2
- package/ds-canonical/hooks/tests/test_check_fork_user_plugin_install.sh +3 -2
- package/ds-canonical/hooks/tests/test_check_plugin_fork_health.sh +9 -0
- package/ds-canonical/hooks/tests/test_check_propose_cite_required.sh +3 -2
- package/ds-canonical/hooks/tests/test_check_propose_discipline.sh +10 -0
- package/ds-canonical/hooks/tests/test_check_propose_plain_chinese.sh +3 -2
- package/ds-canonical/hooks/tests/test_check_storybook_addon_packaging.sh +10 -0
- package/ds-canonical/hooks/tests/test_check_storybook_addon_preset_cjs.sh +3 -2
- package/ds-canonical/references/build-ui-canonicals.md +2 -2
- package/ds-canonical/references/composition-fidelity.md +3 -3
- package/ds-canonical/references/naming-conventions.md +1 -0
- package/ds-canonical/references/ssot-consultation.md +1 -1
- package/ds-canonical/references/ssot-index.md +7 -7
- package/ds-canonical/rules/meta-patterns.md +5 -5
- package/ds-canonical/rules/self-verify.md +1 -1
- package/ds-canonical/rules/story-rules.md +2 -0
- package/ds-canonical/rules/ui-development.md +1 -1
- package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +11 -2
- package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +1 -1
- package/ds-canonical/skills/design-system-audit/SKILL.md +15 -15
- package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +4 -3
- package/ds-story-manifest.json +15 -21
- package/llms-full.txt +9 -5
- package/llms.txt +2 -2
- package/package.json +1 -1
- package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
- package/src/components/Accordion/accordion.spec.md +22 -5
- package/src/components/Accordion/accordion.tsx +1 -1
- package/src/components/Alert/alert.anatomy.stories.tsx +4 -4
- package/src/components/Alert/alert.principles.stories.tsx +5 -5
- package/src/components/Alert/alert.spec.md +16 -11
- package/src/components/Alert/alert.stories.tsx +5 -5
- package/src/components/Alert/alert.tsx +2 -2
- package/src/components/AppShell/app-shell.principles.stories.tsx +68 -21
- package/src/components/AppShell/app-shell.spec.md +17 -24
- package/src/components/AppShell/app-shell.tsx +4 -3
- package/src/components/AspectRatio/aspect-ratio.anatomy.stories.tsx +3 -3
- package/src/components/AspectRatio/aspect-ratio.spec.md +15 -1
- package/src/components/Avatar/avatar.anatomy.stories.tsx +1 -1
- package/src/components/Avatar/avatar.principles.stories.tsx +8 -8
- package/src/components/Avatar/avatar.spec.md +25 -54
- package/src/components/Avatar/avatar.tsx +2 -2
- package/src/components/Badge/badge.principles.stories.tsx +2 -2
- package/src/components/Badge/badge.spec.md +22 -13
- package/src/components/Badge/badge.tsx +1 -1
- package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +5 -2
- package/src/components/Breadcrumb/breadcrumb.spec.md +25 -25
- package/src/components/Breadcrumb/breadcrumb.stories.tsx +7 -32
- package/src/components/Breadcrumb/breadcrumb.tsx +1 -1
- package/src/components/BulkActionBar/bulk-action-bar.principles.stories.tsx +2 -2
- package/src/components/BulkActionBar/bulk-action-bar.spec.md +20 -6
- package/src/components/BulkActionBar/bulk-action-bar.tsx +2 -2
- package/src/components/Button/button.anatomy.stories.tsx +2 -2
- package/src/components/Button/button.spec.md +19 -17
- package/src/components/Button/button.stories.tsx +1 -1
- package/src/components/Button/button.tsx +10 -9
- package/src/components/Calendar/calendar.anatomy.stories.tsx +1 -1
- package/src/components/Calendar/calendar.spec.md +37 -17
- package/src/components/Calendar/calendar.tsx +26 -22
- package/src/components/Carousel/carousel.anatomy.stories.tsx +6 -6
- package/src/components/Carousel/carousel.principles.stories.tsx +1 -1
- package/src/components/Carousel/carousel.spec.md +23 -3
- package/src/components/Carousel/carousel.tsx +19 -4
- package/src/components/Chart/chart.anatomy.stories.tsx +1 -1
- package/src/components/Chart/chart.spec.md +20 -1
- package/src/components/Checkbox/checkbox-group.tsx +2 -1
- package/src/components/Checkbox/checkbox.anatomy.stories.tsx +4 -4
- package/src/components/Checkbox/checkbox.principles.stories.tsx +2 -2
- package/src/components/Checkbox/checkbox.spec.md +35 -15
- package/src/components/Checkbox/checkbox.stories.tsx +1 -1
- package/src/components/Checkbox/checkbox.tsx +14 -3
- package/src/components/Chip/chip.anatomy.stories.tsx +5 -5
- package/src/components/Chip/chip.principles.stories.tsx +9 -3
- package/src/components/Chip/chip.spec.md +8 -9
- package/src/components/Chip/chip.tsx +2 -2
- package/src/components/CircularProgress/circular-progress.anatomy.stories.tsx +6 -6
- package/src/components/CircularProgress/circular-progress.spec.md +10 -11
- package/src/components/CircularProgress/circular-progress.stories.tsx +36 -43
- package/src/components/CircularProgress/circular-progress.tsx +1 -1
- package/src/components/Coachmark/coachmark.anatomy.stories.tsx +1 -1
- package/src/components/Coachmark/coachmark.principles.stories.tsx +14 -29
- package/src/components/Coachmark/coachmark.spec.md +21 -13
- package/src/components/Coachmark/coachmark.tsx +4 -4
- package/src/components/Combobox/combobox.anatomy.stories.tsx +28 -28
- package/src/components/Combobox/combobox.principles.stories.tsx +1 -1
- package/src/components/Combobox/combobox.spec.md +25 -7
- package/src/components/Combobox/combobox.tsx +12 -3
- package/src/components/Command/command.anatomy.stories.tsx +1 -1
- package/src/components/Command/command.principles.stories.tsx +8 -8
- package/src/components/Command/command.spec.md +18 -8
- package/src/components/Command/command.tsx +8 -3
- package/src/components/DataTable/data-table-sort-manager.tsx +1 -1
- package/src/components/DataTable/data-table.anatomy.stories.tsx +9 -7
- package/src/components/DataTable/data-table.principles.stories.tsx +3 -3
- package/src/components/DataTable/data-table.spec.md +15 -11
- package/src/components/DataTable/data-table.stories.tsx +58 -13
- package/src/components/DataTable/data-table.tsx +13 -0
- package/src/components/DataTable/filter-operators.spec.md +19 -27
- package/src/components/DateGrid/date-grid.anatomy.stories.tsx +8 -8
- package/src/components/DateGrid/date-grid.principles.stories.tsx +7 -7
- package/src/components/DateGrid/date-grid.spec.md +17 -14
- package/src/components/DateGrid/date-grid.tsx +8 -4
- package/src/components/DatePicker/date-picker.anatomy.stories.tsx +11 -15
- package/src/components/DatePicker/date-picker.principles.stories.tsx +8 -8
- package/src/components/DatePicker/date-picker.spec.md +40 -36
- package/src/components/DatePicker/date-picker.stories.tsx +23 -53
- package/src/components/DatePicker/date-picker.tsx +12 -6
- package/src/components/DescriptionList/description-list.anatomy.stories.tsx +2 -2
- package/src/components/DescriptionList/description-list.principles.stories.tsx +4 -18
- package/src/components/DescriptionList/description-list.spec.md +9 -3
- package/src/components/DescriptionList/description-list.stories.tsx +2 -18
- package/src/components/DescriptionList/description-list.tsx +1 -1
- package/src/components/Dialog/dialog.principles.stories.tsx +1 -1
- package/src/components/Dialog/dialog.spec.md +26 -11
- package/src/components/Dialog/dialog.stories.tsx +159 -184
- package/src/components/Dialog/dialog.tsx +2 -1
- package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +2 -2
- package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +16 -17
- package/src/components/DropdownMenu/dropdown-menu.spec.md +10 -15
- package/src/components/DropdownMenu/dropdown-menu.stories.tsx +13 -15
- package/src/components/DropdownMenu/dropdown-menu.tsx +12 -2
- package/src/components/Empty/empty.spec.md +19 -18
- package/src/components/Empty/empty.tsx +1 -1
- package/src/components/Field/field-controls.spec.md +52 -41
- package/src/components/Field/field-wrapper.tsx +2 -2
- package/src/components/Field/field.anatomy.stories.tsx +6 -5
- package/src/components/Field/field.principles.stories.tsx +8 -7
- package/src/components/Field/field.spec.md +42 -20
- package/src/components/Field/field.stories.tsx +9 -7
- package/src/components/Field/field.tsx +6 -3
- package/src/components/Field/form-validation.spec.md +20 -19
- package/src/components/FieldControlGroup/field-control-group.anatomy.stories.tsx +16 -15
- package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +5 -1
- package/src/components/FieldControlGroup/field-control-group.spec.md +17 -1
- package/src/components/FieldControlGroup/field-control-group.stories.tsx +9 -9
- package/src/components/FieldControlGroup/field-control-group.tsx +4 -3
- package/src/components/FileItem/file-item.anatomy.stories.tsx +7 -17
- package/src/components/FileItem/file-item.principles.stories.tsx +7 -7
- package/src/components/FileItem/file-item.spec.md +24 -24
- package/src/components/FileUpload/file-upload.anatomy.stories.tsx +4 -2
- package/src/components/FileUpload/file-upload.principles.stories.tsx +10 -12
- package/src/components/FileUpload/file-upload.spec.md +37 -8
- package/src/components/FileUpload/file-upload.tsx +5 -3
- package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +16 -11
- package/src/components/FileViewer/file-viewer.principles.stories.tsx +4 -4
- package/src/components/FileViewer/file-viewer.spec.md +7 -19
- package/src/components/FileViewer/file-viewer.stories.tsx +3 -3
- package/src/components/FileViewer/file-viewer.tsx +42 -16
- package/src/components/HoverCard/hover-card.spec.md +20 -10
- package/src/components/HoverCard/hover-card.stories.tsx +1 -1
- package/src/components/HoverCard/hover-card.tsx +12 -1
- package/src/components/Input/input.anatomy.stories.tsx +4 -4
- package/src/components/Input/input.principles.stories.tsx +4 -31
- package/src/components/Input/input.spec.md +16 -4
- 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.spec.md +14 -1
- package/src/components/Menu/menu-item.principles.stories.tsx +5 -5
- package/src/components/Menu/menu-item.spec.md +24 -12
- package/src/components/Menu/menu-item.tsx +7 -3
- package/src/components/Notice/notice.principles.stories.tsx +7 -7
- package/src/components/Notice/notice.spec.md +7 -5
- package/src/components/Notice/notice.tsx +5 -1
- package/src/components/NumberInput/number-input.anatomy.stories.tsx +4 -4
- package/src/components/NumberInput/number-input.principles.stories.tsx +13 -35
- package/src/components/NumberInput/number-input.spec.md +19 -0
- package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +4 -3
- package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +2 -5
- package/src/components/OverflowIndicator/overflow-indicator.spec.md +9 -1
- package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +6 -42
- package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -3
- package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +11 -2
- package/src/components/PeoplePicker/people-picker.spec.md +26 -12
- package/src/components/PeoplePicker/people-picker.stories.tsx +14 -15
- package/src/components/PeoplePicker/people-picker.tsx +12 -4
- package/src/components/Popover/popover.spec.md +20 -11
- package/src/components/Popover/popover.tsx +2 -2
- package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +1 -1
- package/src/components/ProfileCard/profile-card.principles.stories.tsx +29 -25
- package/src/components/ProfileCard/profile-card.spec.md +30 -10
- package/src/components/ProfileCard/profile-card.tsx +12 -7
- package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +1 -1
- package/src/components/ProgressBar/progress-bar.principles.stories.tsx +7 -5
- package/src/components/ProgressBar/progress-bar.spec.md +9 -1
- package/src/components/ProgressBar/progress-bar.stories.tsx +1 -1
- package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +6 -3
- package/src/components/RadioGroup/radio-group.principles.stories.tsx +6 -13
- package/src/components/RadioGroup/radio-group.spec.md +7 -1
- package/src/components/RadioGroup/radio-group.tsx +10 -0
- package/src/components/Rating/rating.anatomy.stories.tsx +1 -0
- package/src/components/Rating/rating.principles.stories.tsx +9 -6
- package/src/components/Rating/rating.spec.md +13 -7
- package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +44 -24
- package/src/components/ScrollArea/scroll-area.principles.stories.tsx +51 -57
- package/src/components/ScrollArea/scroll-area.spec.md +5 -7
- package/src/components/ScrollArea/scroll-area.stories.tsx +110 -60
- package/src/components/ScrollArea/scroll-area.tsx +1 -1
- package/src/components/SegmentedControl/segmented-control.anatomy.stories.tsx +1 -1
- package/src/components/SegmentedControl/segmented-control.spec.md +15 -14
- package/src/components/SegmentedControl/segmented-control.stories.tsx +1 -1
- package/src/components/Select/select.anatomy.stories.tsx +12 -11
- package/src/components/Select/select.principles.stories.tsx +3 -3
- package/src/components/Select/select.spec.md +34 -8
- package/src/components/Select/select.stories.tsx +2 -2
- package/src/components/Select/select.tsx +18 -3
- package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +2 -2
- package/src/components/SelectMenu/select-menu.principles.stories.tsx +5 -5
- package/src/components/SelectMenu/select-menu.spec.md +19 -12
- package/src/components/SelectMenu/select-menu.stories.tsx +34 -27
- package/src/components/SelectMenu/select-menu.tsx +14 -3
- package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +1 -1
- package/src/components/SelectionControl/selection-item.spec.md +13 -2
- package/src/components/SelectionControl/selection-item.stories.tsx +1 -1
- package/src/components/SelectionControl/selection-item.tsx +8 -2
- package/src/components/Separator/separator.principles.stories.tsx +2 -2
- package/src/components/Separator/separator.spec.md +11 -5
- package/src/components/Sheet/sheet.anatomy.stories.tsx +7 -6
- package/src/components/Sheet/sheet.principles.stories.tsx +18 -38
- package/src/components/Sheet/sheet.spec.md +9 -11
- package/src/components/Sheet/sheet.stories.tsx +2 -2
- package/src/components/Sheet/sheet.tsx +6 -5
- package/src/components/Sidebar/sidebar.anatomy.stories.tsx +42 -33
- package/src/components/Sidebar/sidebar.principles.stories.tsx +4 -4
- package/src/components/Sidebar/sidebar.spec.md +22 -17
- package/src/components/Sidebar/sidebar.stories.tsx +16 -0
- package/src/components/Sidebar/sidebar.tsx +15 -7
- package/src/components/Skeleton/skeleton.anatomy.stories.tsx +2 -2
- package/src/components/Skeleton/skeleton.principles.stories.tsx +20 -7
- package/src/components/Skeleton/skeleton.spec.md +6 -4
- package/src/components/Skeleton/skeleton.stories.tsx +34 -26
- package/src/components/Skeleton/skeleton.tsx +1 -1
- package/src/components/Slider/slider.principles.stories.tsx +3 -3
- package/src/components/Slider/slider.spec.md +16 -12
- package/src/components/Slider/slider.stories.tsx +2 -18
- package/src/components/Slider/slider.tsx +6 -2
- package/src/components/Steps/steps.anatomy.stories.tsx +3 -3
- package/src/components/Steps/steps.principles.stories.tsx +9 -12
- package/src/components/Steps/steps.spec.md +31 -25
- package/src/components/Steps/steps.stories.tsx +5 -40
- package/src/components/Steps/steps.tsx +17 -12
- package/src/components/Switch/switch.principles.stories.tsx +1 -1
- package/src/components/Switch/switch.spec.md +13 -0
- package/src/components/Switch/switch.tsx +3 -3
- package/src/components/Tabs/tabs.anatomy.stories.tsx +4 -4
- package/src/components/Tabs/tabs.principles.stories.tsx +1 -1
- package/src/components/Tabs/tabs.spec.md +13 -6
- package/src/components/Tabs/tabs.stories.tsx +3 -3
- package/src/components/Tabs/tabs.tsx +2 -2
- package/src/components/Tag/tag.anatomy.stories.tsx +15 -15
- package/src/components/Tag/tag.principles.stories.tsx +1 -1
- package/src/components/Tag/tag.spec.md +25 -5
- package/src/components/Textarea/textarea.anatomy.stories.tsx +3 -3
- package/src/components/Textarea/textarea.principles.stories.tsx +7 -7
- package/src/components/Textarea/textarea.spec.md +15 -3
- package/src/components/Textarea/textarea.tsx +1 -1
- package/src/components/TimePicker/time-columns.tsx +1 -1
- package/src/components/TimePicker/time-picker.anatomy.stories.tsx +8 -2
- package/src/components/TimePicker/time-picker.spec.md +23 -3
- package/src/components/TimePicker/time-picker.tsx +5 -3
- package/src/components/Toast/toast.anatomy.stories.tsx +1 -1
- package/src/components/Toast/toast.spec.md +7 -4
- package/src/components/Toast/toast.stories.tsx +12 -6
- package/src/components/Toast/toast.tsx +1 -1
- package/src/components/Tooltip/tooltip.anatomy.stories.tsx +1 -1
- package/src/components/Tooltip/tooltip.spec.md +11 -8
- package/src/components/Tooltip/tooltip.tsx +1 -1
- package/src/components/TreeView/tree-view.anatomy.stories.tsx +25 -9
- package/src/components/TreeView/tree-view.principles.stories.tsx +5 -5
- package/src/components/TreeView/tree-view.spec.md +11 -9
- package/src/components/TreeView/tree-view.stories.tsx +5 -3
- package/src/components/TreeView/tree-view.tsx +8 -5
- package/src/patterns/action-bar/action-bar.spec.md +11 -4
- package/src/patterns/element-anatomy/element-anatomy.spec.md +8 -6
- package/src/patterns/element-anatomy/inline-action.spec.md +18 -18
- package/src/patterns/element-anatomy/item-anatomy.spec.md +47 -42
- package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -6
- package/src/patterns/element-anatomy/item-anatomy.tsx +3 -3
- package/src/patterns/header-canonical/chrome-header.tsx +3 -2
- package/src/patterns/header-canonical/header-canonical.spec.md +24 -11
- package/src/patterns/header-canonical/header-canonical.stories.tsx +9 -9
- package/src/patterns/horizontal-overflow/horizontal-overflow.spec.md +22 -12
- package/src/patterns/overlay-surface/overlay-surface.spec.md +43 -39
- package/src/patterns/overlay-surface/overlay-surface.tsx +3 -2
- package/src/patterns/resize-handle/resize-handle.spec.md +10 -1
- package/src/patterns/resize-handle/resize-handle.stories.tsx +7 -7
- package/src/tokens/README.md +5 -2
- package/src/tokens/color/color.spec.md +17 -10
- package/src/tokens/color/semantic.css +2 -0
- package/src/tokens/density/density.spec.md +4 -14
- package/src/tokens/elevation/elevation.spec.md +7 -8
- package/src/tokens/layoutSpace/layoutSpace.spec.md +20 -27
- package/src/tokens/motion/motion.spec.md +15 -7
- package/src/tokens/opacity/opacity.spec.md +15 -26
- package/src/tokens/orphan-tokens.spec.md +14 -3
- package/src/tokens/radius/radius.spec.md +13 -15
- package/src/tokens/token-system.spec.md +10 -13
- package/src/tokens/typography/typography.spec.md +8 -12
- package/src/tokens/uiSize/uiSize.spec.md +28 -16
- /package/ds-canonical/hooks/{check_addon_subdir_ship.sh → retired/2026-06-11-prune-merge/check_addon_subdir_ship.sh} +0 -0
- /package/ds-canonical/hooks/{check_consumer_app_story_title.sh → retired/2026-06-11-prune-merge/check_consumer_app_story_title.sh} +0 -0
- /package/ds-canonical/hooks/{check_consumer_ds_primitive_misuse.sh → retired/2026-06-11-prune-merge/check_consumer_ds_primitive_misuse.sh} +0 -0
- /package/ds-canonical/hooks/{check_consumer_no_ds_catalog.sh → retired/2026-06-11-prune-merge/check_consumer_no_ds_catalog.sh} +0 -0
- /package/ds-canonical/hooks/{check_consumer_story_baseline.sh → retired/2026-06-11-prune-merge/check_consumer_story_baseline.sh} +0 -0
- /package/ds-canonical/hooks/{check_data_table_size_num_to_meta_width.sh → retired/2026-06-11-prune-merge/check_data_table_size_num_to_meta_width.sh} +0 -0
- /package/ds-canonical/hooks/{check_fork_user_plugin_install.sh → retired/2026-06-11-prune-merge/check_fork_user_plugin_install.sh} +0 -0
- /package/ds-canonical/hooks/{check_plugin_freshness.sh → retired/2026-06-11-prune-merge/check_plugin_freshness.sh} +0 -0
- /package/ds-canonical/hooks/{check_propose_cite_required.sh → retired/2026-06-11-prune-merge/check_propose_cite_required.sh} +0 -0
- /package/ds-canonical/hooks/{check_propose_plain_chinese.sh → retired/2026-06-11-prune-merge/check_propose_plain_chinese.sh} +0 -0
- /package/ds-canonical/hooks/{check_storybook_addon_preset_cjs.sh → retired/2026-06-11-prune-merge/check_storybook_addon_preset_cjs.sh} +0 -0
|
@@ -29,9 +29,9 @@ TanStack Table 負責邏輯,DataTable 負責視覺與互動。
|
|
|
29
29
|
|
|
30
30
|
**Layout Family**:非上述 family — composite / multi-section(多區塊組合,自 own layout)。
|
|
31
31
|
|
|
32
|
-
### 檔案結構
|
|
32
|
+
### 檔案結構
|
|
33
33
|
|
|
34
|
-
12 file
|
|
34
|
+
檔案拆分架構(12 file split matrix)與工程決策史屬 code home — 詳 `data-table.tsx` 檔頭 docblock(2026-06-11 遷移,Level 4;spec 只管設計語言)。
|
|
35
35
|
|
|
36
36
|
---
|
|
37
37
|
|
|
@@ -64,7 +64,7 @@ TanStack Table 負責邏輯,DataTable 負責視覺與互動。
|
|
|
64
64
|
|------|------|------|
|
|
65
65
|
| **L1 基礎結構** | 骨架、尺寸、border、色彩、高度模式、行高模式 | ✅ 完成(本文件 L1 段)|
|
|
66
66
|
| **L2 選取** | row selection、checkbox、單/多選、bulk action 整合 | ✅ 完成(本文件 L2 段)|
|
|
67
|
-
| **L3 欄位互動** | 排序(本文件 L3)、resize、reorder、pin、顯示隱藏 | ✅ 完成(sort + resize + reorder + pin + visibility 全 props 支援:`enableColumnResize` / `enableColumnReorder` / `columnVisibility` / `pinnedLeftColumns` / `pinnedRightColumns`,見 data-table.tsx
|
|
67
|
+
| **L3 欄位互動** | 排序(本文件 L3)、resize、reorder、pin、顯示隱藏 | ✅ 完成(sort + resize + reorder + pin + visibility 全 props 支援:`enableColumnResize` / `enableColumnReorder` / `columnVisibility` / `pinnedLeftColumns` / `pinnedRightColumns`,見 `data-table.tsx` `DataTableProps` 宣告)|
|
|
68
68
|
| **L4 資料操作 + Cell 能力** | 進階篩選(本文件 L4 Filter)、inline edit、nested rows、row drag(本文件 L4 段)| ✅ Filter / Inline edit / Nested rows / Row drag v3 完成(Jira canonical + virtualization fix) |
|
|
69
69
|
| **L5 進階** | 分組、搜尋、tree data v2 enhancements、export CSV/Excel | 待 v2 |
|
|
70
70
|
|
|
@@ -105,17 +105,17 @@ Table 分三層:
|
|
|
105
105
|
|
|
106
106
|
完整 class / overflow 規則見 `data-table.tsx`。
|
|
107
107
|
|
|
108
|
-
**Header 在 scroll 容器外面。** 不用 CSS sticky——header 結構性地在 body 上方,永遠固定在頂部。Header bg 用 `
|
|
108
|
+
**Header 在 scroll 容器外面。** 不用 CSS sticky——header 結構性地在 body 上方,永遠固定在頂部。Header bg 用 `--muted`(code `HEADER_BG = 'bg-muted'`,比 surface 深一階,同 anatomy ColorMatrix)。
|
|
109
109
|
|
|
110
110
|
**三個 region 共享垂直捲動。** body-viewport 是唯一的垂直 scroll container,三個 body region 是它的 flex children。垂直捲動天然同步,不需 JS。
|
|
111
111
|
|
|
112
|
-
**只有 center 水平捲動。** center-body
|
|
112
|
+
**只有 center 水平捲動。** center-body 是唯一的水平 scroll container,center-header 跟隨其捲動位置同步(同步機制見「捲軸」段 + `data-table.tsx`)。
|
|
113
113
|
|
|
114
|
-
**Left / right 不水平捲動。**
|
|
114
|
+
**Left / right 不水平捲動。** Frozen 邊界用 `border-divider`(全高度)。
|
|
115
115
|
|
|
116
116
|
**固定行高確保跨 region 對齊。** 所有 row 用 `h-table-row-{size}`,三個 region 的 row 精確同高。
|
|
117
117
|
|
|
118
|
-
**Header/body region 寬度同步。** Header region 寬度由內容決定(columns + actions),body region
|
|
118
|
+
**Header/body region 寬度同步。** Header region 寬度由內容決定(columns + actions),body region 量測 header 寬度同步(機制見 `data-table.tsx`)。
|
|
119
119
|
|
|
120
120
|
### 四、行高模式
|
|
121
121
|
|
|
@@ -173,10 +173,12 @@ Row actions 欄本質上是 frozen right column,左邊界也使用 full-height
|
|
|
173
173
|
| Case | Story | Avg / p95 / long-task | Gate |
|
|
174
174
|
|---|---|---|---|
|
|
175
175
|
| A Plain virt | `VirtualScroll` | ≤16.67/≤33/0 | hard |
|
|
176
|
-
| B Rich budget | `RoadmapPerfBudget`(500×13 rich+inline-edit,fixed 600px) | ≤50/≤80/≤1 | hard |
|
|
176
|
+
| B Rich budget | `RoadmapPerfBudget`(500×13 rich+inline-edit,fixed 600px;2026-05-17 整併誤 retire → 2026-06-12 R2 重建,gate 恢復可跑) | ≤50/≤80/≤1 | hard |
|
|
177
177
|
| C Row drag | `RowDragWithVirtualization` | ≤33/≤50/longest<100 | soft(DnD thermal) |
|
|
178
178
|
| D Edit isolation | `<Profiler>` TBD | skip ≥ visible−active | hard |
|
|
179
179
|
|
|
180
|
+
**2026-06-12 重建後實測**(static build,3 runs/case):1x CPU — A 16.56/16.8/0、B 24.0/33.4/0、C 16.67/16.8/0 全過 gate;script 預設 4x throttle 在有背景負載機器上全 case 一致 ~2.3x 超標(含未動過的對照組 A)→ 本表門檻實證對應 1x/閒置條件,4x 門檻是否重校 = user 決策(本表數字不動)。
|
|
181
|
+
|
|
180
182
|
**Anti-pattern**:`RoadmapAllInOne`(全 features stack)≈117ms 不達 B,因 SortableRowProvider/column reorder/resize/selection/overlay 同時開。Consumer:13+ cols rich-cell → 拆 detail drawer / column visibility 預設 hide,不該期 60fps + 全 feature stack。Cite + Phase 1/2 history → `cell-registry.tsx:480-499` JSDoc + commits log。
|
|
181
183
|
|
|
182
184
|
### 七、Column Type
|
|
@@ -446,7 +448,7 @@ Row drag + column reorder + TreeView 共用 `lib/drag-visual.ts`:source `opacity
|
|
|
446
448
|
|
|
447
449
|
`enableRowDrag?: boolean` + `onRowReorder?: (sourceId, targetId, 'before' | 'after')`。Library:@dnd-kit/core(v15.0 Path B 用 `useDraggable` + `useDroppable`,不用 `@dnd-kit/sortable`)。**必填 `getRowId`**(否則 dnd 用 row.index reorder 後錯位)。
|
|
448
450
|
|
|
449
|
-
- **Handle
|
|
451
|
+
- **Handle**:Button tertiary iconOnly xs(GripVertical)24px chip,所有 state(idle / hover / aria-disabled)統一 `bg-surface-raised`(border / shadow 已 retire,2026-05-12 per user「我有叫你加 elevation 嗎」),fixed-position 浮層貼 row 左緣、不佔 column 空間(位置 JS 計算,實作見 `data-table.tsx`);**hover-reveal** 由 JS 控 visibility / opacity(row 或 handle hover 顯示;drag 中 source 強制顯示、其他列隱藏)。對齊 Jira backlog(@benchmark-unverified,M22)。Tertiary chip 非 ItemInlineAction 因透明背景撞 table border。
|
|
450
452
|
- **Sort × Drag 互斥**:sort.length>0 → handle disabled+Tooltip。**Top-level only**(`row.depth>0` 不顯 handle)。**Position**:active vs over 視覺位置 → `'after'`/`'before'` 對齊 `arrayMove`。**Consumer-managed mutation**:`onRowReorder(sourceId, targetId, position)`,DS 不持 row order(Notion/Airtable/Linear)。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
|
|
451
453
|
- **Virtualization 整合**(v3 2026-05-05):enableRowDrag 自動把 overscan 拉到 `Math.max(overscan, 5)` + drag 期 freeze `measureElement` + `modifiers={[snapToCursorModifier]}`(ghost top-left 對齊 cursor,不鎖軸)。**3-panel mirror sync**:各 region 對同 row id 各呼叫 `useDraggable` + `useDroppable`,mirror 自然取得相同 transform;handle 只 render primary region(left 優先 → center)避雙觸發。**Cross-parent drop 禁止**(已知 limit):nested 只同 top-level 重排,collisionDetection 過濾,顯 invalid signal。
|
|
452
454
|
|
|
@@ -517,12 +519,14 @@ DataTable 是 composite multi-section 元件,**不套 canonical 5**(Inspector /
|
|
|
517
519
|
|
|
518
520
|
**Why not radio-group**:之前 boilerplate 從 RadioGroup spec 誤抄。DataTable 是 multi-row / multi-column composite,not single-choice selection group;a11y semantics 完全不同(grid vs radio-group)。 <!-- @benchmark-verified: 2026-05-18 D1 rewrite -->
|
|
519
521
|
|
|
520
|
-
|
|
521
522
|
## 被引用(auto-maintained,Dim 3 reciprocal audit)
|
|
522
523
|
|
|
523
524
|
> 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
|
|
524
525
|
|
|
526
|
+
- `bulk-action-bar.spec.md`
|
|
525
527
|
- `carousel.spec.md`
|
|
526
528
|
- `circular-progress.spec.md`
|
|
529
|
+
- `description-list.spec.md`
|
|
530
|
+
- `opacity.spec.md`
|
|
527
531
|
- `scroll-area.spec.md`
|
|
528
|
-
- `
|
|
532
|
+
- `tree-view.spec.md`
|
|
@@ -163,7 +163,7 @@ export const ColumnResize: Story = {
|
|
|
163
163
|
/>
|
|
164
164
|
</div>
|
|
165
165
|
<div>
|
|
166
|
-
<h3 className="text-body font-bold text-foreground mb-2"
|
|
166
|
+
<h3 className="text-body font-bold text-foreground mb-2">欄位釘選與欄寬調整並存</h3>
|
|
167
167
|
<p className="text-caption text-fg-muted mb-3">
|
|
168
168
|
把 SKU 跟產品名稱固定在左側,依然可以拖動分隔線調整這兩欄的寬度。
|
|
169
169
|
<br />目前各欄寬度:{JSON.stringify(pinnedWidths)}
|
|
@@ -296,6 +296,7 @@ export const RowAutoHeight: Story = {
|
|
|
296
296
|
}
|
|
297
297
|
|
|
298
298
|
/* ── Empty State ── */
|
|
299
|
+
// 「預設空狀態」pane = 「自訂空狀態」的對照基線;Empty primitive 消費教學 canonical → anatomy.EmptyState,此處不重複教學
|
|
299
300
|
export const EmptyState: Story = {
|
|
300
301
|
name: '空狀態',
|
|
301
302
|
render: () => (
|
|
@@ -1390,11 +1391,11 @@ export const FilterPanelModified: Story = {
|
|
|
1390
1391
|
},
|
|
1391
1392
|
}
|
|
1392
1393
|
|
|
1393
|
-
/* ── 進階篩選 —
|
|
1394
|
+
/* ── 進階篩選 — 長標籤溢出 ── */
|
|
1394
1395
|
export const FilterPanelLongTagOverflow: Story = {
|
|
1395
1396
|
name: '進階篩選 — 長標籤溢出',
|
|
1396
1397
|
render: () => {
|
|
1397
|
-
//
|
|
1398
|
+
// 製造業 ERP 的產品分類名稱普遍很長 — 示範多選後 Combobox tag 溢出時的 +N 摘要收斂
|
|
1398
1399
|
const longLabelColumns = [
|
|
1399
1400
|
col.accessor('category', {
|
|
1400
1401
|
header: '類別',
|
|
@@ -1418,7 +1419,7 @@ export const FilterPanelLongTagOverflow: Story = {
|
|
|
1418
1419
|
}))
|
|
1419
1420
|
return (
|
|
1420
1421
|
<div className="w-full max-w-[680px]">
|
|
1421
|
-
<p className="text-caption text-fg-muted mb-3"
|
|
1422
|
+
<p className="text-caption text-fg-muted mb-3">產品分類名稱很長(製造業 ERP 常見)時,已選的多個標籤超出單行寬度,Combobox 自動收斂為 +N 摘要。</p>
|
|
1422
1423
|
<DataTableFilterPanel
|
|
1423
1424
|
mode="flat"
|
|
1424
1425
|
columns={[...longLabelColumns]}
|
|
@@ -1432,14 +1433,14 @@ export const FilterPanelLongTagOverflow: Story = {
|
|
|
1432
1433
|
|
|
1433
1434
|
/* ── 列拖曳重排(Jira-style + 3-panel pinned columns)──────────────────────
|
|
1434
1435
|
enableRowDrag + onRowReorder 整合範例(v3 Jira 設計準則):
|
|
1435
|
-
- handle
|
|
1436
|
+
- handle 浮在 row 左緣(fixed-position;Button tertiary iconOnly xs = elevated chip)
|
|
1436
1437
|
- 不佔 column 空間 — table 看起來乾淨,沒有預留拖曳欄位
|
|
1437
|
-
- hover row → handle 浮現(
|
|
1438
|
-
- 拖曳 row → @dnd-kit/
|
|
1438
|
+
- hover row → handle 浮現(JS 控 opacity)
|
|
1439
|
+
- 拖曳 row → @dnd-kit/core useDraggable + useDroppable(v15.0 Path B);放下 → onRowReorder(sourceId, targetId, 'before' | 'after')
|
|
1439
1440
|
- consumer 自管 data array mutation(同 Notion / Airtable / Linear pattern)
|
|
1440
1441
|
- sort 啟用時 drag handle 自動 disabled + Tooltip 解釋
|
|
1441
|
-
- pinned-left + pinned-right 同時存在 →
|
|
1442
|
-
|
|
1442
|
+
- pinned-left + pinned-right 同時存在 → source 留原位,2px drop indicator 跨三 region 同步標示落點
|
|
1443
|
+
(per-region useDraggable / useDroppable,不 auto-shift) */
|
|
1443
1444
|
export const RowDragInteractive: Story = {
|
|
1444
1445
|
name: '列拖曳重排(含釘選欄)',
|
|
1445
1446
|
render: () => {
|
|
@@ -1462,8 +1463,8 @@ export const RowDragInteractive: Story = {
|
|
|
1462
1463
|
<div className="flex flex-col gap-3 max-w-3xl">
|
|
1463
1464
|
<p className="text-caption text-fg-muted">
|
|
1464
1465
|
handle 浮在 row 左緣(不佔 column 空間,Jira 設計準則)。pinned-left(SKU)+ pinned-right(Updated)+
|
|
1465
|
-
center
|
|
1466
|
-
<code>
|
|
1466
|
+
center 中段欄。拖曳時 source 列留在原位(壓住視覺),2px 主色 drop indicator 跨三個 region
|
|
1467
|
+
同步標示落點(per-region <code>useDraggable</code> / <code>useDroppable</code>,不 auto-shift)。
|
|
1467
1468
|
</p>
|
|
1468
1469
|
<DataTable
|
|
1469
1470
|
columns={columnsWithPrice}
|
|
@@ -1510,8 +1511,8 @@ export const RowDragWithVirtualization: Story = {
|
|
|
1510
1511
|
return (
|
|
1511
1512
|
<div className="flex flex-col gap-3 max-w-3xl">
|
|
1512
1513
|
<p className="text-caption text-fg-muted">
|
|
1513
|
-
200 列 + 虛擬捲動。v3 修正:enableRowDrag 自動拉高 overscan ≥
|
|
1514
|
-
measureElement、
|
|
1514
|
+
200 列 + 虛擬捲動。v3 修正:enableRowDrag 自動拉高 overscan ≥ 5、drag 期間 freeze
|
|
1515
|
+
measureElement、snapToCursorModifier ghost 對齊游標(不鎖軸)— 拖曳 + 持續往下捲不再錯位。
|
|
1515
1516
|
</p>
|
|
1516
1517
|
<DataTable
|
|
1517
1518
|
columns={baseColumns}
|
|
@@ -1890,3 +1891,47 @@ export const RoadmapAllInOne: Story = {
|
|
|
1890
1891
|
}
|
|
1891
1892
|
},
|
|
1892
1893
|
}
|
|
1894
|
+
|
|
1895
|
+
/* ── Feature-split perf budget story(2026-05-14 codex perf debate verdict;2026-06-12 deep-audit
|
|
1896
|
+
R2 重建 — 2026-05-17 stories 整併批次誤 retire,但 spec「六之三」Case B hard gate +
|
|
1897
|
+
scripts/runtime-perf-datatable.mjs:20 仍指向本 story,gate 形同不可跑):──────────────────
|
|
1898
|
+
獨立 perf 量測 story — 同 Roadmap 13 cols rich-cell data(useRoadmapColumns SSOT),但**禁用**
|
|
1899
|
+
row drag / column reorder / column resize / selection / spreadsheet overlay,只保 inline edit
|
|
1900
|
+
display。目的:隔離 feature-stack 疊加 cost(SortableRowProvider / filter / sort / columnOrder
|
|
1901
|
+
state),驗證 rich cell 本體 scroll budget(avg ≤ 50ms / p95 ≤ 80ms / long-task ≤ 1,CPU 4x
|
|
1902
|
+
throttle)。**不動** RoadmapAllInOne demo IA(user 2026-05-10 directive 全合一)。
|
|
1903
|
+
重建版去掉原手刻說明 banner(px-loose + border-b border-divider = R9 chrome-header drift
|
|
1904
|
+
簽名,且量測 story 不需 chrome;說明留本註解)。 */
|
|
1905
|
+
export const RoadmapPerfBudget: Story = {
|
|
1906
|
+
name: '效能預算量測',
|
|
1907
|
+
parameters: { layout: 'fullscreen' },
|
|
1908
|
+
tags: ['!autodocs'],
|
|
1909
|
+
render: () => {
|
|
1910
|
+
const bigData = React.useMemo(() => {
|
|
1911
|
+
const arr: RoadmapItem[] = []
|
|
1912
|
+
for (let i = 0; i < 500; i++) {
|
|
1913
|
+
const base = ROADMAP_DATA[i % ROADMAP_DATA.length]
|
|
1914
|
+
const id = `RDM-${String(i + 100).padStart(3, '0')}`
|
|
1915
|
+
arr.push({ ...base, id, title: `${base.title} (#${i + 1})` })
|
|
1916
|
+
}
|
|
1917
|
+
return arr
|
|
1918
|
+
}, [])
|
|
1919
|
+
const [data, setData] = React.useState(bigData)
|
|
1920
|
+
const columns = useRoadmapColumns()
|
|
1921
|
+
const handleCommit = (rowId: string, colId: string, value: unknown) => {
|
|
1922
|
+
setData((prev) => prev.map((r) => (r.id === rowId ? { ...r, [colId]: value } : r)))
|
|
1923
|
+
}
|
|
1924
|
+
return (
|
|
1925
|
+
<div className="mx-[var(--layout-space-loose)] mb-[var(--layout-space-loose)]">
|
|
1926
|
+
<DataTable
|
|
1927
|
+
columns={columns}
|
|
1928
|
+
data={data}
|
|
1929
|
+
height="600px"
|
|
1930
|
+
inlineEdit
|
|
1931
|
+
getRowId={(row) => row.id}
|
|
1932
|
+
onCellCommit={handleCommit}
|
|
1933
|
+
/>
|
|
1934
|
+
</div>
|
|
1935
|
+
)
|
|
1936
|
+
},
|
|
1937
|
+
}
|
|
@@ -1,5 +1,17 @@
|
|
|
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
|
// code-quality-allow: file-size — foundational composite — 拆檔會複雜化 context / ref / state 同步
|
|
3
|
+
//
|
|
4
|
+
// ── 檔案結構(2026-05-03 split matrix;2026-06-11 自 data-table.spec.md 遷入,Level 4 code home)──
|
|
5
|
+
// 每個檔過 M21 / M17 / Rule-of-3 三 test:
|
|
6
|
+
// - data-table.tsx(主,foundational)
|
|
7
|
+
// - data-table-filter-panel.tsx + data-table-sort-manager.tsx + data-table-column-visibility-panel.tsx(panel state 隔離)
|
|
8
|
+
// - cell-registry.tsx(column type → cell display / edit 解析 SSOT)
|
|
9
|
+
// - data-table-interaction-layer.tsx + active-editor-controller.ts(spreadsheet overlay + portal editor)
|
|
10
|
+
// - column-types.ts + filter-operators.ts(✓ Rule-of-3 SSOT,3+ consumer)
|
|
11
|
+
// - filter-tree.ts(pure data + eval,test isolation)
|
|
12
|
+
// - lib/column-meta.ts(Internal SSOT,消 5 處 `(col as any)`)
|
|
13
|
+
// - + stories / spec / css
|
|
14
|
+
// M21 retract:filter-value-picker.tsx 1 consumer → 已 inline 回 panel。
|
|
3
15
|
import * as React from 'react'
|
|
4
16
|
import { createPortal } from 'react-dom'
|
|
5
17
|
import { Empty } from '@/design-system/components/Empty/empty'
|
|
@@ -56,6 +68,7 @@ type TableSize = 'sm' | 'md' | 'lg'
|
|
|
56
68
|
export interface DataTableProps<TData>
|
|
57
69
|
extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>,
|
|
58
70
|
VariantProps<typeof dataTableVariants> {
|
|
71
|
+
// any-allow: TanStack ColumnDef TValue idiom(per-column value 型別異質,官方範例同)— 對齊本 module 既有 escape 紀律
|
|
59
72
|
columns: ColumnDef<TData, any>[]
|
|
60
73
|
data: TData[]
|
|
61
74
|
size?: TableSize
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Advanced Filter
|
|
1
|
+
# Advanced Filter 設計原則(Operator × ColumnType × ValueShape SSOT,v3)
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> **狀態**:已落地 — registry 寫成 `filter-operators.ts`,`filter-tree.ts` + `data-table-filter-panel.tsx` 消費(原 draft 兩個升級條件皆已達成,2026-06-11 對齊)。
|
|
4
4
|
> **M8 benchmark**:對照 ClickUp(CU)/ Airtable(AT)/ Notion(NT)三家。**v3 加 datetime / includeTime + 砍 number.between(2/3 業界共識)**。
|
|
5
5
|
> **設計路線**:**ClickUp 為 baseline**,合理 + 不衝突 + 真實用的擴充採納。
|
|
6
6
|
> **檔位**:暫放 DataTable/,若決定抽 `patterns/advanced-filter/` 再搬。
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
- **砍 `number.between`**(9→8 ops)— Notion + Airtable 共識,同 field 重複 condition 可組合 `gte X AND lte Y`,無自然視覺也無業界 NumberRangeInput 元件
|
|
11
11
|
- **加 `column.meta.includeTime: boolean` 旗標** — 對齊 Notion idiom,不另設 datetime column type
|
|
12
12
|
- **加 ValueShape `datetime_single` / `datetime_range`** — `includeTime=true` 時切到這兩個 shape
|
|
13
|
-
-
|
|
13
|
+
- **datetime 不另設 relative shape** — `is_relative` 維持 `date_relative`(relative 邏輯不變;12-shape 表與 code `ValueShape` union 皆無 `datetime_relative`)
|
|
14
14
|
- **filter 比對精度**:`includeTime=true` 走 ms 精度(避開 Airtable 著名地雷:filter 忽略 time)
|
|
15
15
|
- **不新增 `time-only` column type**(業界沒人做,罕見場景)
|
|
16
16
|
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
| `select_single` | `<Select>` from `column.meta.options` | (預留)罕用 |
|
|
34
34
|
| `person_single` | `<PeoplePicker>` 單選 | (預留)罕用 |
|
|
35
35
|
|
|
36
|
-
**date_relative 預設選項**(
|
|
37
|
-
`today / yesterday / tomorrow / this_week / last_week / next_week / this_month / last_month / next_month / past_7_days / past_30_days`
|
|
36
|
+
**date_relative 預設選項**(13 個,分過去 / 目前 / 未來三組 — 對齊 code `DATE_RELATIVE_OPTIONS` / `DATE_RELATIVE_GROUPS`):
|
|
37
|
+
`today / yesterday / tomorrow / this_week / last_week / next_week / this_month / last_month / next_month / past_7_days / past_30_days / next_7_days / next_30_days`
|
|
38
38
|
|
|
39
39
|
**`number_range` 已砍**(配合 `number.between` 砍除)。
|
|
40
40
|
|
|
@@ -189,30 +189,15 @@
|
|
|
189
189
|
| 統一用 `is_set` / `is_not_set`(不混 `is_empty`) | 9 types 全用(boolean 豁免) |
|
|
190
190
|
| select / person 用 `is` 配多值 picker(不另設 `is_any_of`) | ✓ 對齊 CU UX |
|
|
191
191
|
| multiSelect / multiPerson 用 `has_*` 動詞(對應 CU labels Any/All/None) | ✓ |
|
|
192
|
-
| number
|
|
192
|
+
| number 不設 `between`(v3 砍 — 同 field `gte AND lte` 組合替代,見拍板 #10) | ✓ |
|
|
193
193
|
| date 用 `before/after/between/relative` + `is_set` 不混 Airtable `is_empty` 風 | ✓ |
|
|
194
194
|
| 6 ops 擴充項皆有 ≥ 2 家 world-class DS 採用,且不衝突 CU 設計語言 | ✓ |
|
|
195
195
|
|
|
196
196
|
**未跑 audit / test 驗證**,僅與 web-researched ClickUp / Airtable / Notion docs 自我比對。
|
|
197
197
|
|
|
198
|
-
## 5. TypeScript
|
|
198
|
+
## 5. TypeScript 結構(已落地)
|
|
199
199
|
|
|
200
|
-
|
|
201
|
-
export type ValueShape =
|
|
202
|
-
| 'none' | 'text' | 'number' | 'number_range'
|
|
203
|
-
| 'date_single' | 'date_range' | 'date_relative'
|
|
204
|
-
| 'select_single' | 'select_multi'
|
|
205
|
-
| 'person_single' | 'person_multi'
|
|
206
|
-
|
|
207
|
-
export interface OperatorSpec {
|
|
208
|
-
op: string // e.g. 'contains'
|
|
209
|
-
label: string // e.g. '包含'(暫硬編,留 i18n hook)
|
|
210
|
-
valueShape: ValueShape
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
export const OPERATOR_REGISTRY: Record<ColumnType, OperatorSpec[]> = { ... }
|
|
214
|
-
export const DEFAULT_OPERATOR: Record<ColumnType, string> = { ... }
|
|
215
|
-
```
|
|
200
|
+
型別與 registry 落地於 `filter-operators.ts`(`ValueShape` 12 種含 `datetime_*`、無 `number_range`;`OPERATOR_REGISTRY` / `DEFAULT_OPERATOR`;`getValueShape` 處理 `includeTime` auto-promote)。Tree 型別與求值在 `filter-tree.ts`。原 v2 草案已退役,以 code 為準。
|
|
216
201
|
|
|
217
202
|
## 6. 拍板紀錄
|
|
218
203
|
|
|
@@ -253,12 +238,19 @@ export const DEFAULT_OPERATOR: Record<ColumnType, string> = { ... }
|
|
|
253
238
|
|
|
254
239
|
**技術坑(信心 85%,Phase B spec.md 詳)**:TanStack `ColumnFiltersState` per-column 一筆 filter value,N 條同 column 會 AND-chain 不能 OR。**業界標準解法**:棄用 `columnFilters`,改自管 FilterTree state + 用 `globalFilter` + 自訂 `globalFilterFn` 走樹求 boolean。
|
|
255
240
|
|
|
256
|
-
## 8.
|
|
241
|
+
## 8. 邊界案例(code 真值 — `filter-tree.ts` / `data-table-filter-panel.tsx`)
|
|
242
|
+
|
|
243
|
+
- **Condition 值空 / 未選 field**:視為 incomplete,求值 **pass-through**(不過濾任何 row);空值 ≠ `is_not_set`(後者是顯式 op)— `isConditionComplete` 守門
|
|
244
|
+
- **群組刪光 condition**:空群組保留並 pass-through(true),panel 顯示「移除空群組」按鈕由 user 顯式刪除,不自動消失
|
|
245
|
+
- **巢狀深度**:1-level cap 由 TypeScript 型別鎖死(`FilterGroup.children: FilterCondition[]`),無 runtime guard;繞過型別塞入的非 condition 物件缺 `field`/`op` → incomplete → pass-through,不 crash
|
|
246
|
+
- **relative 區間邊界**:全部 local time、雙端 inclusive(`startOfDay`–`endOfDay`);`past_7_days` = 7 天前 00:00 起**含今天整天**;week 以週一起算(`weekStartsOn: 1`)
|
|
247
|
+
|
|
248
|
+
## 9. Phase B 進度
|
|
257
249
|
|
|
258
|
-
- [x] ValueShape × DS 元件對照 — 完成,coverage 8/12 直接消費 + 4
|
|
250
|
+
- [x] ValueShape × DS 元件對照 — 完成,coverage 8/12 直接消費 + 4 預留;datetime 走 `<DatePicker showTime>` / `<DatePickerRange showTime>` prop variant(M21,非新元件)
|
|
259
251
|
- [x] InputSurface 議題消失(配合砍 `number.between`)
|
|
260
|
-
- [
|
|
261
|
-
- [
|
|
252
|
+
- [x] FilterTree data model + DataTable 耦合 — 已落地 `filter-tree.ts` + `data-table-filter-panel.tsx`(原規劃 `advanced-filter.draft.md` 未另立檔,內容即本 spec + code)
|
|
253
|
+
- [x] datetime spec — 併入本 spec v3(原規劃 `datetime-picker.draft.md` 不需要,無新元件)
|
|
262
254
|
- [x] i18n 策略 — 暫硬編繁中,留 i18n hook(對齊 DS 既有元件慣例)
|
|
263
255
|
- [→] Phase B.5 lock canonical via `/ensure-canonical`(spec 全收斂後)
|
|
264
256
|
|
|
@@ -105,7 +105,7 @@ export const Overview = {
|
|
|
105
105
|
<div>
|
|
106
106
|
<H3>視覺一覽</H3>
|
|
107
107
|
<Desc>實際渲染 — single mode,已選今日的前一日展示 selected 視覺,today 以數字下方藍色底線標示。</Desc>
|
|
108
|
-
<div className="inline-flex bg-surface-raised border border-border rounded-lg
|
|
108
|
+
<div className="inline-flex bg-surface-raised border border-border rounded-lg w-fit">
|
|
109
109
|
<DateGrid
|
|
110
110
|
mode="single"
|
|
111
111
|
selected={(() => {
|
|
@@ -196,7 +196,7 @@ export const Inspector = {
|
|
|
196
196
|
{/* Left: live preview + blueprint */}
|
|
197
197
|
<div className="flex flex-col gap-5">
|
|
198
198
|
<div className="px-6 py-6 rounded-lg bg-canvas border border-divider flex items-center justify-center">
|
|
199
|
-
<div className="bg-surface-raised border border-border rounded-lg
|
|
199
|
+
<div className="bg-surface-raised border border-border rounded-lg">
|
|
200
200
|
<DateGrid
|
|
201
201
|
mode="single"
|
|
202
202
|
selected={selected}
|
|
@@ -288,7 +288,7 @@ export const Inspector = {
|
|
|
288
288
|
return (
|
|
289
289
|
<div className="flex flex-col gap-4">
|
|
290
290
|
<H3>元件檢閱器</H3>
|
|
291
|
-
<Desc>DateGrid 的所有 layout token 一覽。theme / density
|
|
291
|
+
<Desc>DateGrid 的所有 layout token 一覽。theme / density 切換時色彩自動反轉,日格走 h-field-sm 隨 density 縮放(28×28 md / 32×32 lg),與 field 家族保持比例。</Desc>
|
|
292
292
|
<InspectorInner />
|
|
293
293
|
</div>
|
|
294
294
|
)
|
|
@@ -442,13 +442,13 @@ export const SizeMatrix = {
|
|
|
442
442
|
<div className="flex flex-wrap gap-6 items-start">
|
|
443
443
|
<div className="flex flex-col gap-2">
|
|
444
444
|
<span className="text-caption font-medium text-fg-secondary">單月(預設)</span>
|
|
445
|
-
<div className="bg-surface-raised border border-border rounded-lg
|
|
445
|
+
<div className="bg-surface-raised border border-border rounded-lg">
|
|
446
446
|
<DateGrid mode="single" defaultMonth={new Date()} locale={zhTW} />
|
|
447
447
|
</div>
|
|
448
448
|
</div>
|
|
449
449
|
<div className="flex flex-col gap-2">
|
|
450
450
|
<span className="text-caption font-medium text-fg-secondary">雙月並排(range 常用)</span>
|
|
451
|
-
<div className="bg-surface-raised border border-border rounded-lg
|
|
451
|
+
<div className="bg-surface-raised border border-border rounded-lg">
|
|
452
452
|
<DateGrid mode="single" defaultMonth={new Date()} locale={zhTW} numberOfMonths={2} />
|
|
453
453
|
</div>
|
|
454
454
|
</div>
|
|
@@ -483,7 +483,7 @@ export const StateBehavior = {
|
|
|
483
483
|
<div className="flex flex-wrap gap-6 items-start">
|
|
484
484
|
<div className="flex flex-col gap-2 min-w-0">
|
|
485
485
|
<span className="text-caption font-medium text-fg-secondary">mode="single"</span>
|
|
486
|
-
<div className="bg-surface-raised border border-border rounded-lg
|
|
486
|
+
<div className="bg-surface-raised border border-border rounded-lg">
|
|
487
487
|
<DateGrid
|
|
488
488
|
mode="single"
|
|
489
489
|
selected={single}
|
|
@@ -499,7 +499,7 @@ export const StateBehavior = {
|
|
|
499
499
|
|
|
500
500
|
<div className="flex flex-col gap-2 min-w-0">
|
|
501
501
|
<span className="text-caption font-medium text-fg-secondary">mode="multiple"</span>
|
|
502
|
-
<div className="bg-surface-raised border border-border rounded-lg
|
|
502
|
+
<div className="bg-surface-raised border border-border rounded-lg">
|
|
503
503
|
<DateGrid
|
|
504
504
|
mode="multiple"
|
|
505
505
|
selected={multiple}
|
|
@@ -515,7 +515,7 @@ export const StateBehavior = {
|
|
|
515
515
|
|
|
516
516
|
<div className="flex flex-col gap-2 min-w-0">
|
|
517
517
|
<span className="text-caption font-medium text-fg-secondary">mode="range"</span>
|
|
518
|
-
<div className="bg-surface-raised border border-border rounded-lg
|
|
518
|
+
<div className="bg-surface-raised border border-border rounded-lg">
|
|
519
519
|
<DateGrid
|
|
520
520
|
mode="range"
|
|
521
521
|
selected={range}
|
|
@@ -80,7 +80,7 @@ export const UsageGuidance: Story = {
|
|
|
80
80
|
<LinkTo kind="Design System/Internal/DateGrid/展示" name="範圍 — 分析時段 / 訂單範圍"><span className="text-primary hover:underline font-medium cursor-pointer">Range — 分析時段 / 訂單範圍</span></LinkTo>
|
|
81
81
|
</li>
|
|
82
82
|
<li>
|
|
83
|
-
<LinkTo kind="Design System/Internal/DateGrid/展示" name="行內 — 儀表板小卡"><span className="text-primary hover:underline font-medium cursor-pointer">行內 —
|
|
83
|
+
<LinkTo kind="Design System/Internal/DateGrid/展示" name="行內 — 儀表板小卡"><span className="text-primary hover:underline font-medium cursor-pointer">行內 — Linear 專案截止日小卡</span></LinkTo>
|
|
84
84
|
</li>
|
|
85
85
|
</ul>
|
|
86
86
|
<p className="text-fg-muted mt-3">判斷不確定時:對照 spec.md「何時用 / 何時不用」段;若仍不符,改用近親元件(見下方「vs 近親」)。</p>
|
|
@@ -120,10 +120,10 @@ export const UsageGuidance: Story = {
|
|
|
120
120
|
</Rule>
|
|
121
121
|
</Section>
|
|
122
122
|
|
|
123
|
-
<Section title="vs 近親 —
|
|
123
|
+
<Section title="vs 近親 — DateGrid(inline)vs DatePicker(field trigger)">
|
|
124
124
|
<Rule
|
|
125
|
-
title="
|
|
126
|
-
note="dashboard 小卡、側欄 widget、日期 filter bar。使用者一眼就看到整月,不需點開。
|
|
125
|
+
title="DateGrid — inline 月曆,頁面上常駐可見"
|
|
126
|
+
note="dashboard 小卡、側欄 widget、日期 filter bar。使用者一眼就看到整月,不需點開。DateGrid 是純 primitive,不自包 Popover。"
|
|
127
127
|
>
|
|
128
128
|
<Demo title="Linear 專案截止日 widget">
|
|
129
129
|
<div className="flex flex-col gap-2 w-fit">
|
|
@@ -152,7 +152,7 @@ export const UsageGuidance: Story = {
|
|
|
152
152
|
|
|
153
153
|
<Rule
|
|
154
154
|
title="判斷法 — 看「頁面是否常駐顯示整月」"
|
|
155
|
-
note="常駐(月曆是主要內容)→
|
|
155
|
+
note="常駐(月曆是主要內容)→ DateGrid;輔助(主要是一個欄位,偶爾改)→ DatePicker。空間有限的表單永遠用 DatePicker,不要塞整個月曆進表單。"
|
|
156
156
|
>
|
|
157
157
|
<Label>
|
|
158
158
|
常駐月曆 = 使用者「在選日的脈絡中」(排班、活動、分析時段篩選);
|
|
@@ -304,9 +304,9 @@ export const LocaleRule: Story = {
|
|
|
304
304
|
<div>
|
|
305
305
|
<Rule
|
|
306
306
|
title="locale prop 控制週首日與星期標頭語言"
|
|
307
|
-
note="react-day-picker 接受 date-fns locale 物件。週首日由 locale 物件決定,不以語言籠統判斷:
|
|
307
|
+
note="react-day-picker 接受 date-fns locale 物件。週首日由 locale 物件決定,不以語言籠統判斷:en-US 週日起、en-GB 週一起——同樣是英文,週首日就不同;zhTW / de / fr(date-fns 內建值)都是週一起。下方對照:zhTW 首欄是週一,en-US 首欄是週日。Consumer 決定傳哪個 locale,DateGrid 不內建語言。"
|
|
308
308
|
>
|
|
309
|
-
<Demo title="zhTW(繁體中文 ·
|
|
309
|
+
<Demo title="zhTW(繁體中文 · 週一起)">
|
|
310
310
|
<DateGrid mode="single" defaultMonth={new Date(2026, 3, 1)} locale={zhTW} />
|
|
311
311
|
</Demo>
|
|
312
312
|
<Demo title="預設(en-US · 週日起)">
|
|
@@ -26,7 +26,7 @@ DateGrid 是 **DatePicker 內部的 date-grid primitive**(月份格網 + 前後
|
|
|
26
26
|
|
|
27
27
|
**Layout Family**:非上述 family — composite / multi-section(月份 caption + 星期標頭 + 日期網格 + nav 按鈕,多區塊組合)。
|
|
28
28
|
|
|
29
|
-
**Storybook title 層級**:`Design System/Internal/DateGrid/*`(非 Components/,因為它是 DatePicker 的 internal primitive;對齊
|
|
29
|
+
**Storybook title 層級**:`Design System/Internal/DateGrid/*`(非 Components/,因為它是 DatePicker 的 internal primitive;對齊 `.claude/rules/ui-development.md`「Public component vs Internal primitive canonical」(intent-based 判準):consumer 經 `DatePicker` wrapper 取得,不直接 import 本元件)。
|
|
30
30
|
|
|
31
31
|
**世界級命名對照(為什麼不叫 Calendar)**:
|
|
32
32
|
|
|
@@ -46,6 +46,8 @@ DateGrid 是 **DatePicker 內部的 date-grid primitive**(月份格網 + 前後
|
|
|
46
46
|
|
|
47
47
|
## 何時用
|
|
48
48
|
|
|
49
|
+
DateGrid 是 internal primitive(見「定位」),一般 consumer 經 `DatePicker` 取得;以下為 DS 內部組合或進階 inline 場景:
|
|
50
|
+
|
|
49
51
|
- **Inline 月曆顯示**:dashboard / 行事曆小卡 / 日期 filter bar
|
|
50
52
|
- **DatePicker 浮層內嵌**:DatePicker 消費本元件作為選日 popup(見 `../DatePicker/date-picker.spec.md`)
|
|
51
53
|
- **範圍選擇**:`mode="range"` 適用「from → to」場景(訂單日期範圍、查詢時段)
|
|
@@ -57,7 +59,7 @@ DateGrid 是 **DatePicker 內部的 date-grid primitive**(月份格網 + 前後
|
|
|
57
59
|
|------|------|------|
|
|
58
60
|
| 日期輸入欄位 | `DatePicker` | DateGrid 是 inline,欄位需要 trigger + popup 結構 |
|
|
59
61
|
| 純顯示單日期 | `<DatePicker mode="display">` / `Intl.DateTimeFormat` | 不需 interactive 月曆 |
|
|
60
|
-
| 時間選擇(時分) |
|
|
62
|
+
| 時間選擇(時分) | `TimePicker`(見 `../TimePicker/time-picker.spec.md`)| DateGrid 只處理日期層級 |
|
|
61
63
|
| 事件行事曆(日程本) | 專用行事曆元件 | DateGrid 是日期選擇;事件日誌需要 event overlay / drag / week/month view 切換 |
|
|
62
64
|
|
|
63
65
|
---
|
|
@@ -70,6 +72,8 @@ DateGrid 是 **DatePicker 內部的 date-grid primitive**(月份格網 + 前後
|
|
|
70
72
|
| `multiple` | 可勾選多個不連續日期 | event 報名多日 |
|
|
71
73
|
| `range` | from → to 連續範圍 | 訂單日期範圍 / 查詢時段 |
|
|
72
74
|
|
|
75
|
+
**range vs multiple 分界**:選的是「連續區間」(只在乎起迄兩端)→ `range`;選的是「各自獨立的日子」(可不連續、逐日增減)→ `multiple`。起迄日場景(訂單 / 查詢時段)固定走 `range`;簽核 / 報名這類逐日勾選走 `multiple`。
|
|
76
|
+
|
|
73
77
|
---
|
|
74
78
|
|
|
75
79
|
## 實作機制:classNames 鏡射 modifier keys(2026-04-21 AR43 修正)
|
|
@@ -99,10 +103,10 @@ DateGrid 是 **DatePicker 內部的 date-grid primitive**(月份格網 + 前後
|
|
|
99
103
|
| **today + selected** | 數字下方短圓桿(白) | bar 色切 `on-emphasis` | 選中藍底上藍 bar 隱形,必切白;以 state 疊加 selector 覆寫 |
|
|
100
104
|
| **disabled** | 灰底 + 淡字 | `bg-disabled` + `fg-disabled` + `cursor-not-allowed` | 跟 Button disabled token 一致,不自創 palette |
|
|
101
105
|
| **outside(非本月)**| 淡字(只文字) | `fg-muted` | 比 disabled 弱:outside 仍可 hover / 可點,純是「非焦點月份」的標示 |
|
|
102
|
-
| **selected / range 端點** | 藍底白字圓 | button `primary` 底 + `on-emphasis` 字
|
|
103
|
-
| **range 端點 cell bg** | 灰底半圓 track,**高度 = button
|
|
104
|
-
| **range track(中間)** | 灰底矩形,**高度 = button**(28×28 @ md)
|
|
105
|
-
| **hover(未選中)** | 藍圈 outline(無 fill) | button hover ring 色 `primary
|
|
106
|
+
| **selected / range 端點** | 藍底白字圓 | button `primary` 底 + `on-emphasis` 字 | range_start / range_end 共用此視覺 |
|
|
107
|
+
| **range 端點 cell bg** | 灰底半圓 track,**高度 = button**,向 middle 外擴 2px bridge gap | `neutral-selected`;class 細節見「Range track canonical」+ tsx | 圓弧半徑 = button 半徑無錯位;舊版 cell-level bg 圓弧半徑 16px 比 button 14px 大 = 視覺 misalign |
|
|
108
|
+
| **range track(中間)** | 灰底矩形,**高度 = button**(28×28 @ md),左右各外擴 2px 接合相鄰 cell | `neutral-selected`;button 透明顯露 track(class 細節見 tsx)| track 高度跟 selected 圓一致,不留 2px「fat」邊;相鄰 pseudo 接合連貫橫向 track |
|
|
109
|
+
| **hover(未選中)** | 藍圈 outline(無 fill) | button hover ring 色 `primary`,無 bg(ring 寬度等 class 細節見 tsx)| 細 ring 對齊 Apple HIG `@benchmark-unverified` / Ant `@benchmark-unverified`(visual,non-source-citable) |
|
|
106
110
|
|
|
107
111
|
## 組合狀態(state stacking order)
|
|
108
112
|
|
|
@@ -110,7 +114,7 @@ DateGrid 是 **DatePicker 內部的 date-grid primitive**(月份格網 + 前後
|
|
|
110
114
|
- range-start / range-end → selected 規則(cell 半圓 track + button 圓)
|
|
111
115
|
- range-middle → track 規則(cell 灰底矩形 + button 透明)
|
|
112
116
|
- today + range-middle → track(灰底)+ today bar(藍色仍可見,cell 未 selected)
|
|
113
|
-
- hover 在 selected /
|
|
117
|
+
- hover 在 selected / disabled 上被 ring-0 壓制(避免二次 hover 出現方框 bug);range-middle 的 button 透明顯露 track,hover ring 仍顯示(見 tsx `range_middle` 註解)
|
|
114
118
|
|
|
115
119
|
## Spacing canonical(2026-05-03 v8)
|
|
116
120
|
|
|
@@ -136,7 +140,7 @@ Prev/Next chevron 用 `<Button variant="text" size="xs" iconOnly>`(DS primitive
|
|
|
136
140
|
- `fg-muted`(45%)專屬 dismiss / inline action / placeholder(spec.md 既有定義)
|
|
137
141
|
- chevron nav 是 functional navigation,不是 dismiss → 不該套 fg-muted 自開新 tier
|
|
138
142
|
|
|
139
|
-
歷史(2026-05-03):v6-v8
|
|
143
|
+
歷史(2026-05-03):v6-v8 曾以未驗證的「Ant chevron muted」印象覆蓋 DS canonical,已撤回(M23 防再犯)。
|
|
140
144
|
|
|
141
145
|
⚠️ RDP `PreviousMonthButton` override 必丟 `children`(RDP 把 `<Chevron>` 當 children 傳)否則 double svg(2026-05-03 v8 抓到 bug)。
|
|
142
146
|
|
|
@@ -147,9 +151,8 @@ Prev/Next chevron 用 `<Button variant="text" size="xs" iconOnly>`(DS primitive
|
|
|
147
151
|
## Range track canonical(2026-05-03 v8)
|
|
148
152
|
|
|
149
153
|
對齊 Ant `cell-range-start::before { border-radius: 9999px 0 0 9999px }`(stadium pattern): <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
|
|
150
|
-
- `range_start` cell pseudo
|
|
151
|
-
- `
|
|
152
|
-
- `range_middle` cell pseudo:`before:-inset-x-[2px] inset-y-0 bg-neutral-selected`(無 rounding)
|
|
154
|
+
- `range_start` / `range_end` cell pseudo:左 / 右半圓 stadium,向 middle 側外擴 2px bridge gap(class 細節見 tsx `range_start` / `range_end`)
|
|
155
|
+
- `range_middle` cell pseudo:滿 cell 高矩形、左右各外擴 2px,無 rounding(class 細節見 tsx)
|
|
153
156
|
- pseudo 蓋全 cell + bridge 4px gap → button 圓的 corner triangle 看到 pseudo bg(對齊 button 圓的左/右半弧,無「凸出」)
|
|
154
157
|
- `bg-neutral-selected`(semantic = neutral-2)— 對齊 TimePicker 選中項目樣式
|
|
155
158
|
|
|
@@ -173,7 +176,7 @@ react-day-picker v9 自動處理:
|
|
|
173
176
|
- **Focus**:`autoFocus` prop 自動 focus 到選中日(或今天)
|
|
174
177
|
- **Locale**:`locale` prop 控制週首日、星期標頭語言
|
|
175
178
|
|
|
176
|
-
|
|
179
|
+
**DS 自訂部分**:day button 的 focus ring 由本元件 classNames 覆寫為 DS canonical(`focus-visible:ring-2 ring-ring`,非 RDP 預設樣式);nav 按鈕為 DS `<Button>` 並帶 `aria-label`(上一個月 / 下一個月)。其餘 consumer 無需額外處理,保留 react-day-picker API 即可。
|
|
177
180
|
|
|
178
181
|
---
|
|
179
182
|
|
|
@@ -195,9 +198,9 @@ DateGrid 本元件是**對 `react-day-picker` 的 `<DayPicker>` 元件薄包裝*
|
|
|
195
198
|
|
|
196
199
|
- **Disabled day**:`disabled` prop 走 react-day-picker matcher;disabled cell 視覺 `text-fg-disabled`(M24)、`cursor-not-allowed`、click 不觸發 onSelect、鍵盤導覽自動 skip。
|
|
197
200
|
- **Loading(server-rendered grid)**:DateGrid 為 sync render(date math 在 client),非 async surface。consumer 若需 async disabled-dates fetch(如後端 holiday list),應先 disable trigger 直到 fetch 完成,DateGrid 開啟後立即 ready。
|
|
198
|
-
- **Empty(全 disabled days)**:極端場景(所有日期都被 disabled matcher 命中),DateGrid 渲完整 grid 但全部 cell 為 disabled state,鍵盤焦點停留無導覽目標(react-day-picker v9 內建)。
|
|
201
|
+
- **Empty(全 disabled days)**:極端場景(所有日期都被 disabled matcher 命中),DateGrid 渲完整 grid 但全部 cell 為 disabled state,鍵盤焦點停留無導覽目標(react-day-picker v9 內建)。Enter / Space 在 disabled cell 上無動作不報錯(RDP DayButton 對 disabled day 渲染 native `disabled`,focus target 時改掛 `aria-disabled`),Tab 走 roving tabIndex 整個 grid 只停一格。
|
|
199
202
|
- **Dark mode**:走 semantic token(primary / neutral / fg-muted)自動 adapt。
|
|
200
|
-
- **Density**:DateGrid day cell 走 `h-field-sm w-[var(--field-height-sm)]`,**隨 density 縮放**(md = 28×28 / lg = 32×32,token `--field-height-sm` 在 `[data-density="lg"]` override 為 `2rem`),跟 popup 內 Input / Button 等 field 家族一起放大保持比例(見 L128 + L120)。
|
|
203
|
+
- **Density**:DateGrid day cell 走 `h-field-sm w-[var(--field-height-sm)]`,**隨 density 縮放**(md = 28×28 / lg = 32×32,token `--field-height-sm` 在 `[data-density="lg"]` override 為 `2rem`),跟 popup 內 Input / Button 等 field 家族一起放大保持比例(見 L128 + L120)。grid 寬度為 intrinsic(7 × cell + 4px gap + `p-3`),lg 下整體變寬;DateGrid 無內部 overflow / responsive 縮排機制,容器(Popover / parent)以內容寬呈現。
|
|
201
204
|
|
|
202
205
|
---
|
|
203
206
|
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @internal — DS-internal 單元(per `.claude/rules/ui-development.md` Public vs Internal canonical;spec frontmatter `isInternal`)。
|
|
3
|
+
* 不進 root barrel front-door;由 DatePicker wrap 消費,end-user app 請用 wrapper 元件。
|
|
4
|
+
*/
|
|
1
5
|
// @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
6
|
// M22 retrofit DONE 2026-05-03 v11(real source URLs added inline at lines 38 + 111)
|
|
3
7
|
import * as React from 'react'
|
|
@@ -17,8 +21,8 @@ import { Button } from '@/design-system/components/Button/button'
|
|
|
17
21
|
* |------|------|
|
|
18
22
|
* | Outer padding | `p-3`(12px 四邊對稱) |
|
|
19
23
|
* | Nav + Month caption row | h-field-xs(24px)單行,chevron(xs)分居左右 / 月份置中垂直對齊 |
|
|
20
|
-
* | Nav → Weekday gap | 12px(
|
|
21
|
-
* | Weekday | text-body(14px)text-
|
|
24
|
+
* | Nav → Weekday gap | 12px(month_caption mb-3) |
|
|
25
|
+
* | Weekday | text-body(14px)text-foreground font-medium(neutral-9,同 caption 權重;撤銷 v3 fg-secondary) |
|
|
22
26
|
* | Cell gap(水平 + 垂直)| 4px(gap-1) |
|
|
23
27
|
* | Day cell size | h-field-sm w-[var(--field-height-sm)](28×28 md / 32×32 lg) |
|
|
24
28
|
* | Day button | rounded-full 填滿 cell |
|
|
@@ -200,8 +204,8 @@ export const dateGridMeta = {
|
|
|
200
204
|
},
|
|
201
205
|
states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],
|
|
202
206
|
tokens: {
|
|
203
|
-
bg: ['bg-disabled', 'bg-primary', 'bg-primary-hover', 'bg-transparent'],
|
|
204
|
-
fg: ['text-fg-disabled', 'text-fg-muted', 'text-
|
|
207
|
+
bg: ['bg-disabled', 'bg-neutral-selected', 'bg-on-emphasis', 'bg-primary', 'bg-primary-hover', 'bg-transparent'],
|
|
208
|
+
fg: ['text-fg-disabled', 'text-fg-muted', 'text-foreground', 'text-on-emphasis'],
|
|
205
209
|
ring: ['ring-primary', 'ring-ring'],
|
|
206
210
|
},
|
|
207
211
|
} as const
|