@qijenchen/design-system 0.1.0-beta.80 → 0.1.0-beta.82
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 +1 -1
- package/dist/components/Alert/alert.d.ts +5 -0
- package/dist/components/Alert/alert.d.ts.map +1 -1
- package/dist/components/Alert/alert.js +4 -1
- package/dist/components/Alert/alert.js.map +1 -1
- package/dist/components/AppShell/app-shell.d.ts +1 -1
- package/dist/components/AppShell/app-shell.js.map +1 -1
- package/dist/components/AspectRatio/aspect-ratio.d.ts +2 -1
- package/dist/components/AspectRatio/aspect-ratio.d.ts.map +1 -1
- package/dist/components/AspectRatio/aspect-ratio.js +1 -1
- package/dist/components/AspectRatio/aspect-ratio.js.map +1 -1
- package/dist/components/Avatar/avatar.d.ts +3 -2
- package/dist/components/Avatar/avatar.d.ts.map +1 -1
- package/dist/components/Avatar/avatar.js +8 -3
- package/dist/components/Avatar/avatar.js.map +1 -1
- package/dist/components/Badge/badge.d.ts.map +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 +14 -1
- package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -1
- package/dist/components/Breadcrumb/breadcrumb.js +9 -3
- package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
- package/dist/components/BulkActionBar/bulk-action-bar.d.ts +4 -1
- package/dist/components/BulkActionBar/bulk-action-bar.d.ts.map +1 -1
- package/dist/components/BulkActionBar/bulk-action-bar.js +2 -2
- package/dist/components/BulkActionBar/bulk-action-bar.js.map +1 -1
- package/dist/components/Button/button.d.ts +4 -4
- package/dist/components/Button/button.d.ts.map +1 -1
- package/dist/components/Button/button.js +73 -44
- package/dist/components/Button/button.js.map +1 -1
- package/dist/components/Button/index.d.ts +1 -0
- package/dist/components/Button/index.d.ts.map +1 -1
- package/dist/components/Button/index.js +3 -0
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Calendar/calendar.d.ts +3 -1
- package/dist/components/Calendar/calendar.d.ts.map +1 -1
- package/dist/components/Calendar/calendar.js +40 -17
- package/dist/components/Calendar/calendar.js.map +1 -1
- package/dist/components/Carousel/carousel.d.ts +1 -1
- package/dist/components/Carousel/carousel.d.ts.map +1 -1
- package/dist/components/Carousel/carousel.js +3 -1
- 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 -1
- package/dist/components/Chart/chart.js.map +1 -1
- package/dist/components/Checkbox/checkbox.d.ts +6 -3
- package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox/checkbox.js +26 -4
- package/dist/components/Checkbox/checkbox.js.map +1 -1
- package/dist/components/Checkbox/index.d.ts +1 -0
- package/dist/components/Checkbox/index.d.ts.map +1 -1
- package/dist/components/Checkbox/index.js +3 -0
- package/dist/components/Checkbox/index.js.map +1 -1
- package/dist/components/Chip/chip.d.ts +9 -3
- package/dist/components/Chip/chip.d.ts.map +1 -1
- package/dist/components/Chip/chip.js +46 -13
- package/dist/components/Chip/chip.js.map +1 -1
- package/dist/components/Coachmark/coachmark.d.ts +5 -3
- package/dist/components/Coachmark/coachmark.d.ts.map +1 -1
- package/dist/components/Coachmark/coachmark.js +10 -7
- package/dist/components/Coachmark/coachmark.js.map +1 -1
- package/dist/components/Combobox/combobox.d.ts +3 -1
- package/dist/components/Combobox/combobox.d.ts.map +1 -1
- package/dist/components/Combobox/combobox.js +11 -7
- package/dist/components/Combobox/combobox.js.map +1 -1
- package/dist/components/Command/command.d.ts +2 -2
- package/dist/components/Command/command.d.ts.map +1 -1
- package/dist/components/Command/command.js +4 -2
- package/dist/components/Command/command.js.map +1 -1
- package/dist/components/DataTable/active-editor-controller.d.ts +4 -3
- package/dist/components/DataTable/active-editor-controller.d.ts.map +1 -1
- package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
- package/dist/components/DataTable/cell-registry.js +3 -0
- package/dist/components/DataTable/cell-registry.js.map +1 -1
- package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-interaction-layer.d.ts +4 -3
- package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
- package/dist/components/DataTable/data-table.d.ts +38 -7
- package/dist/components/DataTable/data-table.d.ts.map +1 -1
- package/dist/components/DataTable/data-table.js +213 -63
- package/dist/components/DataTable/data-table.js.map +1 -1
- package/dist/components/DataTable/filter-tree.d.ts +5 -0
- package/dist/components/DataTable/filter-tree.d.ts.map +1 -1
- package/dist/components/DateGrid/date-grid.d.ts +3 -3
- package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
- package/dist/components/DateGrid/date-grid.js +52 -6
- package/dist/components/DateGrid/date-grid.js.map +1 -1
- package/dist/components/DatePicker/date-picker.d.ts +2 -8
- package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
- package/dist/components/DatePicker/date-picker.js +139 -109
- package/dist/components/DatePicker/date-picker.js.map +1 -1
- package/dist/components/DescriptionList/description-list.d.ts.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 +1 -1
- package/dist/components/Dialog/dialog.d.ts.map +1 -1
- package/dist/components/Dialog/dialog.js +2 -1
- package/dist/components/Dialog/dialog.js.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.d.ts +4 -4
- package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.js +25 -8
- package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
- package/dist/components/Empty/empty.d.ts.map +1 -1
- package/dist/components/Empty/empty.js +1 -1
- package/dist/components/Empty/empty.js.map +1 -1
- package/dist/components/Field/field-wrapper.d.ts +1 -0
- package/dist/components/Field/field-wrapper.d.ts.map +1 -1
- package/dist/components/Field/field-wrapper.js +27 -7
- package/dist/components/Field/field-wrapper.js.map +1 -1
- package/dist/components/Field/field.d.ts +1 -1
- package/dist/components/Field/field.d.ts.map +1 -1
- package/dist/components/Field/field.js +2 -1
- package/dist/components/Field/field.js.map +1 -1
- package/dist/components/Field/use-form-validation.d.ts +5 -1
- package/dist/components/Field/use-form-validation.d.ts.map +1 -1
- package/dist/components/Field/use-form-validation.js +31 -21
- package/dist/components/Field/use-form-validation.js.map +1 -1
- package/dist/components/FieldControlGroup/field-control-group.d.ts +3 -3
- 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 +3 -2
- 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.d.ts.map +1 -1
- package/dist/components/FileUpload/file-upload.js +22 -10
- package/dist/components/FileUpload/file-upload.js.map +1 -1
- package/dist/components/FileViewer/can-render-image.d.ts +6 -0
- package/dist/components/FileViewer/can-render-image.d.ts.map +1 -0
- package/dist/components/FileViewer/can-render-image.js +11 -0
- package/dist/components/FileViewer/can-render-image.js.map +1 -0
- package/dist/components/FileViewer/file-viewer.d.ts +2 -2
- package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
- package/dist/components/FileViewer/file-viewer.js +24 -16
- package/dist/components/FileViewer/file-viewer.js.map +1 -1
- package/dist/components/FileViewer/image-renderer.d.ts +0 -5
- package/dist/components/FileViewer/image-renderer.d.ts.map +1 -1
- package/dist/components/FileViewer/image-renderer.js +1 -9
- 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 +3 -1
- package/dist/components/HoverCard/hover-card.js.map +1 -1
- package/dist/components/Input/input.d.ts +26 -3
- package/dist/components/Input/input.d.ts.map +1 -1
- package/dist/components/Input/input.js +12 -8
- package/dist/components/Input/input.js.map +1 -1
- package/dist/components/LinkInput/link-input.d.ts +3 -3
- package/dist/components/LinkInput/link-input.d.ts.map +1 -1
- package/dist/components/LinkInput/link-input.js +29 -28
- package/dist/components/LinkInput/link-input.js.map +1 -1
- package/dist/components/Menu/menu-item.d.ts.map +1 -1
- package/dist/components/Menu/menu-item.js +5 -4
- package/dist/components/Menu/menu-item.js.map +1 -1
- package/dist/components/Notice/notice.d.ts +5 -0
- package/dist/components/Notice/notice.d.ts.map +1 -1
- package/dist/components/Notice/notice.js +11 -5
- package/dist/components/Notice/notice.js.map +1 -1
- package/dist/components/NumberInput/number-input.d.ts +1 -1
- package/dist/components/NumberInput/number-input.d.ts.map +1 -1
- package/dist/components/NumberInput/number-input.js +17 -8
- package/dist/components/NumberInput/number-input.js.map +1 -1
- package/dist/components/OverflowIndicator/overflow-indicator.d.ts +1 -1
- package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
- package/dist/components/OverflowIndicator/overflow-indicator.js +2 -1
- package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
- package/dist/components/Pagination/index.d.ts +2 -0
- package/dist/components/Pagination/index.d.ts.map +1 -0
- package/dist/components/Pagination/index.js +6 -0
- package/dist/components/Pagination/index.js.map +1 -0
- package/dist/components/Pagination/pagination.d.ts +49 -0
- package/dist/components/Pagination/pagination.d.ts.map +1 -0
- package/dist/components/Pagination/pagination.js +182 -0
- package/dist/components/Pagination/pagination.js.map +1 -0
- package/dist/components/PeoplePicker/people-picker.d.ts +3 -3
- package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
- package/dist/components/PeoplePicker/people-picker.js +38 -36
- package/dist/components/PeoplePicker/people-picker.js.map +1 -1
- package/dist/components/PeoplePicker/person-display.d.ts +4 -0
- package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
- package/dist/components/PeoplePicker/person-display.js +3 -3
- 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 +58 -32
- package/dist/components/Popover/popover.js.map +1 -1
- package/dist/components/ProfileCard/profile-card.d.ts +11 -3
- package/dist/components/ProfileCard/profile-card.d.ts.map +1 -1
- package/dist/components/ProfileCard/profile-card.js +14 -4
- package/dist/components/ProfileCard/profile-card.js.map +1 -1
- package/dist/components/RadioGroup/radio-group.d.ts +1 -1
- package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
- package/dist/components/RadioGroup/radio-group.js +28 -3
- package/dist/components/RadioGroup/radio-group.js.map +1 -1
- package/dist/components/Rating/rating.js +3 -3
- package/dist/components/Rating/rating.js.map +1 -1
- package/dist/components/ScrollArea/scroll-area.d.ts +1 -1
- package/dist/components/ScrollArea/scroll-area.js +2 -2
- package/dist/components/ScrollArea/scroll-area.js.map +1 -1
- package/dist/components/SegmentedControl/segmented-control.d.ts +2 -2
- package/dist/components/SegmentedControl/segmented-control.d.ts.map +1 -1
- package/dist/components/SegmentedControl/segmented-control.js +23 -10
- package/dist/components/SegmentedControl/segmented-control.js.map +1 -1
- package/dist/components/Select/select.d.ts +10 -4
- package/dist/components/Select/select.d.ts.map +1 -1
- package/dist/components/Select/select.js +57 -14
- package/dist/components/Select/select.js.map +1 -1
- package/dist/components/SelectMenu/index.js +4 -2
- package/dist/components/SelectMenu/select-menu.d.ts +31 -6
- package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
- package/dist/components/SelectMenu/select-menu.js +169 -85
- package/dist/components/SelectMenu/select-menu.js.map +1 -1
- package/dist/components/Separator/separator.js +1 -1
- package/dist/components/Separator/separator.js.map +1 -1
- package/dist/components/Sheet/sheet.d.ts +1 -1
- package/dist/components/Sheet/sheet.d.ts.map +1 -1
- package/dist/components/Sheet/sheet.js +3 -2
- package/dist/components/Sheet/sheet.js.map +1 -1
- package/dist/components/Sidebar/sidebar.d.ts +2 -2
- package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
- package/dist/components/Sidebar/sidebar.js +28 -10
- 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 -2
- 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.map +1 -1
- package/dist/components/Steps/steps.js +6 -3
- package/dist/components/Steps/steps.js.map +1 -1
- package/dist/components/Switch/switch.d.ts +2 -2
- package/dist/components/Switch/switch.d.ts.map +1 -1
- package/dist/components/Switch/switch.js +47 -9
- package/dist/components/Switch/switch.js.map +1 -1
- package/dist/components/Tabs/tabs.d.ts +8 -5
- package/dist/components/Tabs/tabs.d.ts.map +1 -1
- package/dist/components/Tabs/tabs.js +45 -33
- package/dist/components/Tabs/tabs.js.map +1 -1
- package/dist/components/Tag/tag.d.ts.map +1 -1
- package/dist/components/Tag/tag.js +20 -4
- package/dist/components/Tag/tag.js.map +1 -1
- package/dist/components/Textarea/textarea.d.ts +2 -1
- package/dist/components/Textarea/textarea.d.ts.map +1 -1
- package/dist/components/Textarea/textarea.js +24 -13
- package/dist/components/Textarea/textarea.js.map +1 -1
- package/dist/components/TimePicker/time-picker.d.ts +2 -2
- package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
- package/dist/components/TimePicker/time-picker.js +23 -12
- package/dist/components/TimePicker/time-picker.js.map +1 -1
- package/dist/components/Toast/toast.d.ts +1 -1
- package/dist/components/Toast/toast.d.ts.map +1 -1
- package/dist/components/Toast/toast.js +7 -3
- package/dist/components/Toast/toast.js.map +1 -1
- package/dist/components/Tooltip/tooltip.js +1 -1
- package/dist/components/Tooltip/tooltip.js.map +1 -1
- package/dist/components/TreeView/tree-view.d.ts +1 -1
- package/dist/components/TreeView/tree-view.d.ts.map +1 -1
- package/dist/components/TreeView/tree-view.js +11 -5
- package/dist/components/TreeView/tree-view.js.map +1 -1
- package/dist/hooks/use-controllable.d.ts.map +1 -1
- package/dist/hooks/use-controllable.js +4 -2
- package/dist/hooks/use-controllable.js.map +1 -1
- package/dist/hooks/use-is-touch-device.d.ts.map +1 -1
- package/dist/hooks/use-is-touch-device.js +3 -1
- package/dist/hooks/use-is-touch-device.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.d.ts +2 -2
- 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/patterns/overlay-surface/overlay-surface.js.map +1 -1
- package/dist/tokens/categorical-color.d.ts +1 -1
- package/dist/tokens/categorical-color.js.map +1 -1
- package/dist/tokens/uiSize/icon-size.d.ts +2 -2
- package/ds-canonical/fork/governance.lock +1 -1
- package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +10 -1
- package/ds-canonical/hooks/check_audit_post_report_validator.sh +13 -0
- package/ds-canonical/hooks/check_full_story_visual_interaction_sweep.sh +4 -3
- package/ds-canonical/hooks/check_opacity_token_usage.sh +10 -1
- package/ds-canonical/hooks/check_plugin_fork_health.sh +30 -22
- package/ds-canonical/hooks/check_story_invariants.sh +17 -5
- package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +5 -2
- package/ds-canonical/references/principle-dim-map.json +100 -0
- package/ds-canonical/references/story-baseline-registry.json +4 -3
- package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +1 -1
- package/ds-canonical/skills/design-system-audit/SKILL.md +2 -2
- package/ds-story-manifest.json +41 -18
- package/llms-full.txt +11 -1
- package/llms.txt +3 -1
- package/package.json +1 -1
- package/src/components/Alert/alert.anatomy.stories.tsx +9 -6
- package/src/components/Alert/alert.spec.md +3 -3
- package/src/components/Alert/alert.tsx +9 -1
- package/src/components/AppShell/app-shell.anatomy.stories.tsx +3 -0
- package/src/components/AppShell/app-shell.spec.md +3 -2
- package/src/components/AppShell/app-shell.tsx +1 -1
- package/src/components/AspectRatio/aspect-ratio.spec.md +1 -2
- package/src/components/AspectRatio/aspect-ratio.tsx +3 -2
- package/src/components/Avatar/avatar.principles.stories.tsx +1 -1
- package/src/components/Avatar/avatar.spec.md +10 -30
- package/src/components/Avatar/avatar.stories.tsx +1 -1
- package/src/components/Avatar/avatar.tsx +30 -16
- package/src/components/Badge/badge.anatomy.stories.tsx +2 -2
- package/src/components/Badge/badge.spec.md +5 -4
- package/src/components/Badge/badge.tsx +4 -1
- package/src/components/Breadcrumb/breadcrumb.anatomy.stories.tsx +2 -2
- package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +15 -10
- package/src/components/Breadcrumb/breadcrumb.spec.md +5 -3
- package/src/components/Breadcrumb/breadcrumb.tsx +10 -4
- package/src/components/BulkActionBar/bulk-action-bar.anatomy.stories.tsx +3 -2
- package/src/components/BulkActionBar/bulk-action-bar.spec.md +15 -14
- package/src/components/BulkActionBar/bulk-action-bar.tsx +10 -4
- package/src/components/Button/button.anatomy.stories.tsx +6 -6
- package/src/components/Button/button.spec.md +3 -2
- package/src/components/Button/button.tsx +67 -27
- package/src/components/Button/index.ts +1 -0
- package/src/components/Calendar/calendar.anatomy.stories.tsx +5 -3
- package/src/components/Calendar/calendar.principles.stories.tsx +3 -1
- package/src/components/Calendar/calendar.spec.md +9 -2
- package/src/components/Calendar/calendar.stories.tsx +3 -1
- package/src/components/Calendar/calendar.tsx +53 -19
- package/src/components/Carousel/carousel.principles.stories.tsx +1 -1
- package/src/components/Carousel/carousel.tsx +4 -1
- package/src/components/Chart/chart.spec.md +1 -1
- package/src/components/Chart/chart.tsx +2 -1
- package/src/components/Checkbox/checkbox.principles.stories.tsx +1 -1
- package/src/components/Checkbox/checkbox.spec.md +1 -1
- package/src/components/Checkbox/checkbox.tsx +41 -7
- package/src/components/Checkbox/index.ts +1 -0
- package/src/components/Chip/chip.anatomy.stories.tsx +9 -9
- package/src/components/Chip/chip.principles.stories.tsx +3 -3
- package/src/components/Chip/chip.spec.md +7 -4
- package/src/components/Chip/chip.tsx +60 -15
- package/src/components/CircularProgress/circular-progress.anatomy.stories.tsx +1 -1
- package/src/components/CircularProgress/circular-progress.principles.stories.tsx +7 -5
- package/src/components/CircularProgress/circular-progress.spec.md +2 -0
- package/src/components/CircularProgress/circular-progress.stories.tsx +3 -11
- package/src/components/Coachmark/coachmark.anatomy.stories.tsx +2 -2
- package/src/components/Coachmark/coachmark.principles.stories.tsx +1 -1
- package/src/components/Coachmark/coachmark.spec.md +3 -3
- package/src/components/Coachmark/coachmark.tsx +23 -13
- package/src/components/Combobox/combobox.anatomy.stories.tsx +4 -4
- package/src/components/Combobox/combobox.spec.md +1 -1
- package/src/components/Combobox/combobox.tsx +30 -17
- package/src/components/Command/command.principles.stories.tsx +10 -12
- package/src/components/Command/command.spec.md +5 -5
- package/src/components/Command/command.stories.tsx +4 -4
- package/src/components/Command/command.tsx +3 -2
- package/src/components/DataTable/active-editor-controller.ts +4 -3
- package/src/components/DataTable/cell-registry.tsx +8 -0
- package/src/components/DataTable/data-table-filter-panel.tsx +8 -2
- package/src/components/DataTable/data-table-interaction-layer.tsx +8 -7
- package/src/components/DataTable/data-table.anatomy.stories.tsx +4 -4
- package/src/components/DataTable/data-table.css +2 -2
- package/src/components/DataTable/data-table.spec.md +72 -115
- package/src/components/DataTable/data-table.stories.tsx +51 -3
- package/src/components/DataTable/data-table.tsx +348 -63
- package/src/components/DataTable/filter-operators.spec.md +4 -4
- package/src/components/DataTable/filter-tree.ts +192 -42
- package/src/components/DateGrid/date-grid.anatomy.stories.tsx +1 -1
- package/src/components/DateGrid/date-grid.spec.md +11 -8
- package/src/components/DateGrid/date-grid.tsx +63 -8
- package/src/components/DatePicker/date-picker.principles.stories.tsx +1 -1
- package/src/components/DatePicker/date-picker.spec.md +1 -0
- package/src/components/DatePicker/date-picker.stories.tsx +19 -0
- package/src/components/DatePicker/date-picker.tsx +52 -15
- package/src/components/DescriptionList/description-list.spec.md +1 -1
- package/src/components/DescriptionList/description-list.tsx +3 -1
- package/src/components/Dialog/dialog.spec.md +1 -1
- package/src/components/Dialog/dialog.tsx +2 -1
- package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +3 -1
- package/src/components/DropdownMenu/dropdown-menu.spec.md +8 -5
- package/src/components/DropdownMenu/dropdown-menu.tsx +33 -7
- package/src/components/Empty/empty.anatomy.stories.tsx +1 -1
- package/src/components/Empty/empty.spec.md +2 -2
- package/src/components/Empty/empty.stories.tsx +4 -15
- package/src/components/Empty/empty.tsx +4 -1
- package/src/components/Field/field-controls.spec.md +2 -1
- package/src/components/Field/field-wrapper.tsx +28 -8
- package/src/components/Field/field.anatomy.stories.tsx +7 -7
- package/src/components/Field/field.principles.stories.tsx +1 -1
- package/src/components/Field/field.spec.md +9 -7
- package/src/components/Field/field.tsx +2 -1
- package/src/components/Field/form-validation.spec.md +6 -3
- package/src/components/Field/use-form-validation.ts +49 -21
- package/src/components/FieldControlGroup/field-control-group.anatomy.stories.tsx +11 -10
- package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +3 -3
- package/src/components/FieldControlGroup/field-control-group.spec.md +3 -3
- package/src/components/FieldControlGroup/field-control-group.tsx +3 -3
- package/src/components/FileItem/file-item.anatomy.stories.tsx +6 -4
- package/src/components/FileItem/file-item.tsx +3 -2
- package/src/components/FileUpload/file-upload.anatomy.stories.tsx +1 -1
- package/src/components/FileUpload/file-upload.spec.md +4 -1
- package/src/components/FileUpload/file-upload.tsx +36 -10
- package/src/components/FileViewer/can-render-image.ts +15 -0
- package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +6 -4
- package/src/components/FileViewer/file-viewer.spec.md +2 -2
- package/src/components/FileViewer/file-viewer.tsx +47 -21
- package/src/components/FileViewer/image-renderer.tsx +3 -8
- package/src/components/HoverCard/hover-card.spec.md +1 -1
- package/src/components/HoverCard/hover-card.tsx +3 -1
- package/src/components/Input/input.anatomy.stories.tsx +4 -4
- package/src/components/Input/input.principles.stories.tsx +1 -1
- package/src/components/Input/input.spec.md +1 -1
- package/src/components/Input/input.stories.tsx +11 -5
- package/src/components/Input/input.tsx +11 -9
- package/src/components/LinkInput/link-input.anatomy.stories.tsx +2 -0
- package/src/components/LinkInput/link-input.tsx +49 -34
- package/src/components/Menu/menu-item.anatomy.stories.tsx +1 -1
- package/src/components/Menu/menu-item.spec.md +4 -3
- package/src/components/Menu/menu-item.tsx +15 -4
- package/src/components/Notice/notice.anatomy.stories.tsx +10 -5
- package/src/components/Notice/notice.spec.md +4 -3
- package/src/components/Notice/notice.tsx +22 -5
- package/src/components/NumberInput/number-input.anatomy.stories.tsx +5 -4
- package/src/components/NumberInput/number-input.principles.stories.tsx +2 -1
- package/src/components/NumberInput/number-input.spec.md +2 -1
- package/src/components/NumberInput/number-input.tsx +25 -9
- package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +3 -3
- package/src/components/OverflowIndicator/overflow-indicator.spec.md +1 -1
- package/src/components/OverflowIndicator/overflow-indicator.tsx +2 -1
- package/src/components/Pagination/index.ts +5 -0
- package/src/components/Pagination/pagination.anatomy.stories.tsx +143 -0
- package/src/components/Pagination/pagination.principles.stories.tsx +81 -0
- package/src/components/Pagination/pagination.spec.md +150 -0
- package/src/components/Pagination/pagination.stories.tsx +98 -0
- package/src/components/Pagination/pagination.tsx +263 -0
- package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +1 -1
- package/src/components/PeoplePicker/people-picker.spec.md +4 -4
- package/src/components/PeoplePicker/people-picker.stories.tsx +1 -1
- package/src/components/PeoplePicker/people-picker.tsx +65 -55
- package/src/components/PeoplePicker/person-display.tsx +10 -4
- package/src/components/Popover/popover.anatomy.stories.tsx +2 -2
- package/src/components/Popover/popover.spec.md +13 -14
- package/src/components/Popover/popover.tsx +88 -39
- package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +4 -4
- package/src/components/ProfileCard/profile-card.principles.stories.tsx +2 -2
- package/src/components/ProfileCard/profile-card.spec.md +1 -2
- package/src/components/ProfileCard/profile-card.stories.tsx +1 -1
- package/src/components/ProfileCard/profile-card.tsx +29 -8
- package/src/components/RadioGroup/radio-group.principles.stories.tsx +1 -1
- package/src/components/RadioGroup/radio-group.spec.md +2 -2
- package/src/components/RadioGroup/radio-group.stories.tsx +3 -1
- package/src/components/RadioGroup/radio-group.tsx +37 -3
- package/src/components/Rating/rating.anatomy.stories.tsx +11 -8
- package/src/components/Rating/rating.principles.stories.tsx +1 -1
- package/src/components/Rating/rating.spec.md +2 -2
- package/src/components/Rating/rating.stories.tsx +1 -1
- package/src/components/Rating/rating.tsx +3 -3
- package/src/components/ScrollArea/scroll-area.spec.md +1 -0
- package/src/components/ScrollArea/scroll-area.tsx +1 -1
- package/src/components/SegmentedControl/segmented-control.anatomy.stories.tsx +3 -3
- package/src/components/SegmentedControl/segmented-control.spec.md +7 -3
- package/src/components/SegmentedControl/segmented-control.tsx +29 -11
- package/src/components/Select/select.anatomy.stories.tsx +2 -2
- package/src/components/Select/select.spec.md +3 -2
- package/src/components/Select/select.tsx +62 -19
- package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +1 -1
- package/src/components/SelectMenu/select-menu.principles.stories.tsx +1 -1
- package/src/components/SelectMenu/select-menu.spec.md +12 -8
- package/src/components/SelectMenu/select-menu.tsx +176 -20
- package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +1 -1
- package/src/components/SelectionControl/selection-item.principles.stories.tsx +2 -2
- package/src/components/SelectionControl/selection-item.spec.md +2 -1
- package/src/components/SelectionControl/selection-item.stories.tsx +1 -1
- package/src/components/Separator/separator.anatomy.stories.tsx +2 -2
- package/src/components/Separator/separator.tsx +1 -1
- package/src/components/Sheet/sheet.spec.md +2 -1
- package/src/components/Sheet/sheet.tsx +4 -2
- package/src/components/Sidebar/sidebar.anatomy.stories.tsx +1 -1
- package/src/components/Sidebar/sidebar.spec.md +2 -1
- package/src/components/Sidebar/sidebar.stories.tsx +6 -4
- package/src/components/Sidebar/sidebar.tsx +41 -13
- package/src/components/Skeleton/skeleton.principles.stories.tsx +1 -1
- package/src/components/Skeleton/skeleton.spec.md +1 -2
- package/src/components/Skeleton/skeleton.tsx +1 -1
- package/src/components/Slider/slider.anatomy.stories.tsx +4 -4
- package/src/components/Slider/slider.spec.md +19 -85
- package/src/components/Slider/slider.tsx +13 -5
- package/src/components/Steps/steps.anatomy.stories.tsx +1 -1
- package/src/components/Steps/steps.spec.md +6 -4
- package/src/components/Steps/steps.tsx +11 -3
- package/src/components/Switch/switch.spec.md +4 -3
- package/src/components/Switch/switch.tsx +59 -10
- package/src/components/Tabs/tabs.anatomy.stories.tsx +7 -6
- package/src/components/Tabs/tabs.principles.stories.tsx +5 -3
- package/src/components/Tabs/tabs.spec.md +15 -48
- package/src/components/Tabs/tabs.tsx +70 -34
- package/src/components/Tag/tag.principles.stories.tsx +2 -2
- package/src/components/Tag/tag.spec.md +11 -43
- package/src/components/Tag/tag.tsx +30 -4
- package/src/components/Textarea/textarea.principles.stories.tsx +2 -1
- package/src/components/Textarea/textarea.spec.md +2 -1
- package/src/components/Textarea/textarea.tsx +20 -10
- package/src/components/TimePicker/time-picker.anatomy.stories.tsx +2 -1
- package/src/components/TimePicker/time-picker.spec.md +2 -2
- package/src/components/TimePicker/time-picker.tsx +35 -16
- package/src/components/Toast/toast.anatomy.stories.tsx +5 -6
- package/src/components/Toast/toast.principles.stories.tsx +10 -11
- package/src/components/Toast/toast.spec.md +5 -5
- package/src/components/Toast/toast.stories.tsx +5 -1
- package/src/components/Toast/toast.tsx +13 -7
- package/src/components/Tooltip/tooltip.spec.md +3 -3
- package/src/components/Tooltip/tooltip.tsx +1 -1
- package/src/components/TreeView/tree-view.anatomy.stories.tsx +6 -1
- package/src/components/TreeView/tree-view.principles.stories.tsx +2 -2
- package/src/components/TreeView/tree-view.spec.md +2 -2
- package/src/components/TreeView/tree-view.tsx +27 -5
- package/src/hooks/use-controllable.ts +7 -2
- package/src/hooks/use-is-touch-device.ts +8 -1
- package/src/index.ts +2 -1
- package/src/patterns/element-anatomy/element-anatomy.spec.md +3 -3
- package/src/patterns/element-anatomy/inline-action.spec.md +1 -1
- package/src/patterns/element-anatomy/item-anatomy.spec.md +5 -14
- package/src/patterns/element-anatomy/item-anatomy.stories.tsx +1 -0
- package/src/patterns/element-anatomy/item-anatomy.tsx +5 -6
- package/src/patterns/header-canonical/header-canonical.css +1 -2
- package/src/patterns/header-canonical/header-canonical.spec.md +5 -5
- package/src/patterns/horizontal-overflow/horizontal-overflow.spec.md +5 -4
- package/src/patterns/horizontal-overflow/horizontal-overflow.stories.tsx +137 -0
- package/src/patterns/overlay-surface/overlay-surface.spec.md +8 -7
- package/src/patterns/overlay-surface/overlay-surface.stories.tsx +116 -0
- package/src/patterns/overlay-surface/overlay-surface.tsx +5 -5
- package/src/patterns/resize-handle/resize-handle.spec.md +1 -1
- package/src/tokens/categorical-color.ts +1 -1
- package/src/tokens/color/color.spec.md +11 -13
- package/src/tokens/color/color.stories.tsx +1 -1
- package/src/tokens/color/primitives.css +7 -5
- package/src/tokens/color/semantic.css +8 -2
- package/src/tokens/density/density.spec.md +2 -0
- package/src/tokens/elevation/elevation.spec.md +1 -1
- package/src/tokens/layoutSpace/layoutSpace.spec.md +2 -1
- package/src/tokens/layoutSpace/layoutSpace.stories.tsx +3 -3
- package/src/tokens/motion/motion.spec.md +1 -1
- package/src/tokens/motion/motion.stories.tsx +142 -0
- package/src/tokens/opacity/opacity.spec.md +1 -1
- package/src/tokens/opacity/opacity.stories.tsx +7 -11
- package/src/tokens/radius/radius.spec.md +1 -1
- package/src/tokens/typography/typography.css +1 -1
- package/src/tokens/typography/typography.spec.md +1 -1
- package/src/tokens/uiSize/icon-size.ts +2 -2
- package/src/tokens/uiSize/uiSize.spec.md +12 -11
- package/src/tokens/uiSize/uiSize.stories.tsx +103 -0
- package/src/tokens/utility-registry.json +5 -4
- package/dist/node_modules/react-hook-form/dist/index.esm.js +0 -1950
- package/dist/node_modules/react-hook-form/dist/index.esm.js.map +0 -1
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Public 元件(2026-07-04 Q8 拍板升 public,原 @internal 標記移除)。
|
|
3
|
+
* 理由:avatar.spec.md「hover 必出 ProfileCard」DS-wide canonical 要求 consumer 直接
|
|
4
|
+
* import ProfileCard + ProfileCardDefaultActions 組 HoverCard — 按 ui-development.md
|
|
5
|
+
* 唯一判準(DS 想讓 consumer 直接用 = public)internal 標記是 governance bug;
|
|
6
|
+
* 世界級對照:Atlassian ProfileCard 同為 public standalone。
|
|
4
7
|
*/
|
|
5
8
|
// @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.
|
|
6
9
|
import * as React from 'react'
|
|
@@ -31,12 +34,30 @@ import { ItemContent } from '@/design-system/patterns/element-anatomy/item-anato
|
|
|
31
34
|
*
|
|
32
35
|
* Chat + Audio call 是 **default**,不是 **only**——consumer 可覆寫,但需有明確理由。
|
|
33
36
|
*/
|
|
34
|
-
export const ProfileCardDefaultActions = (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
)
|
|
37
|
+
export const ProfileCardDefaultActions = ({
|
|
38
|
+
onChat,
|
|
39
|
+
onCall,
|
|
40
|
+
}: {
|
|
41
|
+
/** Chat 按鈕 handler(2026-07-06 user 拍板:預設鈕必可接線,未傳 = dev-warn;PersonData.onChat 自動 forward) */
|
|
42
|
+
onChat?: () => void
|
|
43
|
+
/** Audio call 按鈕 handler(ChevronDown 下拉行為留 v2,先接主 callback) */
|
|
44
|
+
onCall?: () => void
|
|
45
|
+
}) => {
|
|
46
|
+
// Dev-mode warning(對齊本檔 defaultFieldValues dev-warn 先例):預設 actions 沒接 handler
|
|
47
|
+
// = 按鈕點了永遠沒反應(2026-07-06 D4 finding);production 必傳 callback 或自組 actions。
|
|
48
|
+
if (process.env.NODE_ENV !== 'production' && !onChat && !onCall) {
|
|
49
|
+
// eslint-disable-next-line no-console
|
|
50
|
+
console.warn(
|
|
51
|
+
'[DS ProfileCard] ProfileCardDefaultActions 未接 onChat/onCall——按鈕點擊無反應。請傳入 callback(PersonData.onChat/onCall 會自動 forward)或自組 actions。'
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
return (
|
|
55
|
+
<>
|
|
56
|
+
<Button variant="tertiary" size="sm" startIcon={MessageCircle} onClick={onChat}>Chat</Button>
|
|
57
|
+
<Button variant="tertiary" size="sm" startIcon={Phone} endIcon={ChevronDown} onClick={onCall}>Audio call</Button>
|
|
58
|
+
</>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
40
61
|
|
|
41
62
|
/**
|
|
42
63
|
* ProfileCard — 人員 HoverCard 的內容元件
|
|
@@ -29,7 +29,7 @@ const Label = ({ children, warn }: { children: React.ReactNode; warn?: boolean }
|
|
|
29
29
|
|
|
30
30
|
const Section = ({ title, children }: { title: string; children: React.ReactNode }) => (
|
|
31
31
|
<section className="mb-12">
|
|
32
|
-
<h2 className="text-
|
|
32
|
+
<h2 className="text-h3 font-bold text-foreground mb-4 pb-2 border-b border-border">{title}</h2>
|
|
33
33
|
{children}
|
|
34
34
|
</section>
|
|
35
35
|
)
|
|
@@ -90,7 +90,7 @@ Item-level default / hover / checked / disabled **色彩**與 Checkbox 共用同
|
|
|
90
90
|
|
|
91
91
|
繼承 Field family,詳見 `../Field/field-controls.spec.md` + `../Field/form-validation.spec.md`。
|
|
92
92
|
|
|
93
|
-
**Field 內 readonly(2026-06-12 user 拍板)**:不渲染 radio 群組,改渲染 `fieldWrapperStyles` readonly 灰框 + 選中項 label(= Select readonly 同款,同為單選資料的鎖定呈現);standalone readonly 維持原樣鎖互動(ReadonlyContext)。
|
|
93
|
+
**Field 內 readonly(2026-06-12 user 拍板)**:不渲染 radio 群組,改渲染 `fieldWrapperStyles` readonly 灰框 + 選中項 label(= Select readonly 同款,同為單選資料的鎖定呈現);standalone readonly 維持原樣鎖互動(ReadonlyContext + item onClick preventDefault guard — 2026-07-05 D4 補:`<label htmlFor>` synthetic click 非 pointer event,`pointer-events-none` 攔不到,需 guard 才真鎖)。
|
|
94
94
|
|
|
95
95
|
---
|
|
96
96
|
|
|
@@ -112,7 +112,7 @@ Item-level default / hover / checked / disabled **色彩**與 Checkbox 共用同
|
|
|
112
112
|
- **極長 label / description**:預設不截斷、自然換行(`labelMaxLines` / `descMaxLines` 預設 `'none'`,Clamp 政策 SSOT 見 `checkbox.spec.md`「Clamp 政策」)。
|
|
113
113
|
- **icon / avatar prefix**:`RadioGroupItem` 一級 `icon` / `avatar` props 轉發 `SelectionItem` prefix 槽(2026-06-12 M30;規則 SSOT 見 `checkbox.spec.md` 同段 + `selection-item.spec.md`)。
|
|
114
114
|
- **RTL**:未實作方向鏡像;RTL 屬 DS-wide 決策,未定(與 Chip / Breadcrumb 同口徑)。
|
|
115
|
-
- **Dark mode / density**:走 SelectionItem semantic token 自動 adapt
|
|
115
|
+
- **Dark mode / density**:走 SelectionItem semantic token 自動 adapt;垂直行距由 SelectionItem `py = (field-height − 1lh) / 2` 公式消費 uiSize token(`--field-height-*`)生成,隨 density 自動調整(零外部 gap 機制 SSOT 見 `checkbox.spec.md`「群組模式」)。
|
|
116
116
|
|
|
117
117
|
---
|
|
118
118
|
|
|
@@ -44,7 +44,9 @@ export const Modes: Story = {
|
|
|
44
44
|
</div>
|
|
45
45
|
<div>
|
|
46
46
|
<h3 className="text-body font-bold text-foreground mb-2">disabled</h3>
|
|
47
|
-
|
|
47
|
+
{/* mode="disabled" → Radix Root disabled 原生 propagate 全 item(radio 控件真停用);
|
|
48
|
+
SelectionItem disabled 另管 label 降色 — 雙傳對齊「停用」story 寫法 */}
|
|
49
|
+
<RadioGroup mode="disabled" value="yearly" aria-label="付款方案(disabled mode demo)">
|
|
48
50
|
<SelectionItem control={<RadioGroupItem value="monthly" id="m-dis" />} label="月付方案" htmlFor="m-dis" disabled />
|
|
49
51
|
<SelectionItem control={<RadioGroupItem value="yearly" id="y-dis" />} label="年付方案" htmlFor="y-dis" disabled />
|
|
50
52
|
<SelectionItem control={<RadioGroupItem value="lifetime" id="l-dis" />} label="終身方案" htmlFor="l-dis" disabled />
|
|
@@ -80,14 +80,31 @@ const RadioGroup = React.forwardRef<
|
|
|
80
80
|
// 對齊 Carbon read-only single-select(只顯示 selected 內容)+ Airtable / Notion read-only。
|
|
81
81
|
// 實作:walk children 找 control.value === selectedValue 的 SelectionItem,render label plain text。
|
|
82
82
|
// (不用 context dispatch 給 RadioGroupItem — SelectionItem layout wrapper 仍會渲染所有 item label)
|
|
83
|
+
// 2026-07-04 修:display / readonly-in-Field 分支的 <div> 原丟棄剩餘 props(id/data-*/aria-*)
|
|
84
|
+
// 且不轉發 forwardRef ref → 自家 radio-group.stories.tsx display demo 傳的 aria-label 都靜默失效。
|
|
85
|
+
// 抽出 Radix 專屬 non-DOM props,其餘 DOM props 於兩分支 spread 轉發(與 Checkbox/Switch 同修);
|
|
86
|
+
// edit 主路徑不受影響(Root 仍 spread 完整 props)。
|
|
87
|
+
const {
|
|
88
|
+
onValueChange: _onValueChange,
|
|
89
|
+
disabled: _disabled,
|
|
90
|
+
required: _required,
|
|
91
|
+
name: _name,
|
|
92
|
+
orientation: _orientation,
|
|
93
|
+
dir: _dir,
|
|
94
|
+
loop: _loop,
|
|
95
|
+
asChild: _asChild,
|
|
96
|
+
children: _children,
|
|
97
|
+
...restDomProps
|
|
98
|
+
} = props as RadioGroupProps & { asChild?: boolean }
|
|
99
|
+
|
|
83
100
|
if (resolvedMode === 'display') {
|
|
84
101
|
const selectedValue = (value ?? defaultValue) as string | undefined
|
|
85
102
|
if (!selectedValue) {
|
|
86
|
-
return <div role="group" className={cn('grid', className)}><span className="text-fg-muted">{EMPTY_DISPLAY}</span></div>
|
|
103
|
+
return <div {...restDomProps} ref={ref as React.Ref<HTMLDivElement>} role="group" className={cn('grid', className)}><span className="text-fg-muted">{EMPTY_DISPLAY}</span></div>
|
|
87
104
|
}
|
|
88
105
|
const selectedLabel = findSelectedRadioLabel(props.children, selectedValue)
|
|
89
106
|
return (
|
|
90
|
-
<div role="group" className={cn('grid', className)}>
|
|
107
|
+
<div {...restDomProps} ref={ref as React.Ref<HTMLDivElement>} role="group" className={cn('grid', className)}>
|
|
91
108
|
<span className="text-foreground">{selectedLabel ?? selectedValue}</span>
|
|
92
109
|
</div>
|
|
93
110
|
)
|
|
@@ -103,6 +120,8 @@ const RadioGroup = React.forwardRef<
|
|
|
103
120
|
const boxSize = resolvedBoxSize
|
|
104
121
|
return (
|
|
105
122
|
<div
|
|
123
|
+
{...restDomProps}
|
|
124
|
+
ref={ref as React.Ref<HTMLDivElement>}
|
|
106
125
|
role="radiogroup"
|
|
107
126
|
aria-readonly="true"
|
|
108
127
|
aria-labelledby={fieldCtx?.labelId}
|
|
@@ -260,6 +279,18 @@ const RadioGroupItem = React.forwardRef<
|
|
|
260
279
|
tabIndex={effectiveReadonly ? -1 : undefined}
|
|
261
280
|
className={cn(radioItemVariants({ size }), className)}
|
|
262
281
|
{...props}
|
|
282
|
+
// 2026-07-05 D4 修:readOnly 鎖互動補 label 繞道 — <label htmlFor> 的 synthetic click
|
|
283
|
+
// 不是 pointer event,cva pointer-events-none 攔不到,點 label 文字仍選中。
|
|
284
|
+
// preventDefault 讓 Radix composeEventHandlers(checkForDefaultPrevented)跳過內部 onCheck;
|
|
285
|
+
// 必列在 {...props} 之後才不被 consumer onClick 覆蓋(與 Checkbox/Switch 同修)。
|
|
286
|
+
// 同時攔 Radix roving-focus 的 arrow-key onFocus → click() 路徑(同為 click event)。
|
|
287
|
+
onClick={(event) => {
|
|
288
|
+
if (effectiveReadonly) {
|
|
289
|
+
event.preventDefault()
|
|
290
|
+
return
|
|
291
|
+
}
|
|
292
|
+
props.onClick?.(event)
|
|
293
|
+
}}
|
|
263
294
|
>
|
|
264
295
|
<RadioGroupPrimitive.Indicator className="grid place-content-center">
|
|
265
296
|
<Circle
|
|
@@ -306,7 +337,10 @@ export const radioGroupMeta = {
|
|
|
306
337
|
md: { fieldHeight: 32, iconSize: 8, typography: 'body' },
|
|
307
338
|
lg: { fieldHeight: 36, iconSize: 10, typography: 'body-lg' },
|
|
308
339
|
},
|
|
309
|
-
|
|
340
|
+
// 2026-07-04 修 stale meta:移除 'active' — radioItemVariants cva 無 active-state 樣式,
|
|
341
|
+
// Radix radio 也無 data-state=active(對照 checkboxMeta 正確不含 active)
|
|
342
|
+
// 'checked' = 選定持續態(card 式 = border+text primary;2026-07-07 meta 詞彙統一補列)
|
|
343
|
+
states: ['default', 'hover', 'checked', 'focus-visible', 'disabled'],
|
|
310
344
|
tokens: {
|
|
311
345
|
bg: ['bg-disabled', 'bg-surface'],
|
|
312
346
|
fg: ['text-fg-disabled', 'text-fg-secondary', 'text-foreground', 'text-primary'],
|
|
@@ -11,18 +11,21 @@ export default meta
|
|
|
11
11
|
|
|
12
12
|
/* ── Data ─────────────────────────────────────────────── */
|
|
13
13
|
|
|
14
|
-
type SizeKey = 'sm' | 'md' | 'lg'
|
|
14
|
+
type SizeKey = 'xs' | 'sm' | 'md' | 'lg'
|
|
15
15
|
type PrecisionKey = 'full' | 'half'
|
|
16
16
|
type ModeKey = 'interactive' | 'readOnly' | 'disabled'
|
|
17
17
|
|
|
18
|
-
const SIZES: SizeKey[] = ['sm', 'md', 'lg']
|
|
19
|
-
// 對齊 item-anatomy inline Avatar(sm=20 / md=24 / lg=24),詳見 rating.spec.md
|
|
20
|
-
const SIZE_PX: Record<SizeKey, number> = { sm: 20, md: 24, lg: 24 }
|
|
18
|
+
const SIZES: SizeKey[] = ['xs', 'sm', 'md', 'lg']
|
|
19
|
+
// 對齊 item-anatomy inline Avatar(sm=20 / md=24 / lg=24),詳見 rating.spec.md「為什麼不完全對齊 icon tier — Icon 尺寸對齊 Avatar inline」
|
|
20
|
+
const SIZE_PX: Record<SizeKey, number> = { xs: 20, sm: 20, md: 24, lg: 24 }
|
|
21
21
|
|
|
22
|
+
// 對齊 rating.spec.md「Size」表 canonical:xs = standalone 預設(商品卡 / 評論列表旁 / 搜尋結果 row,
|
|
23
|
+
// component default),sm/md/lg 為 Field 配對尺寸(2026-07-04 補 xs — SizeMatrix 不該藏預設尺寸)
|
|
22
24
|
const SIZE_USE: Record<SizeKey, string> = {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
xs: 'Standalone 預設 — 商品卡 / 評論列表旁(component default,container 24 / icon 20)',
|
|
26
|
+
sm: 'Field sm 並排(Field 配對尺寸)',
|
|
27
|
+
md: 'Field 預設 — 一般表單評分欄位',
|
|
28
|
+
lg: '送出評分的 review form、強調的主 CTA 區塊',
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
/* ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -363,7 +366,7 @@ export const SizeMatrix = {
|
|
|
363
366
|
<tbody>
|
|
364
367
|
{SIZES.map((sz) => (
|
|
365
368
|
<tr key={sz}>
|
|
366
|
-
<Td mono>{sz}{sz === 'md' ? ' ★default' : ''}</Td>
|
|
369
|
+
<Td mono>{sz}{sz === 'md' ? ' ★Field default' : ''}</Td>
|
|
367
370
|
<Td mono>{SIZE_PX[sz]}px</Td>
|
|
368
371
|
<Td mono>gap-1 (4px)</Td>
|
|
369
372
|
<Td>{SIZE_USE[sz]}</Td>
|
|
@@ -288,7 +288,7 @@ export const YellowStarConvention: Story = {
|
|
|
288
288
|
<Rating value={4.5} readOnly precision="half" size="lg" aria-label="誤用範例" icon={Star} />
|
|
289
289
|
</div>
|
|
290
290
|
</div>
|
|
291
|
-
<Label warn>藍星讓使用者猶豫「這是什麼」→ 一瞬間流失 = 設計 bug
|
|
291
|
+
<Label warn>藍星讓使用者猶豫「這是什麼」→ 一瞬間流失 = 設計 bug。(上例外層雖掛 color: var(--primary),渲染仍是黃星——星色由 rating.tsx fill 硬綁 --warning,非 currentColor,機械保證此誤用做不出來)</Label>
|
|
292
292
|
</div>
|
|
293
293
|
</Rule>
|
|
294
294
|
</div>
|
|
@@ -72,13 +72,13 @@ Rating 是**離散 1–5 分評分元件**——使用者對商品、服務、
|
|
|
72
72
|
| `md` | 32px(`h-field-md`) | 24px | **Field 預設**。一般表單評分欄位 | field md |
|
|
73
73
|
| `lg` | 36px(`h-field-lg`) | 24px | 送出評分的 review form、強調的主 CTA 區塊 | field lg |
|
|
74
74
|
|
|
75
|
-
### Standalone vs Field 尺寸選擇(canonical)
|
|
75
|
+
### 為什麼不 default md — Standalone vs Field 尺寸選擇(canonical)
|
|
76
76
|
|
|
77
77
|
- **Standalone 展示**(非 Field 內):用 **`xs`**(container 24 / icon 20)——對齊 Avatar sm 20px / Tag sm;Airbnb / Yelp 商品卡星星亦此大小 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
|
|
78
78
|
- **Field 內**(`<Field>` 表單內當 control):跟 Field size 對應傳 sm/md/lg(Field 預設 md)
|
|
79
79
|
- 世界級對照:Material Rating standalone ≈ 24dp;Ant Rate 在 Form 內跟 Form itemSize。兩種 context 分開設計,不強求單一預設 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
|
|
80
80
|
|
|
81
|
-
### Icon 尺寸對齊 **Avatar inline
|
|
81
|
+
### 為什麼不完全對齊 icon tier — Icon 尺寸對齊 **Avatar inline**(2026-04-21 AR48 canonical)
|
|
82
82
|
|
|
83
83
|
Rating 的 **container 高度消費 `--field-height-*` token**(sm=28 / md=32 / lg=36),讓它可以與 Input / Select / NumberInput / Button 等 field-height family 元件並排時 row-align 一致。
|
|
84
84
|
|
|
@@ -261,10 +261,10 @@ function StarIcon({ Icon, sizePx, fillRatio, isHalf, interactive, onHover, onCli
|
|
|
261
261
|
|
|
262
262
|
// Half: 兩個重疊 icon,左半 filled / 右半 empty + 兩個 hover zone 切半星
|
|
263
263
|
return (
|
|
264
|
-
<span className="relative inline-flex" style={{ width: sizePx, height: sizePx }}>
|
|
265
|
-
<Icon size={sizePx} fill={FILL_EMPTY} stroke="none" className="absolute inset-0" style={{ color: FILL_EMPTY }} />
|
|
264
|
+
<span aria-hidden className="relative inline-flex" style={{ width: sizePx, height: sizePx }}>
|
|
265
|
+
<Icon size={sizePx} fill={FILL_EMPTY} stroke="none" aria-hidden className="absolute inset-0" style={{ color: FILL_EMPTY }} />
|
|
266
266
|
<span className="absolute inset-0 overflow-hidden" style={{ width: sizePx * fillRatio }}>
|
|
267
|
-
<Icon size={sizePx} fill={FILL_FILLED} stroke="none" style={{ color: FILL_FILLED }} />
|
|
267
|
+
<Icon size={sizePx} fill={FILL_FILLED} stroke="none" aria-hidden style={{ color: FILL_FILLED }} />
|
|
268
268
|
</span>
|
|
269
269
|
{interactive && (
|
|
270
270
|
<>
|
|
@@ -3,6 +3,7 @@ component: ScrollArea
|
|
|
3
3
|
family: self-contained
|
|
4
4
|
variants: {}
|
|
5
5
|
sizes: {}
|
|
6
|
+
traits: [] # Radix wrapper 捲軸 primitive,無 trait variants(R3 trait enforce 無適用項;2026-07-04 dim 29 補宣告)
|
|
6
7
|
benchmark:
|
|
7
8
|
- Radix ScrollArea primitive: github.com/radix-ui/primitives/tree/main/packages/react/scroll-area
|
|
8
9
|
---
|
|
@@ -92,7 +92,7 @@ ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
|
|
|
92
92
|
// Phase 2 fill needed: purpose descriptions + when rationale + world-class refs
|
|
93
93
|
export const scrollAreaMeta = {
|
|
94
94
|
component: 'ScrollArea',
|
|
95
|
-
family:
|
|
95
|
+
family: 'self-contained', // 對齊 scroll-area.spec.md frontmatter(SSOT;同 Separator/OverflowIndicator meta 寫法)
|
|
96
96
|
variants: {
|
|
97
97
|
|
|
98
98
|
},
|
|
@@ -168,8 +168,8 @@ export const StateBehavior: Story = {
|
|
|
168
168
|
<tbody>
|
|
169
169
|
<tr><Td>Unselected</Td><Td><TokenCell token="--surface" display="bg-surface" /></Td><Td><TokenCell token="--fg-secondary" display="text-fg-secondary" /></Td><Td><TokenCell token="--border" display="border-border" /></Td><Td>—</Td></tr>
|
|
170
170
|
<tr><Td>Hover unselected</Td><Td><TokenCell token="--surface" display="bg-surface(不變)" /></Td><Td><TokenCell token="--foreground" display="text-foreground" /></Td><Td><TokenCell token="--border-hover" display="border-border-hover" /></Td><Td mono>z-[5](hover 邊框浮上)</Td></tr>
|
|
171
|
-
<tr><Td>Selected</Td><Td><TokenCell token="--surface" display="bg-surface" /></Td><Td><TokenCell token="--primary
|
|
172
|
-
<tr><Td>Disabled</Td><Td
|
|
171
|
+
<tr><Td>Selected</Td><Td><TokenCell token="--surface" display="bg-surface" /></Td><Td><TokenCell token="--primary" display="text-primary" /></Td><Td><TokenCell token="--primary" display="border-primary" /></Td><Td mono>z-10(浮在相鄰 item border 上)</Td></tr>
|
|
172
|
+
<tr><Td>Disabled</Td><Td>bg-surface(不變)</Td><Td>text-fg-disabled</Td><Td>border-border(不變,hover 鎖定)</Td><Td>—</Td></tr>
|
|
173
173
|
</tbody>
|
|
174
174
|
</table>
|
|
175
175
|
</div>
|
|
@@ -289,7 +289,7 @@ export const Accessibility = {
|
|
|
289
289
|
render: () => (
|
|
290
290
|
<div className="max-w-3xl text-body text-fg-secondary">
|
|
291
291
|
<h3 className="text-h5 text-foreground mb-2">無障礙設計</h3>
|
|
292
|
-
<p className="whitespace-pre-line">{" ARIA / Pattern :繼承 Radix toggle-group primitive 的無障礙預設——整組 role=\"group\",每個 item role=\"radio\"(type=\"single\" 互斥選一),鍵盤導覽由 primitive 處理。詳 [Radix Accessibility docs](https://www.radix-ui.com/primitives/docs/components/toggle-group#accessibility)。\n\n Keyboard 行為 :\n\n- Tab — 進入整組(只有一個 tab
|
|
292
|
+
<p className="whitespace-pre-line">{" ARIA / Pattern :繼承 Radix toggle-group primitive 的無障礙預設——整組 role=\"group\",每個 item role=\"radio\"(type=\"single\" 互斥選一),鍵盤導覽由 primitive 處理。詳 [Radix Accessibility docs](https://www.radix-ui.com/primitives/docs/components/toggle-group#accessibility)。\n\n Keyboard 行為 :\n\n- Tab — 進入整組(只有一個 tab 停留點,落在選中項;沒選就落在上次 focus 過的 item,初次進入才是第一項)\n- ←/→ — 在 item 之間移動 roving focus(只移焦點,不切換選取)。WAI-ARIA APG 對水平 segmented/radio group 的主要導覽鍵\n- ↑/↓ — 同 ←/→,也會在 item 間移動 roving focus。Radix toggle-group 未鎖 orientation(沿用 default 雙軸 roving),APG 接受 group 同時支援兩軸方向鍵\n- Enter / Space — 選取目前 focus 的 item\n\n Focus :採 roving tabindex——整組共用一個 tab 停留點,方向鍵在 item 間移動焦點(選取仍需 Enter/Space/click);不是 Dialog 那種把焦點關在裡面的 focus trap。Focus ring 對齊 Button:focus-visible:ring-2 ring-ring ring-offset-1(box-shadow ring,非 CSS outline)。\n\n 驗證 :Storybook a11y addon panel 應 0 critical violation;鍵盤完整可操作(無需滑鼠)。WCAG AA contrast ≥ 4.5:1(text)/ 3:1(UI)。"}</p>
|
|
293
293
|
</div>
|
|
294
294
|
),
|
|
295
295
|
}
|
|
@@ -58,6 +58,7 @@ SegmentedControl 是**互斥多選一的 compact control**——從 2–5 個選
|
|
|
58
58
|
| 只有 1 個 | `Button pressed` | 沒有選擇語意 |
|
|
59
59
|
| 切換的是 container 結構(整塊 view 有自己的 header / toolbar / filters)| `Tabs` | 見下「與 Tabs 的分界」 |
|
|
60
60
|
| 選項需要描述文字 / 複雜排版 | `RadioGroup` | compact control 不支援多行內容 |
|
|
61
|
+
| 頁碼導覽(大量資料翻頁) | `Pagination` | 位置導覽非互斥選值——頁數動態、可摺疊、數字無語意(見 `../Pagination/pagination.spec.md` 近親分界) |
|
|
61
62
|
|
|
62
63
|
---
|
|
63
64
|
|
|
@@ -207,7 +208,9 @@ SegmentedControl 必須能塞進 `Field` 容器(就像 `Input` / `Button` / `S
|
|
|
207
208
|
|
|
208
209
|
### 選中 / 未選
|
|
209
210
|
|
|
210
|
-
- **選中**:文字與邊框都用 `--primary
|
|
211
|
+
- **選中**:文字與邊框都用 `--primary`(底色維持 surface 不變)——pill 風格元件(Chip / SegmentedControl)共用的選中規則(semantic.css「選中狀態」段 SSOT;2026-07-06 拍板自 primary-hover 改 base,hover 階專屬瞬時態);selected item 提升 z-index 讓邊框浮在相鄰 item 之上,避免被重疊的 border 切掉(class 實作見 `segmented-control.tsx` `data-[state=on]` cva)。**❌ 選中態不得用 primary-hover**
|
|
212
|
+
- **選中之上的 hover**:`--primary-hover` 同時染文字與邊框——選中元素的 hover = 同色相升 hover 階(2026-07-06 拍板;Button pressed hover 家族 + Ant active hover 同派,跟 Chip 一致),不用 neutral 灰底
|
|
213
|
+
- **disabled × 選中疊加**:disabled 全滅(primary 描邊/染字退場 → `border-border` + `fg-disabled`)——M24 state > emphasis,跟 Chip 一致(2026-07-07 補明文)
|
|
211
214
|
- **未選**:surface 底 + `--fg-secondary` 文字 + `--border` 邊框
|
|
212
215
|
- hover:文字轉 `--foreground` + 邊框加深一階(`--border-hover`)+ 微提升 z-index;不改 bg,避免 hover 狀態與 selected 搶戲
|
|
213
216
|
|
|
@@ -256,7 +259,7 @@ Items 之間 `-ml-px`(除了第一個)讓相鄰 border 重疊、視覺上只
|
|
|
256
259
|
|
|
257
260
|
## 為何無 ColorMatrix
|
|
258
261
|
|
|
259
|
-
- **無 ColorMatrix**:SegmentedControl 沒有 Button 那種強調層級 variant(primary / secondary / tertiary / text)——只有「選中 / 未選」兩種 **state**,色彩變化純由 state 驅動(底色恆為 `bg-surface` 不變;選中 = `text-primary
|
|
262
|
+
- **無 ColorMatrix**:SegmentedControl 沒有 Button 那種強調層級 variant(primary / secondary / tertiary / text)——只有「選中 / 未選」兩種 **state**,色彩變化純由 state 驅動(底色恆為 `bg-surface` 不變;選中 = `text-primary` + `border-primary`;未選 hover = `text-foreground`,詳「狀態」段)。這是 pill 風格元件(Chip / SegmentedControl)共用的選中規則,非 Button variant。因此 ColorMatrix(逐 variant 列色)不適用,狀態色已在 `StateBehavior` 完整覆蓋。
|
|
260
263
|
|
|
261
264
|
對應 anatomy story:`Overview` + `Inspector` + `SizeMatrix` + `StateBehavior` + 元件特有 `FullWidthMatrix` + `IconOnlyMatrix` + `Accessibility`。Inspector 用 Storybook Controls 即時切 `size` × `fullWidth` × `iconOnly`(取代 Figma inspect);三張矩陣 story(`SizeMatrix` / `FullWidthMatrix` / `IconOnlyMatrix`)則提供結構性並排對照,兩者互補。
|
|
262
265
|
|
|
@@ -275,7 +278,7 @@ Items 之間 `-ml-px`(除了第一個)讓相鄰 border 重疊、視覺上只
|
|
|
275
278
|
|
|
276
279
|
**Keyboard 行為**:
|
|
277
280
|
|
|
278
|
-
- Tab — 進入 group(focus
|
|
281
|
+
- Tab — 進入 group(focus 落在選中項;無選中時落在上次 focus 過的 item——Radix roving focus 記住停留點,初次進入才是第一項)
|
|
279
282
|
- ←/→ — 在 item 間移動 roving focus(只移焦點,不切換選取)。WAI-ARIA APG 對水平 segmented/radio group 的主要導覽鍵
|
|
280
283
|
- ↑/↓ — 同 ←/→,也會在 item 間移動 roving focus。Radix `toggle-group` 未鎖 `orientation`(沿用 default 雙軸 roving),APG 接受 group 同時支援兩軸方向鍵
|
|
281
284
|
- Enter / Space — 選取目前 focus 的 item
|
|
@@ -291,6 +294,7 @@ Items 之間 `-ml-px`(除了第一個)讓相鄰 border 重疊、視覺上只
|
|
|
291
294
|
- `button.spec.md`
|
|
292
295
|
- `chip.spec.md`
|
|
293
296
|
- `horizontal-overflow.spec.md`
|
|
297
|
+
- `pagination.spec.md`
|
|
294
298
|
- `radio-group.spec.md`
|
|
295
299
|
- `select.spec.md`
|
|
296
300
|
- `slider.spec.md`
|
|
@@ -105,6 +105,11 @@ const SegmentedControl = React.forwardRef<
|
|
|
105
105
|
const resolvedSize = useResolvedFieldSize<SegmentedControlSize>(sizeProp, 'md') // SSOT:統一 size resolution(原散落 ?? fieldCtx?.size ?? 'md')
|
|
106
106
|
const resolvedDisabled = useResolvedFieldDisabled(disabled)
|
|
107
107
|
|
|
108
|
+
// 2026-07-04:恆 controlled mirror(見下方 onValueChange 註解)— uncontrolled consumer 的
|
|
109
|
+
// defaultValue 收進 internal state,Radix 永遠拿 controlled value → deselect 空值可攔。
|
|
110
|
+
const [internalValue, setInternalValue] = React.useState(defaultValue ?? '') // '' = controlled 無選取(恆 controlled 從 mount 起,避免 un→controlled 切換)
|
|
111
|
+
const resolvedValue = value !== undefined ? value : internalValue
|
|
112
|
+
|
|
108
113
|
// Memoize provider value(2026-04-22 D3 perf audit):避免每次父 render 重建 4-field object
|
|
109
114
|
// 讓 children SegmentedControlItem 不必要 re-render
|
|
110
115
|
const ctxValue = React.useMemo(
|
|
@@ -117,12 +122,16 @@ const SegmentedControl = React.forwardRef<
|
|
|
117
122
|
<ToggleGroupPrimitive.Root
|
|
118
123
|
ref={ref}
|
|
119
124
|
type="single"
|
|
120
|
-
value={
|
|
121
|
-
defaultValue={defaultValue}
|
|
125
|
+
value={resolvedValue}
|
|
122
126
|
onValueChange={(v) => {
|
|
123
127
|
// Radix 的 single ToggleGroup 允許 deselect(返回空字串)
|
|
124
|
-
// SegmentedControl 是 radio 語意,不允許空值——忽略 deselect
|
|
125
|
-
|
|
128
|
+
// SegmentedControl 是 radio 語意,不允許空值——忽略 deselect。
|
|
129
|
+
// 2026-07-04 修:原 uncontrolled(只傳 defaultValue)時 Radix 內部 state 直通,
|
|
130
|
+
// 點已選中項照樣 deselect 成空值(spec:236「恆有一值」失守)→ wrapper 恆 controlled
|
|
131
|
+
// (internalValue mirror),空字串一律不進 state 也不呼叫 consumer callback。
|
|
132
|
+
if (!v) return
|
|
133
|
+
if (value === undefined) setInternalValue(v)
|
|
134
|
+
onValueChange?.(v)
|
|
126
135
|
}}
|
|
127
136
|
disabled={resolvedDisabled}
|
|
128
137
|
className={cn(segmentedControlVariants({ fullWidth }), className)}
|
|
@@ -166,12 +175,19 @@ const itemVariants = cva(
|
|
|
166
175
|
'disabled:hover:text-fg-disabled disabled:hover:border-border',
|
|
167
176
|
// hover(未選):border 加深一階 + 文字轉深,對齊 Input / Chip hover
|
|
168
177
|
'hover:text-foreground hover:border-border-hover hover:z-[5]',
|
|
169
|
-
// selected: 文字 + 邊框都用 primary
|
|
170
|
-
// ── 這是 pill 風格元件 (Chip / SegmentedControl) 的 canonical
|
|
171
|
-
// primary
|
|
172
|
-
//
|
|
178
|
+
// selected: 文字 + 邊框都用 primary base,底色維持 bg-surface 不變 (跟 Chip 一致)
|
|
179
|
+
// ── 這是 pill 風格元件 (Chip / SegmentedControl) 的 canonical 選中規則(SSOT = semantic.css「選中狀態」段):
|
|
180
|
+
// primary base 同時染文字和線條;底色不改 (不用 primary-subtle)。
|
|
181
|
+
// 2026-07-06 user 拍板:持續選中 hover 階 → base(三家世界級「瞬時弱、持續強」實錘)。
|
|
182
|
+
// Tabs 是 underline 風格,規則不同 (文字 foreground + 底線 primary)。
|
|
173
183
|
// z-10 讓 border 浮在相鄰 item 之上
|
|
174
|
-
'data-[state=on]:text-primary
|
|
184
|
+
'data-[state=on]:text-primary data-[state=on]:border-primary data-[state=on]:z-10',
|
|
185
|
+
// 選中之上的 hover = 同色相升 hover 階(2026-07-06 user 拍板;Button pressed hover 家族
|
|
186
|
+
// + Ant active hover 同派;跟 Chip 一致,顯式宣告解掉 CSS 平手 source-order 脆弱性)
|
|
187
|
+
'data-[state=on]:hover:text-primary-hover data-[state=on]:hover:border-primary-hover',
|
|
188
|
+
// disabled × selected 疊加(2026-07-07 user 拍板統一;M24 disabled 全滅,同 Chip)
|
|
189
|
+
'data-[state=on]:disabled:border-border data-[state=on]:disabled:text-fg-disabled',
|
|
190
|
+
'data-[state=on]:disabled:hover:border-border data-[state=on]:disabled:hover:text-fg-disabled',
|
|
175
191
|
// item 連體:除第一個外,-ml-px 讓相鄰 border 重疊
|
|
176
192
|
'first:rounded-l-md last:rounded-r-md',
|
|
177
193
|
'[&:not(:first-child)]:-ml-px',
|
|
@@ -290,10 +306,12 @@ export const segmentedControlMeta = {
|
|
|
290
306
|
md: { fieldHeight: 32, typography: 'body', iconSize: 16, purpose: '預設 — form field 對齊' },
|
|
291
307
|
lg: { fieldHeight: 36, typography: 'body-lg', iconSize: 20, purpose: 'touch / prominent CTA' },
|
|
292
308
|
},
|
|
293
|
-
|
|
309
|
+
// 2026-07-04 audit 對齊:cva 無 active(按下)專屬樣式,移除 'active'
|
|
310
|
+
// 'selected' = data-[state=on](2026-07-07 meta 詞彙統一補列:持續選中一律 'selected';cva 無按壓 active 樣式)
|
|
311
|
+
states: ['default', 'hover', 'selected', 'focus-visible', 'disabled'],
|
|
294
312
|
tokens: {
|
|
295
313
|
bg: ['bg-surface'],
|
|
296
|
-
fg: ['text-fg-disabled', 'text-fg-secondary', 'text-foreground'],
|
|
314
|
+
fg: ['text-fg-disabled', 'text-fg-secondary', 'text-foreground', 'text-primary'], // selected 態 cva data-[state=on]:text-primary 實際消費(2026-07-06 選中改 base)
|
|
297
315
|
ring: ['ring-ring'],
|
|
298
316
|
},
|
|
299
317
|
defaultSize: 'md',
|
|
@@ -62,7 +62,7 @@ const TOKEN_MAP: Record<ModeKey, Record<StateKey, ColorSpec>> = {
|
|
|
62
62
|
},
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
// Error state tokens (edit only) — traced from select.tsx
|
|
65
|
+
// Error state tokens (edit only) — traced from select.tsx:431/444/598(NativeSelect 兩處 + CustomSelect trigger)
|
|
66
66
|
// border-error hover:border-error-hover, focus-within:border-error
|
|
67
67
|
const ERROR_TOKENS: Record<StateKey, ColorSpec> = {
|
|
68
68
|
default: { bg: '--surface', text: '--foreground', border: '--error', icon: '--fg-muted' },
|
|
@@ -324,7 +324,7 @@ export const Overview = {
|
|
|
324
324
|
['onOpenChange', '(open: boolean) => void', '—', 'open 狀態變更 callback'],
|
|
325
325
|
['showDisplayEndIcon', 'boolean', 'false', 'display 模式渲 ChevronDown(DataTable cell 對齊)'],
|
|
326
326
|
['selectedItemRenderer', '(opt: SelectOption) => ReactNode', '—', 'trigger 已選項目客製 render(PeoplePicker 用)'],
|
|
327
|
-
['disabled', 'boolean', '—', '
|
|
327
|
+
['disabled', 'boolean', '—', '原生屬性;未傳 mode 時 resolve 為 disabled 樣式(顯式 mode prop 恆優先,見 useResolvedFieldMode)'],
|
|
328
328
|
].map(([p, t, d, desc]) => (
|
|
329
329
|
<tr key={p}><Td mono>{p}</Td><Td mono>{t}</Td><Td mono>{d}</Td><Td>{desc}</Td></tr>
|
|
330
330
|
))}
|
|
@@ -273,7 +273,7 @@ Select 的值套用時機是**由 onChange handler 的副作用決定**,不是
|
|
|
273
273
|
|
|
274
274
|
## Loading
|
|
275
275
|
|
|
276
|
-
`loading?: boolean`(forward 給 SelectMenu SSOT,2026-05-15 audit B
|
|
276
|
+
`loading?: boolean`(forward 給 SelectMenu SSOT,2026-05-15 audit B 補;**2026-07-04 Q3 拍板措辭修訂 — 不清空 stale options**):spinner 只在**無可顯示選項時**佔 empty slot 顯 `<Empty icon={<CircularProgress size={48}/>}/>`(cmdk `CommandEmpty` 機制;已有 options 時保留顯示,不取代)+ `aria-busy`。Trigger 不變(chevron 保留,user 隨時可開)。Benchmark 實查:MUI Autocomplete 官方逐字「shows the loadingText in place of suggestions **only if there are no suggestions to show**」/ Ant Select 清空是 consumer 自選(demo select-users.tsx setOptions([]))非元件行為 — 原「取代 options」是過度宣稱,code 行為即世界級共識。
|
|
277
277
|
|
|
278
278
|
---
|
|
279
279
|
|
|
@@ -313,12 +313,13 @@ Select 是 **Field Controls family 成員**——互動狀態(focus / invalid /
|
|
|
313
313
|
|
|
314
314
|
## A11y 預設
|
|
315
315
|
|
|
316
|
-
**ARIA / Pattern**:依裝置分兩條路徑。桌機(非觸控)觸發點是容器 `<div>`,標記 `role="combobox"` + `aria-expanded` / `aria-haspopup="listbox"`,選項在浮層 listbox 裡;searchable 模式時容器內另放可打字篩選的 `<input
|
|
316
|
+
**ARIA / Pattern**:依裝置分兩條路徑。桌機(非觸控)觸發點是容器 `<div>`,標記 `role="combobox"` + `aria-expanded` / `aria-haspopup="listbox"`,選項在浮層 listbox 裡;searchable 模式時容器內另放可打字篩選的 `<input>`(開啟時實際聚焦的元素,accessible name 直接接在 input 本身:有 Field label 時 `aria-labelledby` 指向之、consumer `aria-label` 優先,兩者皆無時 fallback「搜尋選項」——與 Combobox 搜尋框 `searchAriaLabel` 同 canonical)。手機(觸控)改用瀏覽器原生 `<select>` element,直接取得作業系統內建的無障礙與 picker。兩路徑皆由 Field wrapper 補 `aria-invalid` / `aria-required` / `aria-describedby` / `aria-errormessage`。
|
|
317
317
|
|
|
318
318
|
**Keyboard 行為**:
|
|
319
319
|
|
|
320
320
|
- Tab — 聚焦到觸發點
|
|
321
321
|
- Enter / Space — 展開選單(searchable 模式則直接進入打字篩選)
|
|
322
|
+
- ↓ — 選單關閉時亦可直接展開(APG combobox 展開鍵,與 Combobox 同 pattern;展開後不攔,讓方向鍵導覽選單)
|
|
322
323
|
- ↑ / ↓ — 選單展開後在選項間移動
|
|
323
324
|
- Esc — 關閉選單(清除值走右側 clear 按鈕,非 Esc)
|
|
324
325
|
|