@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
|
@@ -70,7 +70,7 @@ Semantic token 直接指向 primitive(無中間層)。
|
|
|
70
70
|
**注意(categorical `red` vs semantic `--error` vs primitive `deep-orange` 三者獨立)**:
|
|
71
71
|
- `--error` = `--color-deep-orange-6`(primitive `deep-orange`,hue 38)—— semantic 狀態色,用於錯誤訊息。
|
|
72
72
|
- Tag / Avatar / Calendar 的 categorical `red` variant = `--color-red-*`(品牌紅家族 hue 25,與 `--brand` `#DF3232` 同族)。
|
|
73
|
-
-
|
|
73
|
+
- **三者無映射關係**:categorical `red`(hue 25)≠ `deep-orange`(primitive hue 38)≠ `--error`(semantic = deep-orange)。categorical 色相 1:1 對 `--color-{hue}-*`,零 offset(SSOT `tokens/categorical-color.ts`)。2026-06-04 修正原「red variant 接 deep-orange」offset。
|
|
74
74
|
|
|
75
75
|
Tailwind utility 透過 `@theme inline` 橋接 semantic token,元件寫 `bg-primary` 或 `bg-error` 即可。Tag / Avatar 使用 CSS 變數任意值(`bg-[var(--color-blue-6)]`)。
|
|
76
76
|
|
|
@@ -174,6 +174,8 @@ Semantic token 按**載體類型**分成四個 family,**family 之間的 token
|
|
|
174
174
|
|
|
175
175
|
## Icon 色彩原則
|
|
176
176
|
|
|
177
|
+
Icon 色彩 canonical 的 SSOT 住 `patterns/element-anatomy/item-anatomy.spec.md`「Icon 色彩原則」——核心規則:icon 代表內容/類別 → 與 label 同色;icon 純指示方向 → `fg-muted`;disabled 統一 `fg-disabled`。本檔不重述(Rule-of-3 pointer)。
|
|
178
|
+
|
|
177
179
|
## 語義色
|
|
178
180
|
|
|
179
181
|
### Action — Primary
|
|
@@ -225,7 +227,7 @@ Semantic token 按**載體類型**分成四個 family,**family 之間的 token
|
|
|
225
227
|
|
|
226
228
|
| 底色 | 文字色 | 原因 |
|
|
227
229
|
|------|--------|------|
|
|
228
|
-
| `bg-warning`(yellow-6,滿版) | `text-on-emphasis-dark`(`black-a85`,深色) | 黃色亮度高,白字對比不足,必須用深色(通用亮底深字 token,非 warning
|
|
230
|
+
| `bg-warning`(yellow-6,滿版) | `text-on-emphasis-dark`(`black-a85`,深色) | 黃色亮度高,白字對比不足,必須用深色(通用亮底深字 token,非 warning 專屬;定義見下「`--on-emphasis` / `--on-emphasis-dark` 配對」段) |
|
|
229
231
|
| `bg-warning-subtle`(淡黃) | `text-[yellow-7]`(step-7) | subtle 底色夠淺,深一階的黃色文字可辨識(見「文字色 Step 原則」) |
|
|
230
232
|
|
|
231
233
|
### Indicator — Notification
|
|
@@ -455,7 +457,7 @@ Dark mode 覆寫:hover/active 方向反轉(hover → step-7,active → ste
|
|
|
455
457
|
- 跨 mode 一致的方向(dark mode 必須 swap step 號)
|
|
456
458
|
- 但 Tag 的「藍」≠ semantic primary(解耦:改 primary 不應影響 Tag)
|
|
457
459
|
|
|
458
|
-
直接用 primitive `--color-blue-5/-7` 不行——dark mode 公式互換會方向顛倒。所以擴展 semantic 互動 token
|
|
460
|
+
直接用 primitive `--color-blue-5/-7` 不行——dark mode 公式互換會方向顛倒。所以擴展 semantic 互動 token 模式到全部 12 個 categorical 色相(SSOT `tokens/categorical-color.ts` `CATEGORICAL_HUES`)。
|
|
459
461
|
|
|
460
462
|
#### 嚴格限制
|
|
461
463
|
|
|
@@ -657,7 +659,7 @@ Dark mode 覆寫:hover/active 方向反轉(hover → step-7,active → ste
|
|
|
657
659
|
|
|
658
660
|
**跟 `bg-neutral-hover` / `bg-neutral-active` 的區別**:neutral 系列表達**互動**狀態(hover / 選中);muted / secondary 表達**結構性的靜態層級** — 即使沒有互動,它永遠是這個顏色。
|
|
659
661
|
|
|
660
|
-
**邊界 — component disabled bg 不走 muted**:Button / Input / Checkbox 等元件 disabled state 走 `--bg-disabled` semantic,不是 `--muted`(同值 neutral-2 但不同 owner — `--bg-disabled` 是 component-state token,`--muted` 是 surface-non-interactive token,per
|
|
662
|
+
**邊界 — component disabled bg 不走 muted**:Button / Input / Checkbox 等元件 disabled state 走 `--bg-disabled` semantic,不是 `--muted`(同值 neutral-2 但不同 owner — `--bg-disabled` 是 component-state token,`--muted` 是 surface-non-interactive token,per「為什麼同值仍分兩個 token」段 rule)。**Readonly state 同理但用自己的 token `--bg-readonly`**(2026-06-10):readonly ≠ disabled(可聚焦/選取/提交,僅不可改值,per Carbon「navigable but not operable」),不借 `--bg-disabled` 名;也不走 `--muted`(readonly 是互動元件 state,非 Skeleton 類靜態 surface)。三者同值 neutral-2、owner 獨立,可分離演進。
|
|
661
663
|
|
|
662
664
|
```tsx
|
|
663
665
|
<Skeleton className="h-4 w-32" /> {/* bg-muted — placeholder 語意 */}
|
|
@@ -755,6 +757,16 @@ CSS 變數在定義元素上解析。`:root` 的 `--foreground: var(--color-neut
|
|
|
755
757
|
|
|
756
758
|
容器自身的樣式(如 tooltip 的 `bg-tooltip`)不受子 div 的 `data-theme` 影響——`data-theme` 在子 div 上,只影響子元素。
|
|
757
759
|
|
|
760
|
+
## 常見誤解
|
|
761
|
+
|
|
762
|
+
各誤解的完整推理已在本檔對應段落,此處彙整索引:
|
|
763
|
+
|
|
764
|
+
- 「`--primary` 跟 `--info` 同色所以可互換」— 語義截然不同,status 元件混入 `--primary` 即 fail(見「Status」段 + `status-color-invariant.mjs`)。
|
|
765
|
+
- 「`--fg-disabled` 剛好是我要的灰,拿來當 bg」— 跨 family 借用是 smell(見「fg token 不可當 bg 用」段 Slider case)。
|
|
766
|
+
- 「`bg-muted` / `bg-secondary` 都是淡灰隨便選」— 前者 = 退化 / placeholder,後者 = 正常存在但退後一級(見「Static Subtle Background」段)。
|
|
767
|
+
- 「`--neutral-active` / `--neutral-selected` 同值可合併」— transient vs persistent 語意獨立(見「active vs selected」段)。
|
|
768
|
+
- 「categorical `red` = `--error`」— hue 25 vs deep-orange,完全無關(見「消費規則」注意事項)。
|
|
769
|
+
|
|
758
770
|
## 禁止事項
|
|
759
771
|
|
|
760
772
|
```tsx
|
|
@@ -774,16 +786,11 @@ SSOT → `.claude/references/structural-token-retention.md`(6 類保留 + sub-ag
|
|
|
774
786
|
|
|
775
787
|
> 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
|
|
776
788
|
|
|
777
|
-
- `opacity.spec.md`
|
|
778
|
-
|
|
779
|
-
## 被引用(auto-maintained,Dim 3 reciprocal audit)
|
|
780
|
-
|
|
781
|
-
> 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
|
|
782
|
-
|
|
783
789
|
- `chart.spec.md`
|
|
784
790
|
- `date-grid.spec.md`
|
|
785
791
|
- `file-item.spec.md`
|
|
786
792
|
- `notice.spec.md`
|
|
793
|
+
- `opacity.spec.md`
|
|
787
794
|
- `progress-bar.spec.md`
|
|
788
795
|
- `separator.spec.md`
|
|
789
796
|
- `skeleton.spec.md`
|
|
@@ -328,6 +328,7 @@
|
|
|
328
328
|
--neutral-hover: var(--color-neutral-1);
|
|
329
329
|
--neutral-active: var(--color-neutral-2);
|
|
330
330
|
--bg-disabled: var(--color-neutral-2);
|
|
331
|
+
--bg-readonly: var(--color-neutral-2); /* readonly 鎖定欄位 chrome — 同值但獨立 owner(≠ disabled:可聚焦/選取/提交,僅不可改值);詳 color.spec.md Static Subtle 邊界 */
|
|
331
332
|
|
|
332
333
|
/* Neutral Interactive — Selected state family
|
|
333
334
|
─────────────────────────────────────────────────────────────
|
|
@@ -515,6 +516,7 @@
|
|
|
515
516
|
--color-neutral-hover: var(--neutral-hover);
|
|
516
517
|
--color-neutral-active: var(--neutral-active);
|
|
517
518
|
--color-disabled: var(--bg-disabled);
|
|
519
|
+
--color-readonly: var(--bg-readonly);
|
|
518
520
|
|
|
519
521
|
/* Neutral Interaction — Selected state family */
|
|
520
522
|
--color-neutral-selected: var(--neutral-selected);
|
|
@@ -18,7 +18,7 @@ Density 由**兩個獨立維度**構成,並配合一個 convenience attribute
|
|
|
18
18
|
|
|
19
19
|
**反例**(耦合):Material M3 / Polaris density 模式綁 control size + spacing — 無法「寬版面 + 標準 control」的場景。
|
|
20
20
|
|
|
21
|
-
**我們走 decouple 流派**:解決 Dialog / overlay chrome 的痛點 — header
|
|
21
|
+
**我們走 decouple 流派**:解決 Dialog / overlay chrome 的痛點 — header 想要版面間距寬鬆(layout-space=lg),但不要被 button chrome 撐高(ui-size 跟 page 走 md)。
|
|
22
22
|
|
|
23
23
|
## 預設同步(density convenience)
|
|
24
24
|
|
|
@@ -35,7 +35,7 @@ Density 由**兩個獨立維度**構成,並配合一個 convenience attribute
|
|
|
35
35
|
|
|
36
36
|
## 解耦用法(canonical 情境)
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
當需要「版面間距寬鬆(layout-space)+ 控件高度標準(ui-size)」時,**顯式設兩個 attribute**:
|
|
39
39
|
|
|
40
40
|
### Canonical 情境 1 — 歷史備忘(Dialog 已撤回)
|
|
41
41
|
|
|
@@ -108,20 +108,10 @@ document.documentElement.setAttribute('data-layout-space', 'md')
|
|
|
108
108
|
| Tooltip | `data-density="md"` | 同 Popover |
|
|
109
109
|
| Sidebar | 無(繼承 page) | Sidebar 是 inline chrome(非 Portal 逃逸),跟隨 page density;size="md" 在 density="lg" 下自動變 36px row(見 sidebar.spec.md「Row size 跟 density 的差別」)|
|
|
110
110
|
|
|
111
|
+
**邊界:page density=lg 下的 Portal overlay**——Popover / DropdownMenu / Tooltip 在 `data-density="lg"` 的 page 上仍鎖 `md`(code:各 Content 自設 `data-density="md"`)。這不是漏接:Portal 到 body 本就不繼承 subtree density(M3),鎖 md 是 overlay「compact」語意的刻意設計(2026-04-22 v5 canonical)。
|
|
112
|
+
|
|
111
113
|
## Anti-patterns(禁止)
|
|
112
114
|
|
|
113
115
|
- ❌ 元件同時設 `data-density` + `data-ui-size`(重複,以後者為準但混亂)
|
|
114
116
|
- ❌ Overlay Portal 元件不自設 density(Portal 到 body 不繼承 trigger — 見 Meta-Pattern M3)
|
|
115
117
|
- ❌ 為了追求表面一致性硬把 Dialog button 綁 lg ui-size(犧牲 header 高度 / strapline 彈性)
|
|
116
|
-
|
|
117
|
-
## 被引用(auto-maintained,Dim 3 reciprocal audit)
|
|
118
|
-
|
|
119
|
-
> 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
|
|
120
|
-
|
|
121
|
-
- `dialog.spec.md`
|
|
122
|
-
- `dropdown-menu.spec.md`
|
|
123
|
-
- `popover.spec.md`
|
|
124
|
-
- `sheet.spec.md`
|
|
125
|
-
- `sidebar.spec.md`
|
|
126
|
-
- `tooltip.spec.md`
|
|
127
|
-
- `uiSize.spec.md`
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
<!-- @benchmark-cited: D5 retrofit backfill 2026-06-10 — body world-class claims marked per-claim inline;對齊 token spec 家族 7/9 既有 marker 慣例(deep-audit A.0 抓漏)。 -->
|
|
2
|
+
|
|
1
3
|
# Elevation 設計原則
|
|
2
4
|
|
|
3
5
|
Elevation 定義陰影層級,區分內容層(Card)和浮層(Modal/Popover)的視覺深度。
|
|
@@ -16,11 +18,11 @@ Elevation 定義陰影層級,區分內容層(Card)和浮層(Modal/Popove
|
|
|
16
18
|
| Token | 用途 | 對應元件 |
|
|
17
19
|
|-------|------|----------|
|
|
18
20
|
| `--elevation-100` | 頁面內容層,靜止 | Card |
|
|
19
|
-
| `--elevation-100-hover` | 頁面內容層,hover / 拖拽 |
|
|
21
|
+
| `--elevation-100-hover` | 頁面內容層,hover / 拖拽 lift | —(目前無 DS 內建 consumer;預留給 consumer 的可拖拽 / hover-lift card,如 board card drag) |
|
|
20
22
|
| `--elevation-200` | 浮層,靜止 | Modal、popover、dropdown、overlay drawer |
|
|
21
|
-
| `--elevation-200-hover` | 浮層,hover | — |
|
|
23
|
+
| `--elevation-200-hover` | 浮層,hover | —(同上,預留) |
|
|
22
24
|
|
|
23
|
-
elevation-100 < elevation-200
|
|
25
|
+
elevation-100 < elevation-200,數字越大浮起越高。`*-hover` 兩枚為靜止 token 的「抬升一階」變體:元素被 hover / 拖起時切換,幾何(offset / blur)不變、只加深陰影 alpha(`tokens/color/primitives.css` 定義,light / dark 各一組)。
|
|
24
26
|
|
|
25
27
|
## 與 Surface 的配對規則
|
|
26
28
|
|
|
@@ -46,6 +48,8 @@ elevation-100 < elevation-200,數字越大浮起越高。
|
|
|
46
48
|
|
|
47
49
|
**SSOT** → `tokens/elevation/overlay-geometry.ts` exports `OVERLAY_SIDE_OFFSET = 8` / `OVERLAY_COLLISION_PADDING = 8`。所有 primitive `default` 必 import 該 const(M17 SSOT 必可傳播);Radix `sideOffset` 接 number 不接 CSS var,因此用 JS const 共用,改值只動一處全部聯動。
|
|
48
50
|
|
|
51
|
+
**視窗邊緣碰撞(邊界案例)**:浮層貼近 viewport 邊不足以容納時,Radix `avoidCollisions`(預設開)自動翻轉 / 平移,並與邊緣保持 `collisionPadding` = `OVERLAY_COLLISION_PADDING`(8px;Tooltip / Popover / DropdownMenu 皆接此 const)。例外:HoverCard 用 12(Radix / browser rounding 讓 visual padding 少 1-2px 的補償,見 `hover-card.tsx` 註解)。
|
|
52
|
+
|
|
49
53
|
| 浮層類型 | sideOffset | 說明 |
|
|
50
54
|
|---------|-----------|------|
|
|
51
55
|
| Tooltip | 8px | TooltipContent 預設值 |
|
|
@@ -70,10 +74,5 @@ elevation-100 < elevation-200,數字越大浮起越高。
|
|
|
70
74
|
> 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
|
|
71
75
|
|
|
72
76
|
- `motion.spec.md`
|
|
73
|
-
|
|
74
|
-
## 被引用(auto-maintained,Dim 3 reciprocal audit)
|
|
75
|
-
|
|
76
|
-
> 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
|
|
77
|
-
|
|
78
77
|
- `slider.spec.md`
|
|
79
78
|
- `token-system.spec.md`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @benchmark-cited: D5 retrofit 2026-05-18 — body claims marked per-claim @benchmark-unverified inline
|
|
1
|
+
<!-- @benchmark-cited: D5 retrofit 2026-05-18 — body claims marked per-claim @benchmark-unverified inline(M22(d) 顯式撤回;本檔 frontmatter 無 benchmark list,來源 URL 未補)。 -->
|
|
2
2
|
|
|
3
3
|
# LayoutSpace 設計原則
|
|
4
4
|
|
|
@@ -105,7 +105,7 @@ Pattern C 的視覺邏輯見 `overlay-surface.spec.md`「Hover bg 貼邊 chrome
|
|
|
105
105
|
|
|
106
106
|
**核心**:gap 只看親疏不看 role(原 v1「block-adjacent 一律 tight」過機械,違 Gestalt proximity)。
|
|
107
107
|
|
|
108
|
-
世界級對齊:Material 3 / Polaris / Apple HIG / Atlassian 都按「relationship not type」決定 spacing。 <!-- @benchmark-unverified
|
|
108
|
+
世界級對齊:Material 3 / Polaris / Apple HIG / Atlassian 都按「relationship not type」決定 spacing。 <!-- @benchmark-unverified -->
|
|
109
109
|
|
|
110
110
|
### 規則 4:底部 — 拆兩個 distinct 概念
|
|
111
111
|
|
|
@@ -137,22 +137,19 @@ Pattern C 的視覺邏輯見 `overlay-surface.spec.md`「Hover bg 貼邊 chrome
|
|
|
137
137
|
|
|
138
138
|
**為何 loose 而非 tight**:Chrome 是 surface 視覺邊界 + 內容呼吸區;`tight` 足夠 inline list item,chrome 需更穩定 anchor 讓 title / dismiss / actions 不貼邊。
|
|
139
139
|
|
|
140
|
-
**M8 8 家世界級對照**(default density 共識 16px):Material 3 Top App Bar 16dp / Carbon UI Shell 16px / Polaris Page Header 16px / Atlassian Page Header 16px / Apple HIG macOS Toolbar 16-20pt / Linear / Notion / GitHub Primer / Figma 全 16px。 <!-- @benchmark-unverified
|
|
140
|
+
**M8 8 家世界級對照**(default density 共識 16px):Material 3 Top App Bar 16dp / Carbon UI Shell 16px / Polaris Page Header 16px / Atlassian Page Header 16px / Apple HIG macOS Toolbar 16-20pt / Linear / Notion / GitHub Primer / Figma 全 16px。 <!-- @benchmark-unverified -->
|
|
141
141
|
|
|
142
142
|
**禁止**:硬寫 `px-4` / 自創值(`px-5`)/ 用 tight 當 chrome inline / 同 surface header/body/footer inline padding 不一致(三層左邊界必對齊)。
|
|
143
143
|
|
|
144
|
+
**RTL**:本系統水平 padding 一律 `px-*`(左右對稱、無方向性),RTL 下行為不變;方向性 spacing(`ps-*`/`pe-*`)未使用。
|
|
145
|
+
|
|
144
146
|
---
|
|
145
147
|
|
|
146
148
|
## 心智模型(三步推理 + 具體 self-questions)
|
|
147
149
|
|
|
148
150
|
### Step 1 — 判角色(對單一元素)
|
|
149
151
|
|
|
150
|
-
|
|
151
|
-
1. 在該層 layout 占主導(寬度撐滿 + 高度 flex-1)嗎?
|
|
152
|
-
2. 視覺重量是「畫布」(占據 layout)還是「控件」(局部塊)?
|
|
153
|
-
3. 是該層展示主角(主導內容)嗎?
|
|
154
|
-
|
|
155
|
-
多數 yes → **region**;反之 → **element**。
|
|
152
|
+
跑上方「元件角色」節的**判斷 3 題**(占主導? / 畫布 vs 控件? / 展示主角?)— 多數 yes → **region**;反之 → **element**。
|
|
156
153
|
|
|
157
154
|
若 region 再問 1 題:有視覺邊界(底色 / 邊框 / 上下分隔線)嗎?
|
|
158
155
|
- 有 → **bounded**(Card / Table with borders / Panel)
|
|
@@ -195,7 +192,7 @@ Pattern C 的視覺邏輯見 `overlay-surface.spec.md`「Hover bg 貼邊 chrome
|
|
|
195
192
|
- **判親疏**:
|
|
196
193
|
- bundled?(在元件 spec 裡寫成 bundle 嗎?) → **否**(consumer-composed)→ 跨範疇
|
|
197
194
|
- functional 交互?A 不驅動 B,parallel siblings → **不相關**
|
|
198
|
-
- **答**:`loose`(16/24)— 對齊 Material / Polaris / Apple HIG / Atlassian 共識 <!-- @benchmark-unverified
|
|
195
|
+
- **答**:`loose`(16/24)— 對齊 Material / Polaris / Apple HIG / Atlassian 共識 <!-- @benchmark-unverified -->
|
|
199
196
|
|
|
200
197
|
### 範例 2:Cmd+K menu 中 search input ↔ result list
|
|
201
198
|
|
|
@@ -221,16 +218,16 @@ Pattern C 的視覺邏輯見 `overlay-surface.spec.md`「Hover bg 貼邊 chrome
|
|
|
221
218
|
|
|
222
219
|
- **走規則**:規則 4
|
|
223
220
|
- **判**:後接 action button(在 SurfaceFooter 內)?**是** → 套 `bottom 48`
|
|
224
|
-
- **答**:48(概念 A commitment 前留白)。`dialog.tsx
|
|
221
|
+
- **答**:48(概念 A commitment 前留白)。`dialog.tsx` DialogBody 預設 `pb-bottom` 是此規則的實作(預期 body 後接 SurfaceFooter buttons),非 Dialog 例外
|
|
225
222
|
|
|
226
223
|
### 範例 6:SurfaceFooter 內 [Cancel] ↔ [Save] gap
|
|
227
224
|
|
|
228
225
|
- **走範疇判**(在規則 3 之前):
|
|
229
226
|
- bundled?**是**(`button-group.spec` + `overlay-surface.spec` 都自帶 button arrangement canonical = `gap-2`/8px)
|
|
230
227
|
- → 同範疇 / bundled 第一級,**layoutSpace 一般規則跳過**
|
|
231
|
-
- **答**:`gap-2`(8)— 由 `button-group.tsx:51` / `overlay-surface.tsx
|
|
228
|
+
- **答**:`gap-2`(8)— 由 `button-group.tsx:51` / `overlay-surface.tsx` SurfaceFooter 自帶 canonical own
|
|
232
229
|
|
|
233
|
-
**注意**:規則 5「橫排並列」**只**適用 input fields
|
|
230
|
+
**注意**:規則 5「橫排並列」**只**適用 input fields,不套 button group(button spacing 屬 bundled-family canonical own,不走 layoutSpace 一般 rule)。
|
|
234
231
|
|
|
235
232
|
---
|
|
236
233
|
|
|
@@ -270,19 +267,20 @@ Pattern C 的視覺邏輯見 `overlay-surface.spec.md`「Hover bg 貼邊 chrome
|
|
|
270
267
|
|
|
271
268
|
---
|
|
272
269
|
|
|
273
|
-
##
|
|
270
|
+
## 常見誤解
|
|
274
271
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
272
|
+
- ❌ **元素間 gap 硬寫 `gap-4`**:容器級 gap 走規則 3 token(`tight` / `loose`);固定 `gap-2` / `gap-4` 只限規則 5 橫排 input 與 bundled family 自帶 canonical
|
|
273
|
+
- ❌ **Pattern C 場景把 padding 寫在 list 容器**:hover bg 需 flush 貼邊,padding 必須 item 自帶(規則 1C);寫在容器 = hover bg 縮一圈
|
|
274
|
+
- ❌ **unbounded list 漏自帶 py**:規則 2 / 4 的「0」前提是 list 自帶 py 撐 spacing;漏 py = 內容貼 chrome 邊
|
|
278
275
|
|
|
279
|
-
|
|
280
|
-
document.documentElement.setAttribute('data-density', 'lg')
|
|
281
|
-
```
|
|
276
|
+
---
|
|
282
277
|
|
|
283
|
-
|
|
278
|
+
## 模式切換
|
|
284
279
|
|
|
285
280
|
```ts
|
|
281
|
+
// 全域 density(含 layout space)
|
|
282
|
+
document.documentElement.setAttribute('data-density', 'lg')
|
|
283
|
+
// 單獨控制版面間距而不影響元件尺寸
|
|
286
284
|
document.documentElement.setAttribute('data-layout-space', 'lg')
|
|
287
285
|
```
|
|
288
286
|
|
|
@@ -301,13 +299,8 @@ document.documentElement.setAttribute('data-layout-space', 'lg')
|
|
|
301
299
|
> 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
|
|
302
300
|
|
|
303
301
|
- `app-shell.spec.md`
|
|
304
|
-
|
|
305
|
-
## 被引用(auto-maintained,Dim 3 reciprocal audit)
|
|
306
|
-
|
|
307
|
-
> 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
|
|
308
|
-
|
|
309
302
|
- `description-list.spec.md`
|
|
310
303
|
- `empty.spec.md`
|
|
311
|
-
- `
|
|
304
|
+
- `overlay-surface.spec.md`
|
|
312
305
|
- `token-system.spec.md`
|
|
313
306
|
- `uiSize.spec.md`
|
|
@@ -14,27 +14,29 @@ benchmark:
|
|
|
14
14
|
|
|
15
15
|
<!-- @benchmark-cited: D5 retrofit 2026-05-18 — body claims marked per-claim @benchmark-unverified inline; canonical source URLs in frontmatter benchmark list. -->
|
|
16
16
|
|
|
17
|
-
# Motion
|
|
17
|
+
# Motion 設計原則
|
|
18
18
|
|
|
19
19
|
> **Foundational SSOT rationale**(2026-05-18 ship per user 拍板 #3A):跨 5+ overlay 消費者
|
|
20
20
|
> (Tooltip / HoverCard / ProfileCard / Avatar / OverflowIndicator)的 hover 開啟 / 關閉延遲統一。
|
|
21
21
|
|
|
22
22
|
## 定位
|
|
23
23
|
|
|
24
|
-
Hover delay token 是「hover 觸發 → overlay
|
|
24
|
+
Hover delay token 是「hover 觸發 → 延遲 N ms → overlay 顯示」的延遲時間(對齊 token 名 `delay` 術語)。**目的不是動畫長度,是「user 真的想看」過濾器** — 短暫滑過不該觸發 expensive overlay(ProfileCard fetch 資料 / Tooltip 視覺擾動)。
|
|
25
|
+
|
|
26
|
+
**Scope 邊界**:本 token 系統僅管 hover open / close 延遲;overlay 開啟後的 fetch loading 視覺(skeleton / 留空)屬各 consumer 元件 spec(HoverCard / ProfileCard),不在 motion token scope。
|
|
25
27
|
|
|
26
28
|
## 三層 tier 系統
|
|
27
29
|
|
|
28
30
|
| Token | 值 | 用於 | 為何 |
|
|
29
31
|
|---|---|---|---|
|
|
30
|
-
| `--hover-delay-plain` | `500ms` | Tooltip 純文字提示 | 被動 hint,需 user「真停留」才觸發,避免滑過列表時 N 次視覺擾動。對齊 Material 3 plain tooltip 500ms / Apple HIG ~500ms / shadcn-Radix default 500ms 主流共識 |
|
|
32
|
+
| `--hover-delay-plain` | `500ms` | Tooltip 純文字提示 | 被動 hint,需 user「真停留」才觸發,避免滑過列表時 N 次視覺擾動。對齊 Material 3 plain tooltip 500ms / Apple HIG ~500ms / shadcn-Radix default 500ms 主流共識 | <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
|
|
31
33
|
| `--hover-delay-rich` | `700ms` | HoverCard / ProfileCard 內容預覽 | 含 avatar / fields / actions 的 rich content(可能含 fetch)。User 必須「真的想看」才停留 700ms,避免列表掃視時誤觸發 N 個 fetch waterfall |
|
|
32
34
|
| `--hover-delay-close` | `200ms` | 所有 overlay 關閉 | Mouse leave 後給 200ms 緩衝(user 可能誤滑出再回來)。對齊 UX 共識「close delay ≤ open delay」+ 既有 Avatar `closeDelay={200}` 值 |
|
|
33
35
|
|
|
34
36
|
## 為何不用單一值 / 為何不沿用過去 200ms
|
|
35
37
|
|
|
36
38
|
- **過去 200/300ms 偏快**(2026-05-18 ship,2026-05-20 user 抓「太快很容易干擾人」撤回):200ms plain 滑過列表 N 次觸發 Tooltip 視覺擾動;300ms rich 在含 fetch 的 HoverCard 場景列表掃視會打 N 次 server request waterfall。
|
|
37
|
-
- **MUI/Ant 100ms 是 fast-tier 例外**:適合 form input help text 等「我就是要快」的 dense 場景,不適合通用 chrome tooltip。
|
|
39
|
+
- **MUI/Ant 100ms 是 fast-tier 例外**:適合 form input help text 等「我就是要快」的 dense 場景,不適合通用 chrome tooltip。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
|
|
38
40
|
- **單一值** 失去 plain / rich 語意區分:ProfileCard 含 fetch + image + actions 應比 Tooltip(純文字)delay 長,單一值會讓 ProfileCard 滑過列表時整列誤觸發 fetch waterfall。
|
|
39
41
|
- **過短**(< 100ms):每滑必觸發 → 視覺擾動 + 不必要 server request。
|
|
40
42
|
- **過長**(> 1s):user 已不期待 overlay,等出來變干擾。
|
|
@@ -66,8 +68,8 @@ Hover delay token 是「hover 觸發 → overlay 顯示」之間的等待時間
|
|
|
66
68
|
|
|
67
69
|
## 消費者
|
|
68
70
|
|
|
69
|
-
- `components/Avatar/avatar.tsx
|
|
70
|
-
- `components/HoverCard/hover-card.tsx` —
|
|
71
|
+
- `components/Avatar/avatar.tsx` — HoverCard openDelay / closeDelay 消費 `HOVER_DELAY_RICH_MS` / `HOVER_DELAY_CLOSE_MS`(原硬寫 300/200,migrate 到 token)
|
|
72
|
+
- `components/HoverCard/hover-card.tsx` — Root 預設 `openDelay`=`--hover-delay-rich` / `closeDelay`=`--hover-delay-close`(Radix HoverCard 無 Provider;2026-06-11 落地,原宣稱與 code 脫鉤)
|
|
71
73
|
- `components/Tooltip/tooltip.tsx` — Radix Provider 預設 delayDuration override 為 `--hover-delay-plain`
|
|
72
74
|
- `components/ProfileCard/profile-card.tsx`(consumer of HoverCard)— 繼承 `--hover-delay-rich`
|
|
73
75
|
- `components/OverflowIndicator/overflow-indicator.tsx`(consumer)— 用 `--hover-delay-plain`
|
|
@@ -86,7 +88,7 @@ Hover delay token 是「hover 觸發 → overlay 顯示」之間的等待時間
|
|
|
86
88
|
| MUI / Ant Tooltip | 100ms(dense form input fast-tier) | — |
|
|
87
89
|
| **DS canonical(本 spec)** | **500ms** | **700ms** |
|
|
88
90
|
|
|
89
|
-
500ms 對齊 Material 3 / Apple HIG / shadcn 主流共識(三家集中在 500ms),避 MUI/Ant 100ms(form input fast-tier 不適通用 chrome)+ Radix 700(過保守)兩極端。Rich 700ms 比 plain 多 200ms 反映 fetch / multi-section content「真的想看」門檻。
|
|
91
|
+
500ms 對齊 Material 3 / Apple HIG / shadcn 主流共識(三家集中在 500ms),避 MUI/Ant 100ms(form input fast-tier 不適通用 chrome)+ Radix 700(過保守)兩極端。Rich 700ms 比 plain 多 200ms 反映 fetch / multi-section content「真的想看」門檻。 <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
|
|
90
92
|
|
|
91
93
|
## 相關
|
|
92
94
|
|
|
@@ -95,3 +97,9 @@ Hover delay token 是「hover 觸發 → overlay 顯示」之間的等待時間
|
|
|
95
97
|
- `../../components/Tooltip/tooltip.spec.md`(consumer)
|
|
96
98
|
- `../../components/HoverCard/hover-card.spec.md`(consumer)
|
|
97
99
|
- `../../components/Avatar/avatar.spec.md`(consumer)
|
|
100
|
+
|
|
101
|
+
## 被引用(auto-maintained,Dim 3 reciprocal audit)
|
|
102
|
+
|
|
103
|
+
> 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
|
|
104
|
+
|
|
105
|
+
- `hover-card.spec.md`
|
|
@@ -17,22 +17,24 @@ Opacity 定義元件停用狀態的透明度,確保全系統 disabled 視覺
|
|
|
17
17
|
停用狀態有兩種視覺策略(詳見 `color.spec.md`「Disabled 狀態」節 / 「兩種 disabled 策略」):
|
|
18
18
|
|
|
19
19
|
- **Token swap**(預設):disabled 時換成專用 token(`fg-disabled`、`bg-disabled`),精確控制每個層的顏色。適用於多層結構的元件(Button、Input)。
|
|
20
|
-
- **Opacity blanket**:對整個元件套 `opacity-disabled`,一次處理所有子元素。適用於結構簡單、子元素多的元件(Avatar、Switch thumb、Slider
|
|
20
|
+
- **Opacity blanket**:對整個元件套 `opacity-disabled`,一次處理所有子元素。適用於結構簡單、子元素多的元件(Avatar、Switch thumb、Rating)。Slider 屬灰階 token-swap 派,**不**用 opacity(`slider.spec.md`「Disabled 策略」反覆確認後的結論)。
|
|
21
21
|
|
|
22
22
|
不可混用——同一元件要嘛用 token swap,要嘛用 opacity,不兩者同時。
|
|
23
23
|
|
|
24
|
+
**Scope**:opacity 只負責 disabled 一個 role——error / warning 等 state 走 semantic color token 變色(`border-error` 等)、hover / active 走 `-hover` / `-active` token,皆無透明度變化(role 隔離,詳「設計哲學」(2);全 DS production code 無 error-state opacity 用例)。**已 codify 的 reuse 例外**(reuse 同一 token,非新增 opacity role):DataTable 整表 refresh loading(`data-table.spec.md`「狀態處理職責邊界」)與 drag source 半透(同 spec「Drag visual SSOT」+ `lib/drag-visual.ts`)。
|
|
25
|
+
|
|
24
26
|
## 為什麼 0.45
|
|
25
27
|
|
|
26
|
-
0.45 在 light mode 和 dark mode 都能對 disabled 元件產生足夠辨識度(明顯區分於 active state
|
|
28
|
+
0.45 在 light mode 和 dark mode 都能對 disabled 元件產生足夠辨識度(明顯區分於 active state)。「辨識」與「閱讀」是兩個不同要求:WCAG 2.1 SC 1.4.3 明文豁免 inactive UI component 的文字對比(無法定「可讀對比」門檻);但 UX 上使用者仍須**辨識**出「這裡有一個控件、且目前停用」——0.45 服務的是辨識,不是閱讀。
|
|
27
29
|
|
|
28
|
-
選 0.45 的位置:
|
|
30
|
+
選 0.45 的位置: <!-- @benchmark-unverified -->
|
|
29
31
|
|
|
30
32
|
- 比 **Material 0.38** 略亮(Material 在白底 dark text 0.38 太弱,DS 使用 lg / dark mode 共用一個值需折衷)
|
|
31
33
|
- 比 **Apple iOS 0.4 / Atlassian 0.4** 稍亮(iOS 是 mobile-first 對比偏強,DS desktop 場景文字密集需更可辨識)
|
|
32
34
|
- 比 **Polaris 0.5 / Tailwind 0.5** 稍暗(0.5 對 disabled 元件辨識度不足,容易誤判為 hover state)
|
|
33
35
|
- **0.45 是 0.4-0.5 區間中位數**,跨 light / dark mode 都 robust
|
|
34
36
|
|
|
35
|
-
世界級對照(2026-05-01 加):
|
|
37
|
+
世界級對照(2026-05-01 加): <!-- @benchmark-unverified -->
|
|
36
38
|
|
|
37
39
|
| DS | Material 3 | Carbon | Tailwind v4 | Ant Design | Polaris | Apple HIG | Atlassian |
|
|
38
40
|
|----|-----------|--------|-------------|------------|---------|-----------|-----------|
|
|
@@ -44,41 +46,28 @@ Opacity 定義元件停用狀態的透明度,確保全系統 disabled 視覺
|
|
|
44
46
|
|
|
45
47
|
兩個關鍵決策,各自有世界級先例支撐:
|
|
46
48
|
|
|
47
|
-
**(1) 雙策略並存(token swap 為主 + opacity blanket 為輔)— 對齊 Carbon / Atlassian 折衷哲學**
|
|
49
|
+
**(1) 雙策略並存(token swap 為主 + opacity blanket 為輔)— 對齊 Carbon / Atlassian 折衷哲學** <!-- @benchmark-unverified -->
|
|
48
50
|
|
|
49
51
|
純 token swap(Material / Ant / Polaris):每元件每層 disabled 自己一個 token,精確但 token 數激增(Material 有 50+ disabled token);純 opacity blanket(早期 Bootstrap):一律 0.5 簡單但無法表達 multi-layer hierarchy(disabled Button 的 icon / label / border 三層該有不同程度 fade)。
|
|
50
52
|
|
|
51
53
|
本 DS 採 Carbon-aligned 折衷:**多層結構元件用 token swap**(Button 有 fg / bg / border 各自 disabled token);**簡單元件用 opacity blanket**(Avatar / Switch thumb 一個視覺單位,opacity 0.45 一次處理所有子元素)。明文「不可混用」避免 disabled overlay 重疊產生「過度褪色」(0.45 × 0.45 = 0.2 不可讀)。
|
|
52
54
|
|
|
53
|
-
**(2) Single tier 0.45 而非 Tailwind multi-tier opacity scale — 對齊 Polaris / Apple 單值哲學**
|
|
55
|
+
**(2) Single tier 0.45 而非 Tailwind multi-tier opacity scale — 對齊 Polaris / Apple 單值哲學** <!-- @benchmark-unverified -->
|
|
54
56
|
|
|
55
57
|
Tailwind 提供 `opacity-{5/10/20/30/40/50/60/70/80/90/95}` 百分比 ladder,但這是 utility scale 非 semantic role — 每個 consumer 自己挑值,跨元件不一致(A 用 opacity-50 / B 用 opacity-40 都 disabled)。
|
|
56
58
|
|
|
57
59
|
本 DS 為 disabled 場景 single semantic token(`opacity-disabled = 0.45`),所有 disabled 用同一值 — 對齊 Polaris `opacity-disabled` / Material `disabled-on-surface` / Apple `UIDisabled` 「single semantic value for one role」哲學。捨棄 Tailwind multi-tier 的代價是「無法表達多層 hover/active fade」,但 hover / active 走 hover-bg / pressed-bg token,opacity 只負責 disabled,role 隔離。
|
|
58
60
|
|
|
59
|
-
##
|
|
60
|
-
|
|
61
|
-
Avatar、Sidebar、MenuItem、Slider、Switch、Steps、Chip。
|
|
62
|
-
|
|
63
|
-
## 反向引用
|
|
64
|
-
|
|
65
|
-
- Disabled 策略選擇框架:`tokens/color/color.spec.md`
|
|
61
|
+
## A11y(disabled 訊號不只透明度)
|
|
66
62
|
|
|
67
|
-
|
|
63
|
+
透明度是視覺輔助,不是 disabled 的唯一訊號:語意由 native `disabled` / `aria-disabled` attribute 傳達給輔助技術(SR 朗讀 unavailable,非依賴視覺),並伴隨互動阻斷(無法觸發 / `cursor-not-allowed`)提供非色彩線索——色弱使用者不依賴 0.45 fade 也能辨識停用狀態。
|
|
68
64
|
|
|
69
|
-
|
|
65
|
+
## 消費者
|
|
70
66
|
|
|
71
|
-
- `
|
|
72
|
-
- `chip.spec.md`
|
|
73
|
-
- `color.spec.md`
|
|
74
|
-
- `menu-item.spec.md`
|
|
75
|
-
- `sidebar.spec.md`
|
|
76
|
-
- `slider.spec.md`
|
|
77
|
-
- `steps.spec.md`
|
|
78
|
-
- `switch.spec.md`
|
|
67
|
+
直接套用 `opacity-disabled` 的元件(grep 驗證 2026-06-11):Avatar(Field disabled context self-dim)、Button(`aria-disabled` 分支)、MenuItem、Rating(disabled / loading 整塊)、Steps、Switch、Textarea(disabled 分支)、DataTable(drag source 半透 + 整表 refresh loading reuse,經 `lib/drag-visual.ts`)。
|
|
79
68
|
|
|
80
|
-
|
|
69
|
+
非消費者(曾誤列):Slider / Sidebar 走灰階 token swap;Chip 無 opacity 用例;Field wrapper blanket 已移除(Avatar self-dim 取代,見 field-wrapper.tsx 註解)。
|
|
81
70
|
|
|
82
|
-
|
|
71
|
+
## 反向引用
|
|
83
72
|
|
|
84
|
-
-
|
|
73
|
+
- Disabled 策略選擇框架:`tokens/color/color.spec.md`
|
|
@@ -10,10 +10,15 @@ benchmark:
|
|
|
10
10
|
- Polaris Design Tokens — semantic SOP 5-piece set canonical https://polaris.shopify.com/design/colors
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
# Orphan Token
|
|
13
|
+
# Orphan Token 分類設計原則(retire vs structural-keep SSOT)
|
|
14
14
|
|
|
15
15
|
> **Foundational context**(2026-05-21 codify per user verbatim「決策四你他媽仔細給我確認到底該retire的是否真的該retire還是應該結構性保留,請全盤檢查,然後確認之後請下次不要再煩我,尤其是Palette tier」+「都給我做到好」):**永久解決**「audit 每次抓 X 個 orphan tokens」噪音。本 spec 明文哪些 token 結構性保留 + 自動 audit script 識別,user 不需重複確認同一題。
|
|
16
16
|
|
|
17
|
+
## Scope(何時用 / 何時不用)
|
|
18
|
+
|
|
19
|
+
- **用**:DS 作者稽核 token bloat(retire vs structural-keep 判定)— `audit-orphan-tokens.mjs` + design-system-audit Dim 48 消費本分類,屬 DS-internal audit SSOT
|
|
20
|
+
- **不用**:consumer 選 token 的使用指南 — 那是 `tokens/README.md` + 各 token spec 的職責
|
|
21
|
+
|
|
17
22
|
## 為什麼會出現「假孤兒」
|
|
18
23
|
|
|
19
24
|
簡單的 `grep var(--X)` 抓不到以下消費路徑,造成 token **實際有用但 audit 報「無消費」false positive**:
|
|
@@ -79,7 +84,7 @@ benchmark:
|
|
|
79
84
|
|
|
80
85
|
### 7. SOP 5-piece semantic 完整集(1+ token,structural)
|
|
81
86
|
|
|
82
|
-
**Rule**:每個 semantic role(primary / error / success / warning / info)必有 5 件套:`base / hover / active / subtle / text
|
|
87
|
+
**Rule**:每個 semantic role(primary / error / success / warning / info)必有 5 件套:`base / hover / active / subtle / text`;機械保護集另含 `emphasis / foreground / focus`(下方 Regex 共 7 後綴,與 `audit-orphan-tokens.mjs` 一致;無後綴 base 由消費者直接引用不在 regex 內)。即使當前 variant 無消費者也保留。
|
|
83
88
|
|
|
84
89
|
**Why**:Consistency invariant — 缺 `-text` variant 設計時找不到「on-emphasis 文字色」會 hot-create,違反 SSOT。Polaris「Status colors complete set」canonical。
|
|
85
90
|
|
|
@@ -104,9 +109,15 @@ benchmark:
|
|
|
104
109
|
2. **Git blame** declare 提交 — 提交訊息 / PR 描述是否說明用途
|
|
105
110
|
3. 兩 step 都無 → safe retire,從 `tokens/**/*.css` 刪宣告 + 加 git commit message cite 本 spec
|
|
106
111
|
|
|
112
|
+
## 邊界案例
|
|
113
|
+
|
|
114
|
+
- **Audit 間 token 重獲消費者(0 → N)**:audit 為每次執行的即時 snapshot(無跨次狀態),token 重獲消費後自動退出 retire 候選;無 deprecation period 機制
|
|
115
|
+
- **新 structural-keep token**:不在 baseline → `--check` fail,需 `--update` 顯式 justify(防 regex 過寬 silent absorb;baseline 縮減不 fail)— baseline SSOT `scripts/audit-orphan-tokens.baseline.json`
|
|
116
|
+
- **Dark-mode token mirror 驗證**:非本 audit scope — script 只驗「消費存在性」,不驗 light / dark 配對完整性
|
|
117
|
+
|
|
107
118
|
## Audit chain
|
|
108
119
|
|
|
109
|
-
- **Dim 48**
|
|
120
|
+
- **Dim 48**(= `design-system-audit/SKILL.md` 的「Unused / orphan token detector」audit 維度)— chain 本 spec + `audit-orphan-tokens.mjs --check`(not raw `grep var()`)
|
|
110
121
|
- **CI**:`npm run audit:tokens`(future add to `package.json` scripts)— `node scripts/audit-orphan-tokens.mjs --check` fail = real orphan 出現
|
|
111
122
|
- **Hook**:無 hook(本 audit run-time / monthly cadence,非 PreToolUse 攔截場景)
|
|
112
123
|
|
|
@@ -27,7 +27,7 @@ CSS 定義了 `--radius-sm`(目前 = 4px,與 md 同值),但**不在元件中使
|
|
|
27
27
|
- Chart legend swatch(8×8 色塊)
|
|
28
28
|
- 未來其他 micro indicator(若尺寸 ≥ 12px 請改 `rounded-md`,不要為了「更圓」使用 xs)
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
**判斷**(radius / 邊長比):4px 在 8×8 元素上 = 邊長 50%(radius 達半邊長即成 pill,類別色塊語意流失);2px = 25%,輪廓保持方形。≥ 12px 元素上 4px ≤ 33%,比例適當,不需 xs。
|
|
31
31
|
|
|
32
32
|
### `rounded-md`(4px)— 一般元件
|
|
33
33
|
|
|
@@ -57,7 +57,7 @@ CSS 定義了 `--radius-sm`(目前 = 4px,與 md 同值),但**不在元件中使
|
|
|
57
57
|
## 禁止事項
|
|
58
58
|
|
|
59
59
|
```tsx
|
|
60
|
-
// ❌ 不要用非 token
|
|
60
|
+
// ❌ 不要用非 token 的圓角(bare rounded、rounded-xl、rounded-2xl 等)
|
|
61
61
|
<div className="rounded" /> // 4px,但意圖不明
|
|
62
62
|
<div className="rounded-xl" /> // 12px,超出 token 範圍
|
|
63
63
|
<div className="rounded-2xl" /> // 16px,超出 token 範圍
|
|
@@ -81,15 +81,19 @@ CSS 定義了 `--radius-sm`(目前 = 4px,與 md 同值),但**不在元件中使
|
|
|
81
81
|
<span className="rounded-full" />
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
+
### 省略 radius 的行為(空值驗證)
|
|
85
|
+
|
|
86
|
+
不寫 `rounded-*` → `border-radius: 0`(CSS 預設直角),不 fallback 任何 token;無圓角需求的元素本就不寫,不強制每元素標 radius。**有意**的圓角必用上表 4 tier class——bare `rounded`(Tailwind 預設 4px,意圖不明)與硬寫值由上方禁止事項擋。
|
|
87
|
+
|
|
84
88
|
|
|
85
89
|
## 世界級對照
|
|
86
90
|
|
|
87
|
-
對齊 M8(binary strict rule 必 ≥3 家世界級對照),「禁 `rounded-xl` / `rounded-2xl` raw utility」+「禁硬寫 `rounded-[6px]`」是本 spec 的 binary strict rule,以下為支撐 rationale。
|
|
91
|
+
對齊 M8(binary strict rule 必 ≥3 家世界級對照),「禁 `rounded-xl` / `rounded-2xl` raw utility」+「禁硬寫 `rounded-[6px]`」是本 spec 的 binary strict rule,以下為支撐 rationale。 <!-- @benchmark-unverified -->
|
|
88
92
|
|
|
89
93
|
| 維度 | 本 DS | Material 3 | Carbon | Tailwind v4 | Ant Design | Polaris | shadcn/Apple |
|
|
90
94
|
|------|-------|-----------|--------|-------------|------------|---------|--------------|
|
|
91
|
-
| Tier 數 | **4 tier**(xs/md/lg/full)+ 1 reserved sm | 6 tier(extra-small ~ extra-large + full) | 3 tier(0/1/2) |
|
|
92
|
-
| 數值序列 | **2 / 4 / 8 / 9999** geometric × 2 | 4 / 8 / 12 / 16 / 28 額外 | 0 / 2px / 4px(token rem)| 2 / 4 / 6 / 8 / 12 / 16 / 24 | 2 / 4 / 6 / 8 | 2 / 4 / 6 / 8 / 12 / 16 | `--radius` × calc 變化 |
|
|
95
|
+
| Tier 數 | **4 tier**(xs/md/lg/full)+ 1 reserved sm | 6 tier(extra-small ~ extra-large + full) | 3 tier(0/1/2) | 8 tier(xs/sm/md/lg/xl/2xl/3xl/4xl)+ none/full | **4 tier**(XS/SM/Default/LG)| 6 tier(050/100/200/300/400/500/full)| 1 base + calc(shadcn)/ Squircle 連續曲率(Apple)|
|
|
96
|
+
| 數值序列 | **2 / 4 / 8 / 9999** geometric × 2 | 4 / 8 / 12 / 16 / 28 額外 | 0 / 2px / 4px(token rem)| 2 / 4 / 6 / 8 / 12 / 16 / 24 / 32 | 2 / 4 / 6 / 8 | 2 / 4 / 6 / 8 / 12 / 16 | `--radius` × calc 變化 |
|
|
93
97
|
| Pill 方案 | `rounded-full` 9999px | `shape-corner-full` | 不顯式提供 | `rounded-full` 9999px | `borderRadiusOuter` ad-hoc | `border-radius-full` | 視 component shape |
|
|
94
98
|
| 動態 shape | 無(靜態 4 tier)| Dynamic shape morphing(可動畫) | 無 | 無 | 無 | 無 | Apple 連續曲率動態 |
|
|
95
99
|
|
|
@@ -97,32 +101,26 @@ CSS 定義了 `--radius-sm`(目前 = 4px,與 md 同值),但**不在元件中使
|
|
|
97
101
|
|
|
98
102
|
四個關鍵決策,各自有世界級先例支撐:
|
|
99
103
|
|
|
100
|
-
**(1) 4 tier(xs/md/lg/full)— 對齊 Ant Design 4-tier minimal,捨多家 6+ tier**
|
|
104
|
+
**(1) 4 tier(xs/md/lg/full)— 對齊 Ant Design 4-tier minimal,捨多家 6+ tier** <!-- @benchmark-unverified -->
|
|
101
105
|
|
|
102
106
|
Material 3 / Polaris / Tailwind 6-7 tier 過細 — 每 tier 只差 2-4px,reader 視覺難分(「rounded-md 6px」vs「rounded-lg 8px」差 25% 但目視幾乎相同)。Carbon 3 tier(0/1/2)太極簡無法表達 elevation 層級(浮層 vs inline 同 radius 失去視覺 hierarchy)。
|
|
103
107
|
|
|
104
108
|
本 DS 4 tier 是「視覺可區分 + 維護友善」最佳交集 — `xs(2)→ md(4)→ lg(8)→ full` 每跳一級數值翻倍,目視差異 ≥ 50%(Weber-Fechner law 知覺閾值),不會出現「rounded-md vs rounded-mdlg 哪個對」糾結。
|
|
105
109
|
|
|
106
|
-
**(2) Geometric scale(2 / 4 / 8 doubling)— 對齊 Tailwind / Polaris 慣例**
|
|
110
|
+
**(2) Geometric scale(2 / 4 / 8 doubling)— 對齊 Tailwind / Polaris 慣例** <!-- @benchmark-unverified -->
|
|
107
111
|
|
|
108
112
|
數值 doubling 確保 reader 一眼感知「不同層級」(2→4→8 比 4→6→8 對比明顯)。對齊 Tailwind sm(2)/ md(4)/ lg(8) + Polaris 100(4)/ 200(6 — 偏離)/ 300(8) 的 powers-of-2 idiom。
|
|
109
113
|
|
|
110
114
|
捨棄連續 ratio(Material 4/8/12/16/28 等差 + 跳級)的代價是「中段 size 表現空間」(無 6px tier),DS 場景無此需求(中段需求都歸入 md=4)。
|
|
111
115
|
|
|
112
|
-
**(3) `rounded-full` 9999px 而非 50%(對齊 Tailwind / Polaris)**
|
|
116
|
+
**(3) `rounded-full` 9999px 而非 50%(對齊 Tailwind / Polaris)** <!-- @benchmark-unverified -->
|
|
113
117
|
|
|
114
118
|
50% percentage 在「短矩形」(高 < 寬,如 horizontal Switch)變橢圓而非 pill — 9999px 確保任意 aspect ratio 都圓形(實際 capped 在 height/2)。對齊 Tailwind / Polaris 全 pill 慣例,避免短矩形 edge case。
|
|
115
119
|
|
|
116
|
-
**(4) 保留 `--radius-sm` token 但不用 — 對齊 Material「reserve for future dense pattern」**
|
|
120
|
+
**(4) 保留 `--radius-sm` token 但不用 — 對齊 Material「reserve for future dense pattern」** <!-- @benchmark-unverified -->
|
|
117
121
|
|
|
118
122
|
CSS 定義 `--radius-sm = 4px`(目前同 md),component 強制 `rounded-md` 不引用 sm。為什麼留:未來若引入 dense mode(`density="compact"` 介於 md / xs 之間),可開新 sm tier 不破壞既有 xs/md/lg/full 命名階梯(避免 rename 引發全 DS grep refactor)。對齊 Material 3 的「extra-small reserved tier」哲學。
|
|
119
123
|
|
|
120
124
|
捨棄「立即啟用 sm」的代價是命名空間預占,接受 — 命名穩定 > 短期 utility。
|
|
121
125
|
|
|
122
126
|
捨棄「Apple Continuous Corner / Squircle」的代價是「平台一致性」(Apple HIG 用連續曲率非單一 radius,iOS 元件視覺更柔)— DS 是 cross-platform web,採 Material/Tailwind 標準 border-radius 對齊大多數 OS native 元件,避免引入 SVG path 額外 runtime 成本。
|
|
123
|
-
|
|
124
|
-
## 被引用(auto-maintained,Dim 3 reciprocal audit)
|
|
125
|
-
|
|
126
|
-
> 本節由 `scripts/add-reciprocal-pointers.mjs` 自動維護,列出在 SSOT 語境下指向本 spec 的其他 spec。若要手動補充,寫在本節之前。
|
|
127
|
-
|
|
128
|
-
- `token-system.spec.md`
|
|
@@ -228,16 +228,13 @@ Tailwind v4 `@theme inline` 把 CSS variable 升級成 utility class。每 famil
|
|
|
228
228
|
|
|
229
229
|
---
|
|
230
230
|
|
|
231
|
-
##
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
- `
|
|
236
|
-
- `
|
|
237
|
-
- `
|
|
238
|
-
- `layoutSpace/layoutSpace.spec.md`
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
- `radius/radius.spec.md`(L3 Family classification)
|
|
242
|
-
- `typography/typography.spec.md`(L3 Family classification)
|
|
243
|
-
- `.claude/rules/ui-development.md`「Token 命名 4 條硬規則」(下游 lint-style summary)
|
|
231
|
+
## 相關
|
|
232
|
+
|
|
233
|
+
- `README.md`(tokens charter)— 檔案路徑 + Public vs Internal token 表
|
|
234
|
+
- `color/color.spec.md` — L1/L2 色彩 family 具體規則(含 Tag / Avatar 直接消費 L1 的流派定位)
|
|
235
|
+
- `uiSize/uiSize.spec.md` — L3 Family / L4 Layout 尺寸 token
|
|
236
|
+
- `typography/typography.spec.md` — `--font-*` family
|
|
237
|
+
- `elevation/elevation.spec.md` — `--elevation-*`(住 `color/primitives.css`,理由見「跨 family co-location 規則」)
|
|
238
|
+
- `layoutSpace/layoutSpace.spec.md` — `--layout-space-*` 抽象 spacing rhythm
|
|
239
|
+
|
|
240
|
+
---
|