@qijenchen/design-system 0.1.0-beta.85 → 0.1.0-beta.87
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/AGENTS.md +210 -0
- package/CLAUDE.md +17 -191
- package/cli-init.mjs +30 -2
- package/dist/components/Accordion/accordion.d.ts +2 -2
- package/dist/components/Accordion/accordion.d.ts.map +1 -1
- package/dist/components/Accordion/accordion.js.map +1 -1
- package/dist/components/Avatar/avatar.js +1 -1
- package/dist/components/Avatar/avatar.js.map +1 -1
- package/dist/components/BulkActionBar/bulk-action-bar.d.ts +1 -1
- package/dist/components/BulkActionBar/bulk-action-bar.d.ts.map +1 -1
- package/dist/components/BulkActionBar/bulk-action-bar.js +3 -3
- package/dist/components/BulkActionBar/bulk-action-bar.js.map +1 -1
- package/dist/components/Button/button-group.d.ts +2 -2
- package/dist/components/Button/button-group.d.ts.map +1 -1
- package/dist/components/Button/button-group.js +2 -2
- package/dist/components/Button/button-group.js.map +1 -1
- package/dist/components/Button/button.d.ts +2 -1
- package/dist/components/Button/button.d.ts.map +1 -1
- package/dist/components/Button/button.js +1 -1
- package/dist/components/Button/button.js.map +1 -1
- package/dist/components/Carousel/carousel.d.ts +14 -8
- package/dist/components/Carousel/carousel.d.ts.map +1 -1
- package/dist/components/Carousel/carousel.js +64 -37
- package/dist/components/Carousel/carousel.js.map +1 -1
- package/dist/components/Checkbox/checkbox-group.d.ts.map +1 -1
- package/dist/components/Checkbox/checkbox-group.js +21 -14
- package/dist/components/Checkbox/checkbox-group.js.map +1 -1
- package/dist/components/Checkbox/checkbox.d.ts +2 -2
- package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox/checkbox.js +49 -10
- package/dist/components/Checkbox/checkbox.js.map +1 -1
- package/dist/components/Combobox/combobox.d.ts +15 -6
- package/dist/components/Combobox/combobox.d.ts.map +1 -1
- package/dist/components/Combobox/combobox.js +13 -7
- package/dist/components/Combobox/combobox.js.map +1 -1
- package/dist/components/Command/command.d.ts.map +1 -1
- package/dist/components/Command/command.js +11 -2
- package/dist/components/Command/command.js.map +1 -1
- package/dist/components/DataTable/cell-registry.d.ts +5 -5
- package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
- package/dist/components/DataTable/cell-registry.js +41 -38
- package/dist/components/DataTable/cell-registry.js.map +1 -1
- package/dist/components/DataTable/column-types.d.ts +1 -17
- package/dist/components/DataTable/column-types.d.ts.map +1 -1
- package/dist/components/DataTable/column-types.js.map +1 -1
- package/dist/components/DataTable/data-table-column-visibility-panel.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-column-visibility-panel.js +71 -64
- package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -1
- package/dist/components/DataTable/data-table-filter-panel.d.ts +0 -2
- package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-filter-panel.js +3 -4
- package/dist/components/DataTable/data-table-filter-panel.js.map +1 -1
- package/dist/components/DataTable/data-table-interaction-layer.d.ts +2 -2
- package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
- package/dist/components/DataTable/data-table-sort-manager.js +2 -2
- package/dist/components/DataTable/data-table-sort-manager.js.map +1 -1
- package/dist/components/DataTable/data-table.d.ts +1 -1
- package/dist/components/DataTable/data-table.d.ts.map +1 -1
- package/dist/components/DataTable/data-table.js +44 -32
- package/dist/components/DataTable/data-table.js.map +1 -1
- package/dist/components/DatePicker/date-picker.d.ts +3 -3
- package/dist/components/DatePicker/date-picker.js +4 -4
- package/dist/components/DatePicker/date-picker.js.map +1 -1
- package/dist/components/DescriptionList/description-list.d.ts +3 -3
- package/dist/components/DescriptionList/description-list.d.ts.map +1 -1
- package/dist/components/DescriptionList/description-list.js +6 -6
- package/dist/components/DescriptionList/description-list.js.map +1 -1
- package/dist/components/Dialog/dialog.d.ts +2 -2
- 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 +8 -3
- package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.js +7 -7
- package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
- package/dist/components/Field/field-context.d.ts +16 -10
- package/dist/components/Field/field-context.d.ts.map +1 -1
- package/dist/components/Field/field-context.js.map +1 -1
- package/dist/components/Field/field-types.d.ts +2 -2
- package/dist/components/Field/field-types.d.ts.map +1 -1
- package/dist/components/Field/field-types.js.map +1 -1
- package/dist/components/Field/field-wrapper.d.ts +20 -4
- package/dist/components/Field/field-wrapper.d.ts.map +1 -1
- package/dist/components/Field/field-wrapper.js +30 -31
- 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 +25 -3
- package/dist/components/Field/field.js.map +1 -1
- package/dist/components/Field/use-form-validation.d.ts +1 -1
- package/dist/components/Field/use-form-validation.js.map +1 -1
- package/dist/components/FileItem/file-item.d.ts.map +1 -1
- package/dist/components/FileItem/file-item.js +2 -5
- package/dist/components/FileItem/file-item.js.map +1 -1
- package/dist/components/FileUpload/file-upload.d.ts.map +1 -1
- package/dist/components/FileUpload/file-upload.js +5 -1
- package/dist/components/FileUpload/file-upload.js.map +1 -1
- package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
- package/dist/components/FileViewer/file-viewer.js +2 -1
- package/dist/components/FileViewer/file-viewer.js.map +1 -1
- package/dist/components/HoverCard/hover-card.d.ts +2 -2
- package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
- package/dist/components/HoverCard/hover-card.js +4 -2
- package/dist/components/HoverCard/hover-card.js.map +1 -1
- package/dist/components/InlineEdit/inline-edit.d.ts +23 -16
- package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -1
- package/dist/components/InlineEdit/inline-edit.js +104 -62
- package/dist/components/InlineEdit/inline-edit.js.map +1 -1
- package/dist/components/Input/input.d.ts +1 -1
- package/dist/components/Input/input.d.ts.map +1 -1
- package/dist/components/Input/input.js +6 -6
- package/dist/components/Input/input.js.map +1 -1
- package/dist/components/LinkInput/link-input.d.ts +5 -5
- package/dist/components/LinkInput/link-input.d.ts.map +1 -1
- package/dist/components/LinkInput/link-input.js +3 -3
- package/dist/components/LinkInput/link-input.js.map +1 -1
- package/dist/components/Notice/notice.d.ts +17 -1
- package/dist/components/Notice/notice.d.ts.map +1 -1
- package/dist/components/Notice/notice.js +7 -1
- 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 +12 -1
- package/dist/components/NumberInput/number-input.js.map +1 -1
- package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts +1 -1
- package/dist/components/PeoplePicker/avatar-stack-overflow.js.map +1 -1
- package/dist/components/PeoplePicker/people-picker.d.ts +5 -5
- package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
- package/dist/components/PeoplePicker/people-picker.js +7 -5
- package/dist/components/PeoplePicker/people-picker.js.map +1 -1
- package/dist/components/PeoplePicker/person-display.d.ts +1 -1
- package/dist/components/PeoplePicker/person-display.js.map +1 -1
- package/dist/components/ProfileCard/profile-card.d.ts +1 -1
- package/dist/components/ProfileCard/profile-card.js.map +1 -1
- package/dist/components/RadioGroup/radio-group.d.ts +3 -3
- package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
- package/dist/components/RadioGroup/radio-group.js +1 -1
- package/dist/components/RadioGroup/radio-group.js.map +1 -1
- package/dist/components/Rating/rating.d.ts.map +1 -1
- package/dist/components/Rating/rating.js +4 -0
- package/dist/components/Rating/rating.js.map +1 -1
- package/dist/components/ScrollArea/scroll-area.d.ts +3 -2
- package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
- package/dist/components/ScrollArea/scroll-area.js.map +1 -1
- package/dist/components/SegmentedControl/segmented-control.d.ts +4 -3
- package/dist/components/SegmentedControl/segmented-control.d.ts.map +1 -1
- package/dist/components/SegmentedControl/segmented-control.js.map +1 -1
- package/dist/components/Select/select.d.ts +16 -6
- package/dist/components/Select/select.d.ts.map +1 -1
- package/dist/components/Select/select.js +17 -5
- package/dist/components/Select/select.js.map +1 -1
- package/dist/components/SelectMenu/select-menu.d.ts +17 -1
- package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
- package/dist/components/SelectMenu/select-menu.js +17 -3
- package/dist/components/SelectMenu/select-menu.js.map +1 -1
- package/dist/components/SelectionControl/boolean-value.d.ts +1 -1
- package/dist/components/SelectionControl/boolean-value.js.map +1 -1
- package/dist/components/Sheet/sheet.d.ts +2 -2
- 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.js +2 -2
- package/dist/components/Sidebar/sidebar.js.map +1 -1
- package/dist/components/Slider/slider.d.ts.map +1 -1
- package/dist/components/Slider/slider.js +6 -3
- package/dist/components/Slider/slider.js.map +1 -1
- package/dist/components/Steps/steps.d.ts +6 -4
- package/dist/components/Steps/steps.d.ts.map +1 -1
- package/dist/components/Steps/steps.js +19 -5
- package/dist/components/Steps/steps.js.map +1 -1
- package/dist/components/Switch/switch.d.ts +4 -4
- package/dist/components/Switch/switch.d.ts.map +1 -1
- package/dist/components/Switch/switch.js +3 -1
- package/dist/components/Switch/switch.js.map +1 -1
- package/dist/components/Tabs/tabs.d.ts +1 -1
- package/dist/components/Tabs/tabs.d.ts.map +1 -1
- package/dist/components/Tabs/tabs.js +73 -23
- package/dist/components/Tabs/tabs.js.map +1 -1
- package/dist/components/Tag/tag.d.ts +3 -1
- package/dist/components/Tag/tag.d.ts.map +1 -1
- package/dist/components/Tag/tag.js +2 -2
- package/dist/components/Tag/tag.js.map +1 -1
- package/dist/components/Textarea/textarea.d.ts +4 -4
- package/dist/components/Textarea/textarea.d.ts.map +1 -1
- package/dist/components/Textarea/textarea.js +15 -15
- package/dist/components/Textarea/textarea.js.map +1 -1
- package/dist/components/TimePicker/time-picker.d.ts +4 -4
- package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
- package/dist/components/TimePicker/time-picker.js +8 -5
- package/dist/components/TimePicker/time-picker.js.map +1 -1
- package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
- package/dist/components/Tooltip/tooltip.js +27 -23
- package/dist/components/Tooltip/tooltip.js.map +1 -1
- package/dist/components/TreeView/tree-view.d.ts.map +1 -1
- package/dist/components/TreeView/tree-view.js +16 -0
- package/dist/components/TreeView/tree-view.js.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -13
- package/dist/index.js.map +1 -1
- package/dist/lib/drag-visual.d.ts +2 -2
- package/dist/lib/drag-visual.js.map +1 -1
- package/dist/lib/utils.d.ts +1 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +21 -1
- package/dist/lib/utils.js.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.d.ts +2 -0
- package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.js +2 -2
- package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
- package/dist/tokens/categorical-color.d.ts +3 -3
- package/dist/tokens/categorical-color.d.ts.map +1 -1
- package/dist/tokens/categorical-color.js +2 -2
- package/dist/tokens/categorical-color.js.map +1 -1
- package/ds-canonical/fork/AGENTS.md +213 -0
- package/ds-canonical/fork/codex/agents/skills/independent-review/SKILL.md +33 -0
- package/ds-canonical/fork/codex/hooks.json +16 -0
- package/ds-canonical/fork/governance.lock +22 -7
- package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +22 -1
- package/ds-canonical/fork/hooks/inject_deploy_url_after_push.sh +14 -2
- package/ds-canonical/fork/manifest.json +10 -1
- package/ds-canonical/fork/preamble.md +3 -2
- package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +7 -7
- package/ds-canonical/fork/skills/ux-audit/SKILL.md +1 -1
- package/ds-canonical/fork/skills/visual-audit/SKILL.md +0 -1
- package/ds-canonical/hooks/check_codex_brief_invariants.sh +9 -3
- package/ds-canonical/hooks/check_ds_anchor_preflight.sh +22 -1
- package/ds-canonical/hooks/check_overlay_open_focus_escape_probe.sh +19 -2
- package/ds-canonical/hooks/check_plugin_fork_health.sh +17 -1
- package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +21 -4
- package/ds-canonical/hooks/inject_deploy_url_after_push.sh +14 -2
- package/ds-canonical/hooks/session_start_governance_check.sh +10 -2
- package/ds-canonical/references/certified-surfaces.md +20 -0
- package/ds-canonical/references/preflight-gate-baseline.json +5 -0
- package/ds-canonical/references/principle-dim-map.json +20 -2
- package/ds-canonical/references/props-naming.md +2 -1
- package/ds-canonical/references/ssot-index.md +2 -2
- package/ds-canonical/references/story-baseline-registry.json +2 -2
- package/ds-canonical/rules/story-rules.md +1 -1
- package/ds-canonical/rules/ui-development.md +2 -1
- package/ds-canonical/skills/codex-collab/SKILL.md +7 -7
- package/ds-canonical/skills/codex-collab/references/brief-template.md +5 -1
- package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
- package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +5 -5
- package/ds-canonical/skills/design-system-audit/SKILL.md +5 -5
- package/ds-canonical/skills/product-ui-audit/SKILL.md +7 -7
- package/ds-canonical/skills/ux-audit/SKILL.md +1 -1
- package/ds-canonical/skills/visual-audit/SKILL.md +0 -1
- package/ds-story-manifest.json +21 -21
- package/llms-full.txt +3 -3
- package/llms.txt +1 -1
- package/package.json +2 -1
- package/src/components/Accordion/accordion.anatomy.stories.tsx +11 -11
- package/src/components/Accordion/accordion.principles.stories.tsx +21 -6
- package/src/components/Accordion/accordion.spec.md +10 -1
- package/src/components/Accordion/accordion.stories.tsx +10 -5
- package/src/components/Accordion/accordion.tsx +7 -2
- package/src/components/Alert/alert.principles.stories.tsx +2 -8
- package/src/components/AppShell/app-shell.anatomy.stories.tsx +19 -13
- package/src/components/AppShell/app-shell.principles.stories.tsx +21 -21
- package/src/components/AppShell/app-shell.spec.md +4 -0
- package/src/components/AppShell/app-shell.stories.tsx +4 -5
- package/src/components/Avatar/avatar.tsx +1 -1
- package/src/components/Badge/badge.spec.md +2 -2
- package/src/components/Breadcrumb/breadcrumb.anatomy.stories.tsx +7 -3
- package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +4 -1
- package/src/components/Breadcrumb/breadcrumb.stories.tsx +1 -1
- package/src/components/BulkActionBar/bulk-action-bar.anatomy.stories.tsx +6 -6
- package/src/components/BulkActionBar/bulk-action-bar.principles.stories.tsx +18 -6
- package/src/components/BulkActionBar/bulk-action-bar.spec.md +15 -5
- package/src/components/BulkActionBar/bulk-action-bar.stories.tsx +8 -24
- package/src/components/BulkActionBar/bulk-action-bar.tsx +4 -4
- package/src/components/Button/button-group.tsx +4 -4
- package/src/components/Button/button.anatomy.stories.tsx +26 -7
- package/src/components/Button/button.principles.stories.tsx +1 -1
- package/src/components/Button/button.spec.md +2 -2
- package/src/components/Button/button.stories.tsx +22 -28
- package/src/components/Button/button.tsx +2 -1
- package/src/components/Calendar/calendar.anatomy.stories.tsx +1 -1
- package/src/components/Calendar/calendar.spec.md +1 -1
- package/src/components/Carousel/carousel.spec.md +17 -1
- package/src/components/Carousel/carousel.tsx +93 -42
- package/src/components/Checkbox/checkbox-group.tsx +26 -15
- package/src/components/Checkbox/checkbox.anatomy.stories.tsx +3 -3
- package/src/components/Checkbox/checkbox.spec.md +12 -3
- package/src/components/Checkbox/checkbox.stories.tsx +4 -4
- package/src/components/Checkbox/checkbox.tsx +79 -19
- package/src/components/Coachmark/coachmark.anatomy.stories.tsx +5 -5
- package/src/components/Coachmark/coachmark.principles.stories.tsx +1 -1
- package/src/components/Combobox/combobox.anatomy.stories.tsx +11 -4
- package/src/components/Combobox/combobox.principles.stories.tsx +10 -11
- package/src/components/Combobox/combobox.spec.md +6 -2
- package/src/components/Combobox/combobox.stories.tsx +9 -36
- package/src/components/Combobox/combobox.tsx +42 -27
- package/src/components/Command/command.spec.md +3 -3
- package/src/components/Command/command.tsx +9 -2
- package/src/components/DataTable/cell-registry.tsx +75 -76
- package/src/components/DataTable/column-types.ts +4 -17
- package/src/components/DataTable/data-table-column-visibility-panel.tsx +20 -7
- package/src/components/DataTable/data-table-filter-panel.tsx +6 -6
- package/src/components/DataTable/data-table-interaction-layer.tsx +3 -3
- package/src/components/DataTable/data-table-sort-manager.tsx +2 -2
- package/src/components/DataTable/data-table.anatomy.stories.tsx +25 -24
- package/src/components/DataTable/data-table.css +2 -3
- package/src/components/DataTable/data-table.principles.stories.tsx +17 -11
- package/src/components/DataTable/data-table.spec.md +8 -7
- package/src/components/DataTable/data-table.stories.tsx +39 -29
- package/src/components/DataTable/data-table.tsx +90 -67
- package/src/components/DataTable/filter-operators.spec.md +2 -0
- package/src/components/DateGrid/date-grid.spec.md +1 -1
- package/src/components/DatePicker/date-picker.anatomy.stories.tsx +9 -9
- package/src/components/DatePicker/date-picker.principles.stories.tsx +4 -4
- package/src/components/DatePicker/date-picker.spec.md +10 -9
- package/src/components/DatePicker/date-picker.stories.tsx +9 -9
- package/src/components/DatePicker/date-picker.tsx +13 -13
- package/src/components/DescriptionList/description-list.anatomy.stories.tsx +5 -5
- package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
- package/src/components/DescriptionList/description-list.spec.md +12 -12
- package/src/components/DescriptionList/description-list.stories.tsx +3 -3
- package/src/components/DescriptionList/description-list.tsx +10 -10
- package/src/components/Dialog/dialog.tsx +4 -1
- package/src/components/DropdownMenu/dropdown-menu.tsx +27 -14
- package/src/components/Empty/empty.spec.md +0 -1
- package/src/components/Field/field-context.ts +17 -11
- package/src/components/Field/field-controls.spec.md +46 -37
- package/src/components/Field/field-types.ts +14 -12
- package/src/components/Field/field-wrapper.tsx +59 -43
- package/src/components/Field/field.anatomy.stories.tsx +6 -6
- package/src/components/Field/field.principles.stories.tsx +5 -28
- package/src/components/Field/field.spec.md +5 -4
- package/src/components/Field/field.stories.tsx +103 -72
- package/src/components/Field/field.tsx +36 -4
- package/src/components/Field/form-validation.spec.md +4 -0
- package/src/components/Field/use-form-validation.ts +1 -1
- 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/FileItem/file-item.tsx +10 -8
- package/src/components/FileUpload/file-upload.principles.stories.tsx +7 -7
- package/src/components/FileUpload/file-upload.spec.md +3 -2
- package/src/components/FileUpload/file-upload.tsx +5 -1
- package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +1 -1
- package/src/components/FileViewer/file-viewer.principles.stories.tsx +1 -1
- package/src/components/FileViewer/file-viewer.spec.md +1 -1
- package/src/components/FileViewer/file-viewer.stories.tsx +1 -1
- package/src/components/FileViewer/file-viewer.tsx +3 -2
- package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -4
- package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -1
- package/src/components/HoverCard/hover-card.spec.md +2 -2
- package/src/components/HoverCard/hover-card.tsx +4 -2
- package/src/components/InlineEdit/inline-edit.anatomy.stories.tsx +184 -0
- package/src/components/InlineEdit/inline-edit.principles.stories.tsx +142 -0
- package/src/components/InlineEdit/inline-edit.spec.md +71 -46
- package/src/components/InlineEdit/inline-edit.stories.tsx +20 -19
- package/src/components/InlineEdit/inline-edit.tsx +211 -125
- package/src/components/Input/input.anatomy.stories.tsx +15 -15
- package/src/components/Input/input.principles.stories.tsx +3 -3
- package/src/components/Input/input.spec.md +4 -4
- package/src/components/Input/input.stories.tsx +3 -3
- package/src/components/Input/input.tsx +13 -13
- package/src/components/LinkInput/link-input.anatomy.stories.tsx +2 -2
- package/src/components/LinkInput/link-input.principles.stories.tsx +1 -1
- package/src/components/LinkInput/link-input.spec.md +6 -2
- package/src/components/LinkInput/link-input.stories.tsx +8 -8
- package/src/components/LinkInput/link-input.tsx +21 -19
- package/src/components/Notice/notice.principles.stories.tsx +1 -1
- package/src/components/Notice/notice.tsx +8 -2
- package/src/components/NumberInput/number-input.anatomy.stories.tsx +6 -6
- package/src/components/NumberInput/number-input.principles.stories.tsx +4 -4
- package/src/components/NumberInput/number-input.spec.md +6 -6
- package/src/components/NumberInput/number-input.stories.tsx +4 -4
- package/src/components/NumberInput/number-input.tsx +17 -5
- package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +8 -4
- package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +6 -7
- package/src/components/OverflowIndicator/overflow-indicator.spec.md +1 -1
- package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +6 -30
- package/src/components/PeoplePicker/avatar-stack-overflow.ts +1 -1
- package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +13 -10
- package/src/components/PeoplePicker/people-picker.principles.stories.tsx +5 -1
- package/src/components/PeoplePicker/people-picker.stories.tsx +5 -5
- package/src/components/PeoplePicker/people-picker.tsx +39 -20
- package/src/components/PeoplePicker/person-display.tsx +3 -3
- package/src/components/Popover/popover.anatomy.stories.tsx +10 -7
- package/src/components/Popover/popover.principles.stories.tsx +49 -28
- package/src/components/Popover/popover.spec.md +4 -2
- package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +1 -1
- package/src/components/ProfileCard/profile-card.tsx +1 -1
- package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +14 -13
- package/src/components/ProgressBar/progress-bar.principles.stories.tsx +8 -23
- package/src/components/ProgressBar/progress-bar.stories.tsx +8 -2
- package/src/components/README.md +1 -0
- package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +8 -3
- package/src/components/RadioGroup/radio-group.stories.tsx +3 -3
- package/src/components/RadioGroup/radio-group.tsx +19 -14
- package/src/components/Rating/rating.anatomy.stories.tsx +1 -1
- package/src/components/Rating/rating.principles.stories.tsx +3 -3
- package/src/components/Rating/rating.spec.md +2 -2
- package/src/components/Rating/rating.stories.tsx +4 -18
- package/src/components/Rating/rating.tsx +5 -1
- package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
- package/src/components/ScrollArea/scroll-area.spec.md +1 -1
- package/src/components/ScrollArea/scroll-area.tsx +5 -2
- package/src/components/SegmentedControl/segmented-control.principles.stories.tsx +4 -1
- package/src/components/SegmentedControl/segmented-control.spec.md +5 -10
- package/src/components/SegmentedControl/segmented-control.tsx +6 -3
- package/src/components/Select/select.anatomy.stories.tsx +13 -7
- package/src/components/Select/select.principles.stories.tsx +3 -3
- package/src/components/Select/select.spec.md +10 -1
- package/src/components/Select/select.stories.tsx +41 -27
- package/src/components/Select/select.tsx +44 -26
- package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +44 -26
- package/src/components/SelectMenu/select-menu.principles.stories.tsx +0 -1
- package/src/components/SelectMenu/select-menu.stories.tsx +7 -19
- package/src/components/SelectMenu/select-menu.tsx +38 -5
- package/src/components/SelectionControl/boolean-value.tsx +2 -2
- package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +1 -1
- package/src/components/SelectionControl/selection-item.principles.stories.tsx +4 -4
- package/src/components/Separator/separator.principles.stories.tsx +1 -1
- package/src/components/Sheet/sheet.principles.stories.tsx +5 -3
- package/src/components/Sheet/sheet.tsx +4 -1
- package/src/components/Sidebar/sidebar.tsx +1 -1
- package/src/components/Slider/slider.anatomy.stories.tsx +5 -4
- package/src/components/Slider/slider.principles.stories.tsx +6 -6
- package/src/components/Slider/slider.spec.md +13 -1
- package/src/components/Slider/slider.stories.tsx +44 -32
- package/src/components/Slider/slider.tsx +13 -4
- package/src/components/Steps/steps.anatomy.stories.tsx +7 -7
- package/src/components/Steps/steps.principles.stories.tsx +1 -1
- package/src/components/Steps/steps.spec.md +4 -2
- package/src/components/Steps/steps.stories.tsx +4 -56
- package/src/components/Steps/steps.tsx +31 -7
- package/src/components/Switch/switch.anatomy.stories.tsx +3 -3
- package/src/components/Switch/switch.principles.stories.tsx +1 -1
- package/src/components/Switch/switch.spec.md +4 -4
- package/src/components/Switch/switch.stories.tsx +3 -3
- package/src/components/Switch/switch.tsx +16 -10
- package/src/components/Tabs/tabs.anatomy.stories.tsx +6 -0
- package/src/components/Tabs/tabs.principles.stories.tsx +10 -2
- package/src/components/Tabs/tabs.spec.md +5 -2
- package/src/components/Tabs/tabs.stories.tsx +36 -44
- package/src/components/Tabs/tabs.tsx +101 -36
- package/src/components/Tag/tag.anatomy.stories.tsx +2 -2
- package/src/components/Tag/tag.principles.stories.tsx +4 -4
- package/src/components/Tag/tag.spec.md +4 -1
- package/src/components/Tag/tag.tsx +5 -3
- package/src/components/Textarea/textarea.anatomy.stories.tsx +6 -6
- package/src/components/Textarea/textarea.spec.md +5 -5
- package/src/components/Textarea/textarea.tsx +24 -24
- package/src/components/TimePicker/time-picker.anatomy.stories.tsx +12 -11
- package/src/components/TimePicker/time-picker.principles.stories.tsx +37 -44
- package/src/components/TimePicker/time-picker.spec.md +6 -5
- package/src/components/TimePicker/time-picker.stories.tsx +3 -3
- package/src/components/TimePicker/time-picker.tsx +24 -14
- package/src/components/Toast/toast.principles.stories.tsx +1 -1
- package/src/components/Toast/toast.stories.tsx +1 -1
- package/src/components/Tooltip/tooltip.anatomy.stories.tsx +15 -6
- package/src/components/Tooltip/tooltip.principles.stories.tsx +4 -4
- package/src/components/Tooltip/tooltip.spec.md +9 -3
- package/src/components/Tooltip/tooltip.stories.tsx +1 -1
- package/src/components/Tooltip/tooltip.tsx +12 -2
- package/src/components/TreeView/tree-view.anatomy.stories.tsx +16 -14
- package/src/components/TreeView/tree-view.principles.stories.tsx +44 -11
- package/src/components/TreeView/tree-view.spec.md +8 -6
- package/src/components/TreeView/tree-view.stories.tsx +9 -43
- package/src/components/TreeView/tree-view.tsx +36 -0
- package/src/index.ts +13 -10
- package/src/lib/drag-visual.ts +2 -2
- package/src/lib/utils.ts +19 -0
- package/src/patterns/action-bar/action-bar.spec.md +1 -0
- package/src/patterns/element-anatomy/inline-action.spec.md +1 -1
- package/src/patterns/element-anatomy/item-anatomy.spec.md +4 -0
- package/src/patterns/element-anatomy/item-anatomy.tsx +4 -2
- package/src/patterns/header-canonical/header-canonical.spec.md +9 -0
- package/src/patterns/header-canonical/header-canonical.stories.tsx +31 -5
- package/src/tokens/categorical-color.ts +5 -5
- package/src/tokens/color/color.spec.md +4 -4
- package/src/tokens/color/primitives.css +9 -2
- package/src/tokens/motion/motion.spec.md +6 -7
- package/src/tokens/opacity/opacity.spec.md +1 -1
- package/src/tokens/orphan-tokens.spec.md +1 -1
- package/src/tokens/typography/typography.spec.md +2 -0
- package/src/tokens/uiSize/uiSize.css +5 -0
- package/src/tokens/uiSize/uiSize.spec.md +1 -1
|
@@ -248,7 +248,7 @@ export const Overview = {
|
|
|
248
248
|
<thead><tr><Th>Prop</Th><Th>Type</Th><Th>Default</Th><Th>說明</Th></tr></thead>
|
|
249
249
|
<tbody>
|
|
250
250
|
{[
|
|
251
|
-
['mode', "'edit' | '
|
|
251
|
+
['mode', "'edit' | 'view' | 'readonly' | 'disabled'", "'edit'", "顯示模式;view 為純內容輸出(DataTable cell 用)。優先序:顯式 mode prop 永遠最優先,未傳 mode 時 disabled 才升 disabled(useResolvedFieldMode);disabled 以 aria-disabled 表達(trigger 為 div role=combobox,非原生 disabled 屬性)"],
|
|
252
252
|
['error', 'boolean', 'false', '紅色邊框 + aria-invalid,僅 edit 模式生效'],
|
|
253
253
|
['size', "'sm' | 'md' | 'lg'", "'md'", '高度與字體,與 Button 共用 field-height token'],
|
|
254
254
|
['value', 'string | null', '—', 'ISO date string(YYYY-MM-DD)'],
|
|
@@ -708,12 +708,12 @@ export const StateBehavior = {
|
|
|
708
708
|
<span className="text-caption font-medium text-fg-secondary">格式化 — 預設 YYYY/MM/DD 直接組;傳 formatOptions / locale 走 Intl.DateTimeFormat</span>
|
|
709
709
|
<div className="overflow-x-auto">
|
|
710
710
|
<table className="border-collapse text-caption">
|
|
711
|
-
<thead><tr><Th>設定</Th><Th>readonly 預覽</Th><Th>
|
|
711
|
+
<thead><tr><Th>設定</Th><Th>readonly 預覽</Th><Th>view 預覽</Th></tr></thead>
|
|
712
712
|
<tbody>
|
|
713
713
|
<tr>
|
|
714
714
|
<Td>預設(YYYY/MM/DD)</Td>
|
|
715
715
|
<td className="p-2 border-b border-divider"><DatePicker mode="readonly" value="2026-04-02" /></td>
|
|
716
|
-
<td className="p-2 border-b border-divider"><DatePicker mode="
|
|
716
|
+
<td className="p-2 border-b border-divider"><DatePicker mode="view" value="2026-04-02" /></td>
|
|
717
717
|
</tr>
|
|
718
718
|
<tr>
|
|
719
719
|
<Td mono>month: 'short'</Td>
|
|
@@ -721,7 +721,7 @@ export const StateBehavior = {
|
|
|
721
721
|
<DatePicker mode="readonly" value="2026-04-02" formatOptions={{ year: 'numeric', month: 'short', day: 'numeric' }} />
|
|
722
722
|
</td>
|
|
723
723
|
<td className="p-2 border-b border-divider">
|
|
724
|
-
<DatePicker mode="
|
|
724
|
+
<DatePicker mode="view" value="2026-04-02" formatOptions={{ year: 'numeric', month: 'short', day: 'numeric' }} />
|
|
725
725
|
</td>
|
|
726
726
|
</tr>
|
|
727
727
|
<tr>
|
|
@@ -730,7 +730,7 @@ export const StateBehavior = {
|
|
|
730
730
|
<DatePicker mode="readonly" value="2026-04-02" formatOptions={{ year: 'numeric', month: 'long', day: 'numeric' }} />
|
|
731
731
|
</td>
|
|
732
732
|
<td className="p-2 border-b border-divider">
|
|
733
|
-
<DatePicker mode="
|
|
733
|
+
<DatePicker mode="view" value="2026-04-02" formatOptions={{ year: 'numeric', month: 'long', day: 'numeric' }} />
|
|
734
734
|
</td>
|
|
735
735
|
</tr>
|
|
736
736
|
<tr>
|
|
@@ -739,13 +739,13 @@ export const StateBehavior = {
|
|
|
739
739
|
<DatePicker mode="readonly" value="2026-04-02" locale="zh-TW" formatOptions={{ year: 'numeric', month: 'long', day: 'numeric' }} />
|
|
740
740
|
</td>
|
|
741
741
|
<td className="p-2 border-b border-divider">
|
|
742
|
-
<DatePicker mode="
|
|
742
|
+
<DatePicker mode="view" value="2026-04-02" locale="zh-TW" formatOptions={{ year: 'numeric', month: 'long', day: 'numeric' }} />
|
|
743
743
|
</td>
|
|
744
744
|
</tr>
|
|
745
745
|
</tbody>
|
|
746
746
|
</table>
|
|
747
747
|
</div>
|
|
748
|
-
<span className="text-[11px] text-fg-muted">edit trigger 顯示文字與
|
|
748
|
+
<span className="text-[11px] text-fg-muted">edit trigger 顯示文字與 view 都用 Intl.DateTimeFormat 格式化(formatOptions / locale prop 對兩者皆生效,跨模式一致)。</span>
|
|
749
749
|
</div>
|
|
750
750
|
|
|
751
751
|
{/* Empty value display */}
|
|
@@ -761,8 +761,8 @@ export const StateBehavior = {
|
|
|
761
761
|
<DatePicker mode="disabled" value={null} className="w-48" />
|
|
762
762
|
</div>
|
|
763
763
|
<div className="flex items-center gap-3">
|
|
764
|
-
<span className="text-[11px] text-fg-muted w-20 shrink-0">
|
|
765
|
-
<DatePicker mode="
|
|
764
|
+
<span className="text-[11px] text-fg-muted w-20 shrink-0">view</span>
|
|
765
|
+
<DatePicker mode="view" value={null} />
|
|
766
766
|
</div>
|
|
767
767
|
</div>
|
|
768
768
|
</div>
|
|
@@ -51,7 +51,7 @@ export const UsageGuidance: Story = {
|
|
|
51
51
|
<li><LinkTo kind="Design System/Components/DatePicker/展示" name="可清除"><span className="text-primary hover:text-primary-hover font-medium cursor-pointer">篩選器的選填截止日,填錯一鍵清空(可清除)</span></LinkTo></li>
|
|
52
52
|
<li><LinkTo kind="Design System/Components/DatePicker/展示" name="尺寸"><span className="text-primary hover:text-primary-hover font-medium cursor-pointer">緊湊工具列與標準表單的尺寸對應(尺寸)</span></LinkTo></li>
|
|
53
53
|
<li><LinkTo kind="Design System/Components/DatePicker/展示" name="範圍模式:訂房 / 訂機票情境"><span className="text-primary hover:text-primary-hover font-medium cursor-pointer">Range:訂房 / 訂機票情境</span></LinkTo></li>
|
|
54
|
-
<li><LinkTo kind="Design System/Components/DatePicker/展示" name="
|
|
54
|
+
<li><LinkTo kind="Design System/Components/DatePicker/展示" name="檢視樣式"><span className="text-primary hover:text-primary-hover font-medium cursor-pointer">審批詳情頁唯讀展示申請日期(展示樣式)</span></LinkTo></li>
|
|
55
55
|
</ul>
|
|
56
56
|
<p className="text-fg-muted mt-3">判斷不確定時:對照 spec.md「何時用 / 何時不用」段;若仍不符,改用近親元件(見下方 vs 近親 段)。</p>
|
|
57
57
|
</div>
|
|
@@ -139,7 +139,7 @@ export const FormattingRule: Story = {
|
|
|
139
139
|
<div>
|
|
140
140
|
<Rule
|
|
141
141
|
title="格式化跨模式一致 — 預設 YYYY/MM/DD,傳 formatOptions / locale 走 Intl.DateTimeFormat"
|
|
142
|
-
note="未傳格式 prop 時預設直接組 YYYY/MM/DD(locale-independent);傳 formatOptions + locale 才啟用 Intl.DateTimeFormat,同時控制 readonly / disabled
|
|
142
|
+
note="未傳格式 prop 時預設直接組 YYYY/MM/DD(locale-independent);傳 formatOptions + locale 才啟用 Intl.DateTimeFormat,同時控制 view / readonly / disabled 的格式化文字與 edit trigger 顯示文字。跨模式一致、跨頁面可預期。Calendar popup 的月份語言由 Calendar 內部 locale 處理"
|
|
143
143
|
>
|
|
144
144
|
<DatePicker
|
|
145
145
|
mode="readonly"
|
|
@@ -157,7 +157,7 @@ export const FormattingRule: Story = {
|
|
|
157
157
|
|
|
158
158
|
<Rule
|
|
159
159
|
title="Edit trigger 文字也受 formatOptions / locale 控制"
|
|
160
|
-
note={'原本原生 <input type="date"> 的 trigger 格式受瀏覽器 locale 控制無法干預;改自建後,edit trigger 顯示的已選日期也走 Intl.DateTimeFormat——跟
|
|
160
|
+
note={'原本原生 <input type="date"> 的 trigger 格式受瀏覽器 locale 控制無法干預;改自建後,edit trigger 顯示的已選日期也走 Intl.DateTimeFormat——跟 view 模式完全一致'}
|
|
161
161
|
>
|
|
162
162
|
<DatePicker
|
|
163
163
|
value="2026-05-15"
|
|
@@ -170,7 +170,7 @@ export const FormattingRule: Story = {
|
|
|
170
170
|
|
|
171
171
|
<Rule
|
|
172
172
|
title="null 值統一顯示半形連字號"
|
|
173
|
-
note="
|
|
173
|
+
note="view 模式 null / undefined 顯示半形 -(foreground,同 readonly value 色),與其他 Field 元件一致"
|
|
174
174
|
>
|
|
175
175
|
<DatePicker mode="readonly" value={null} />
|
|
176
176
|
</Rule>
|
|
@@ -68,7 +68,7 @@ open 軸同樣只開最小 API — **uncontrolled-only**:`defaultOpen`(初始開
|
|
|
68
68
|
|------|------|------|
|
|
69
69
|
| 日期範圍(from → to) | **`<DatePicker.Range>`**(本檔下「DatePicker.Range」段,2026-04-21 新增) | 仿 Ant `DatePicker.RangePicker` 架構:雙 input + 箭頭 + 共用 calendar icon,Popover 展開兩月份並列 |
|
|
70
70
|
| 日期 + 時間(含時分) | **本元件加 `showTime` prop**(canonical 2026-05-02,Ant idiom) | DatePicker `showTime` / DatePickerRange `showTime` 內建 TimeColumns + 此刻/確定 footer;value 變 ISO datetime |
|
|
71
|
-
| 相對時間(「3 天前」「昨天」)|
|
|
71
|
+
| 相對時間(「3 天前」「昨天」)| 自訂展示元件 | DatePicker 的 view 態是絕對日期;相對時間需要計算 + locale 格式化 |
|
|
72
72
|
| 純文字 YYYY-MM-DD(不需要 picker)| `Input` | 如 API debug 介面、不需互動的純記錄 |
|
|
73
73
|
| 生日等「只有月日、不需要年」的欄位 | 目前用 DatePicker 忍受年份 | 多數情境可接受;要極致可自訂 MonthDayPicker |
|
|
74
74
|
| Notion / Google 式 event calendar 檢視 | **`<Calendar>`** 元件(見 `../Calendar/calendar.spec.md`,月/週/日 event view);**非本元件語義** | DatePicker 是「選日期」的 form control;Calendar 是「看事件」的頁面 canvas,兩者雖名字都有 calendar 但是不同 DS 元件 |
|
|
@@ -232,7 +232,7 @@ DateGrid cell 有 5 種語意視覺,每種用不同形狀/色彩語言避免混
|
|
|
232
232
|
- **needConfirm 獨立於 showTime**(2026-07-05 D4 codify):date-only `<DatePicker needConfirm>` 亦成立,footer 渲染 gate = `showTime || needConfirm`(single 與 Range 一致)——needConfirm 時「確定」是唯一 commit 路徑,漏渲 footer = draft 永遠無法 commit 的死路(2026-07-05 修 single 漏 `|| needConfirm`)
|
|
233
233
|
- showSeconds=false(default)→ TimeColumns 只顯示 H/M(對齊 Ant 預設)
|
|
234
234
|
- Range cell disable(對齊 Ant `useRangeDisabledDate`):activeEnd='start' + end 已選 → date > end disabled;activeEnd='end' + start 已選 → date < start disabled
|
|
235
|
-
- Range stadium pattern(canonical 2026-05-03 v8):
|
|
235
|
+
- Range stadium pattern(canonical 2026-05-03 v8):SSOT → `../DateGrid/date-grid.spec.md`(`range_start` / `range_end` 半圓 stadium 規則;class 細節見 `date-grid.tsx`)
|
|
236
236
|
|
|
237
237
|
### 為什麼用 prop 而非分離 `<DateTimePicker>` 元件
|
|
238
238
|
|
|
@@ -258,7 +258,7 @@ DateGrid cell 有 5 種語意視覺,每種用不同形狀/色彩語言避免混
|
|
|
258
258
|
| `formatOptions` | `Intl.DateTimeFormatOptions` | `{ year: 'numeric', month: 'short', day: 'numeric' }` |
|
|
259
259
|
| `locale` | BCP 47 locale | `'zh-TW'`、`'en-US'` |
|
|
260
260
|
|
|
261
|
-
預設(未傳 `formatOptions` / `locale`)直接組 `YYYY/MM/DD`(locale-independent,對齊 Ant year-first;見 date-picker.tsx `formatDate` 註解);傳 `formatOptions` / `locale` 才走 `Intl.DateTimeFormat`。
|
|
261
|
+
預設(未傳 `formatOptions` / `locale`)直接組 `YYYY/MM/DD`(locale-independent,對齊 Ant year-first;見 date-picker.tsx `formatDate` 註解);傳 `formatOptions` / `locale` 才走 `Intl.DateTimeFormat`。View / readonly / disabled 模式(含 DataTable cell)與 Edit 模式 trigger 文字同一條格式化路徑,兩者一致。
|
|
262
262
|
|
|
263
263
|
---
|
|
264
264
|
|
|
@@ -267,7 +267,7 @@ DateGrid cell 有 5 種語意視覺,每種用不同形狀/色彩語言避免混
|
|
|
267
267
|
`clearable` prop 在有值時顯示 clear 按鈕(endAction)。
|
|
268
268
|
|
|
269
269
|
- 只在 edit 模式顯示
|
|
270
|
-
- 清除後
|
|
270
|
+
- 清除後 `onChange?.('')`(空字串 = 空值;view 態顯示半形 -,text-foreground)
|
|
271
271
|
- **Dual-state sync canonical**(2026-05-03 v10):X 點擊必同時 `onChange?.('')` + `setDraft(null)`(Range 同),否則 `needConfirm=true`(showTime 預設)且 popover 開著時 `displayValue=draft` 仍顯示舊值,trigger 看起來「沒清」。X 在 trigger 上是 standard clear affordance,不走 needConfirm「等確定」語義 — 立刻 commit + 同步 draft
|
|
272
272
|
|
|
273
273
|
---
|
|
@@ -284,16 +284,16 @@ DateGrid cell 有 5 種語意視覺,每種用不同形狀/色彩語言避免混
|
|
|
284
284
|
|
|
285
285
|
DatePicker 套 `React.forwardRef` + `displayName`;`DatePickerProps` extends `Omit<React.HTMLAttributes<HTMLDivElement>, 'value' | 'onChange' | 'placeholder' | 'defaultValue'>`,剩餘 DOM attrs `...props` spread 到**當前 mode 的 root wrapper**(edit trigger `<div role="combobox">` / readonly · disabled wrapper div / Range wrapper div)。
|
|
286
286
|
|
|
287
|
-
**例外**:`mode="
|
|
287
|
+
**例外**:`mode="view"` 預設(未 opt-in `showDisplayEndIcon`)輸出裸 `<span>`,**不** spread `...props`——consumer 傳 DOM attrs(`data-testid` / `onFocus` 等)時注意 view 模式不生效;`className` 各 mode 皆顯式接收(套在該 mode 的 root 元素)。
|
|
288
288
|
|
|
289
|
-
**`asChild` 不支援**:trigger 是 compound(
|
|
289
|
+
**`asChild` 不支援**:trigger 是 compound(view 裸 span / edit `div role="combobox"` 不同 render tree),無單一 Slot 目標。consumer 若要自訂 trigger 視覺,改用 `<DatePicker mode="view">` + 自家 Button composition。
|
|
290
290
|
|
|
291
291
|
---
|
|
292
292
|
|
|
293
293
|
## A11y 預設
|
|
294
294
|
|
|
295
295
|
- Trigger:`role="combobox"` + `aria-haspopup="dialog"` + `aria-expanded={open}` + 必含 accessible name(`aria-label` / 或外層 `<label>` / 或 fieldCtx label)
|
|
296
|
-
- Popover content:`role="dialog"`;單一日期 popover
|
|
296
|
+
- Popover content:`role="dialog"`;單一日期 popover 的 PopoverContent 帶 `aria-label="日期選擇"`(date-picker.tsx:650,DS default dialog label),Range popover 加 `aria-label="日期區間選擇"`
|
|
297
297
|
- DateGrid 鍵盤:Arrow keys 切日 / PageUp/Down 切月 / Home/End 行首尾(react-day-picker v9 內建)
|
|
298
298
|
- Trigger 鍵盤(Space / Enter open;Esc close + 回焦):單一 DatePicker 的 `<div role="combobox">` 無 native Enter/Space→click,由元件**自建 `onKeyDown`** 開 popover(Radix PopoverTrigger 只 compose onClick;date-picker.tsx:554),Esc 關閉後靠 PopoverTrigger 的 Radix **內建** `triggerRef.focus()` 回焦;Range 用 native `<button>` onClick 開、只掛 PopoverAnchor(triggerRef 恆 null → 內建回焦 no-op),改由**自建 `onCloseAutoFocus`** 手動回焦 active 端 button(date-picker.tsx:1020-1026,守 WCAG 2.4.3)
|
|
299
299
|
- Range 雙 trigger:`activeEnd` state 指向當前編輯端,`aria-expanded` 對應只當該 trigger active 時 true
|
|
@@ -311,11 +311,11 @@ DatePicker 套 `React.forwardRef` + `displayName`;`DatePickerProps` extends `Omi
|
|
|
311
311
|
|
|
312
312
|
## 邊界案例
|
|
313
313
|
|
|
314
|
-
- **Disabled**:Field SSOT own;resolvedMode='disabled' 走 readonly / disabled 純 wrapper 分支(無 Popover trigger、`aria-disabled`、不開 picker),文字與 Calendar icon 切 `text-fg-disabled`。readonly 不顯示 Calendar icon(類型身份 indicator 規則,SSOT field-controls.spec.md
|
|
314
|
+
- **Disabled**:Field SSOT own;resolvedMode='disabled' 走 readonly / disabled 純 wrapper 分支(無 Popover trigger、`aria-disabled`、不開 picker),文字與 Calendar icon 切 `text-fg-disabled`。readonly 不顯示 Calendar icon(類型身份 indicator 規則,SSOT field-controls.spec.md「下拉箭頭與類型身份 indicator」段 L266-276);disabled 保留並切 `fg-disabled`。顯式 `mode="view"` 永遠最優先(useResolvedFieldMode step 1,見 field-context.ts):view + disabled 同傳走 view 分支不套 disabled token;要 disabled chrome 傳 `disabled` 或 `mode="disabled"`。
|
|
315
315
|
- **Loading(server-rendered grid)**:DatePicker 為 sync UI 不獨立 own loading。若 consumer 場景需 async date constraint fetch(如後端 disabled-dates list),consumer 應先 disable trigger 直到 fetch 完成,或在 popover 開啟後 body 切 `<Empty icon={<CircularProgress/>}/>`(對齊 panel-body loading SSOT)。本 spec scope 內不渲 loading state。
|
|
316
316
|
- **Empty(no value)**:`value=null` → trigger 顯 placeholder(預設 `YYYY/MM/DD`,showTime 時 `YYYY/MM/DD HH:MM`;consumer 可傳 `placeholder` 覆寫)。無導覽目標時鍵盤焦點停留(react-day-picker v9 內建)。
|
|
317
317
|
- **Invalid date input**:Field validation 處理 `aria-invalid="true"` + error border + 下方 error message;DatePicker 本身不 own validation 規則。
|
|
318
|
-
- **極長格式化日期**:trigger 文字單行 `truncate`(ellipsis),不換行不撐高(
|
|
318
|
+
- **極長格式化日期**:trigger 文字單行 `truncate`(ellipsis),不換行不撐高(View / Edit / typeable / Range 雙 input 皆同)。
|
|
319
319
|
- **RTL**:未實作方向鏡像(trigger / Range 雙 input / DateGrid 皆以 LTR physical 方向設計);RTL 屬 DS-wide 決策,未定(與 Chip / Breadcrumb 同口徑)。
|
|
320
320
|
- **Dark mode / density**:走 Field + Popover SSOT 自動 adapt;DateGrid 內 cell 尺寸 density-aware(消費 `--field-height-sm`:md=28×28 / lg=32×32,對齊 L128 + `date-grid.spec.md:120`),隨 density 縮放而非固定。
|
|
321
321
|
|
|
@@ -333,6 +333,7 @@ DatePicker 套 `React.forwardRef` + `displayName`;`DatePickerProps` extends `Omi
|
|
|
333
333
|
|
|
334
334
|
- `calendar.spec.md`
|
|
335
335
|
- `date-grid.spec.md`
|
|
336
|
+
- `header-canonical.spec.md`
|
|
336
337
|
- `input.spec.md`
|
|
337
338
|
- `number-input.spec.md`
|
|
338
339
|
- `time-picker.spec.md`
|
|
@@ -76,8 +76,8 @@ export const Modes: Story = {
|
|
|
76
76
|
</div>
|
|
77
77
|
{/* @story-trait-rationale: pre-existing trait gaps tracked separately */}
|
|
78
78
|
<div>
|
|
79
|
-
<h3 className="text-body font-bold text-foreground mb-2">
|
|
80
|
-
<DatePicker mode="
|
|
79
|
+
<h3 className="text-body font-bold text-foreground mb-2">view</h3>
|
|
80
|
+
<DatePicker mode="view" value="2026-04-02" />
|
|
81
81
|
</div>
|
|
82
82
|
<div>
|
|
83
83
|
<h3 className="text-body font-bold text-foreground mb-2">readonly</h3>
|
|
@@ -315,26 +315,26 @@ export const ShowTimeRange: Story = {
|
|
|
315
315
|
},
|
|
316
316
|
}
|
|
317
317
|
|
|
318
|
-
/* ──
|
|
319
|
-
export const
|
|
320
|
-
name: '
|
|
318
|
+
/* ── View(DataTable cell 用)── */
|
|
319
|
+
export const View: Story = {
|
|
320
|
+
name: '檢視樣式',
|
|
321
321
|
render: () => (
|
|
322
322
|
<div className="flex flex-col gap-3">
|
|
323
323
|
<div className="flex items-center gap-3">
|
|
324
324
|
<span className="text-caption text-fg-muted w-20">預設</span>
|
|
325
|
-
<DatePicker mode="
|
|
325
|
+
<DatePicker mode="view" value="2026-04-02" />
|
|
326
326
|
</div>
|
|
327
327
|
<div className="flex items-center gap-3">
|
|
328
328
|
<span className="text-caption text-fg-muted w-20">完整月份</span>
|
|
329
|
-
<DatePicker mode="
|
|
329
|
+
<DatePicker mode="view" value="2026-04-02" formatOptions={{ year: 'numeric', month: 'long', day: 'numeric' }} />
|
|
330
330
|
</div>
|
|
331
331
|
<div className="flex items-center gap-3">
|
|
332
332
|
<span className="text-caption text-fg-muted w-20">zh-TW</span>
|
|
333
|
-
<DatePicker mode="
|
|
333
|
+
<DatePicker mode="view" value="2026-04-02" locale="zh-TW" formatOptions={{ year: 'numeric', month: 'long', day: 'numeric' }} />
|
|
334
334
|
</div>
|
|
335
335
|
<div className="flex items-center gap-3">
|
|
336
336
|
<span className="text-caption text-fg-muted w-20">null</span>
|
|
337
|
-
<DatePicker mode="
|
|
337
|
+
<DatePicker mode="view" value={null} />
|
|
338
338
|
</div>
|
|
339
339
|
</div>
|
|
340
340
|
),
|
|
@@ -328,9 +328,9 @@ export interface DatePickerProps
|
|
|
328
328
|
*/
|
|
329
329
|
needConfirm?: boolean
|
|
330
330
|
/**
|
|
331
|
-
*
|
|
332
|
-
* — DataTable cell
|
|
333
|
-
* 設 true 時
|
|
331
|
+
* View 態是否渲 Calendar icon + Field naked wrapper(D-path opt-in,2026-05-08)
|
|
332
|
+
* — DataTable cell view↔edit 像素級對齊用。預設 false(裸 span,backward compat)。
|
|
333
|
+
* 設 true 時 view 走 fieldWrapperStyles(naked variant)+ ItemSuffix CalendarIcon,
|
|
334
334
|
* 與 edit 同 DOM 結構,消除 Layer-B padding mismatch。
|
|
335
335
|
*/
|
|
336
336
|
showDisplayEndIcon?: boolean
|
|
@@ -409,7 +409,7 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
|
|
|
409
409
|
const size = useResolvedFieldSize(sizeProp) // B 組 cascade fix:<Field size>/cell surface-size 對 DatePicker 生效
|
|
410
410
|
const error = useResolvedFieldInvalid(errorProp)
|
|
411
411
|
const disabled = useResolvedFieldDisabled(disabledProp)
|
|
412
|
-
// 2026-06-08 SSOT:mode 經 useResolvedFieldMode;修 <Field mode="
|
|
412
|
+
// 2026-06-08 SSOT:mode 經 useResolvedFieldMode;修 <Field mode="view"> 漏 cascade
|
|
413
413
|
const resolvedMode = useResolvedFieldMode({ mode, disabled })
|
|
414
414
|
const emptyDisplay = useFieldEmptyDisplay()
|
|
415
415
|
const variant: FieldVariantInternal = useResolvedFieldVariant(variantProp)
|
|
@@ -475,21 +475,21 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
|
|
|
475
475
|
}
|
|
476
476
|
}, [onChange, showTime])
|
|
477
477
|
|
|
478
|
-
// mode='
|
|
478
|
+
// mode='view'(Phase B2 2026-05-05):純內容輸出 — 對齊原 DatePickerDisplay sub-component(retired)。
|
|
479
479
|
// Default(showDisplayEndIcon=false):無 Field wrapper / 無 Calendar icon — backward compat 裸 span。
|
|
480
480
|
// Opt-in(showDisplayEndIcon=true,2026-05-08 D-path):Field naked wrapper + ItemSuffix Calendar,
|
|
481
|
-
// 與 edit 同結構消除 cell
|
|
482
|
-
if (resolvedMode === '
|
|
481
|
+
// 與 edit 同結構消除 cell view↔edit 像素偏移(Layer-B padding mismatch)。
|
|
482
|
+
if (resolvedMode === 'view') {
|
|
483
483
|
if (!showDisplayEndIcon) {
|
|
484
|
-
// 2026-05-14 I2 fix(spec contract (e)
|
|
484
|
+
// 2026-05-14 I2 fix(spec contract (e) view typography canonical):bare span 套
|
|
485
485
|
// `fieldDisplayTextClass(size)`(sm/md→text-body,lg→text-body-lg)— 對齊 Field family 統一。
|
|
486
486
|
if (!value) return <span className={cn(fieldDisplayTextClass(size), fieldEmptyColorClass(resolvedMode), className)}>{emptyDisplay}</span>
|
|
487
487
|
return <span className={cn(fieldDisplayTextClass(size), 'truncate', className)}>{displayCommitted}</span>
|
|
488
488
|
}
|
|
489
489
|
return (
|
|
490
490
|
<div
|
|
491
|
-
className={cn(fieldWrapperStyles({ mode: '
|
|
492
|
-
data-field-mode="
|
|
491
|
+
className={cn(fieldWrapperStyles({ mode: 'view', variant, width, size }), className)}
|
|
492
|
+
data-field-mode="view"
|
|
493
493
|
>
|
|
494
494
|
<span className={cn(bareInputStyles, 'flex-1 min-w-0 truncate', !value && fieldEmptyColorClass(resolvedMode))}>
|
|
495
495
|
{value ? displayCommitted : emptyDisplay}
|
|
@@ -801,7 +801,7 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
|
|
|
801
801
|
const size = useResolvedFieldSize(sizeProp) // B 組 cascade fix:<Field size>/cell surface-size 對 DatePicker 生效
|
|
802
802
|
const error = useResolvedFieldInvalid(errorProp)
|
|
803
803
|
const disabled = useResolvedFieldDisabled(disabledProp)
|
|
804
|
-
// 2026-06-08 SSOT:mode 經 useResolvedFieldMode;修 <Field mode="
|
|
804
|
+
// 2026-06-08 SSOT:mode 經 useResolvedFieldMode;修 <Field mode="view"> 漏 cascade
|
|
805
805
|
const resolvedMode = useResolvedFieldMode({ mode, disabled })
|
|
806
806
|
const emptyDisplay = useFieldEmptyDisplay()
|
|
807
807
|
const variant: FieldVariantInternal = useResolvedFieldVariant(variantProp)
|
|
@@ -936,8 +936,8 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
|
|
|
936
936
|
return false
|
|
937
937
|
}, [activeEnd, startDate, endDate])
|
|
938
938
|
|
|
939
|
-
// mode='
|
|
940
|
-
if (resolvedMode === '
|
|
939
|
+
// mode='view'(Phase B2 2026-05-05):純內容輸出 — 無 Field wrapper / 無 Calendar icon。
|
|
940
|
+
if (resolvedMode === 'view') {
|
|
941
941
|
const hasAny = !!(startIso || endIso)
|
|
942
942
|
if (!hasAny) return <span className={cn(fieldEmptyColorClass(resolvedMode), className)}>{emptyDisplay}</span>
|
|
943
943
|
return (
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// foreground(value),無 variant × state 色彩矩陣。色彩 token 已於
|
|
6
6
|
// Overview「Typography(閱讀模式)」段列出。
|
|
7
7
|
// SizeMatrix N/A — 不提供 size prop;大小固定 text-body(14px reading mode),
|
|
8
|
-
// 由 layout(cols /
|
|
8
|
+
// 由 layout(cols / orientation / divided)而非 size 決定差異。ColsMatrix 已
|
|
9
9
|
// 涵蓋 layout 變化。
|
|
10
10
|
import type { Meta, StoryObj } from '@storybook/react'
|
|
11
11
|
import { DescriptionList, DescriptionItem } from './description-list'
|
|
@@ -54,7 +54,7 @@ export const Overview: Story = {
|
|
|
54
54
|
<Desc>items 之間垂直間距走 `--layout-space-tight` token(density-aware)——切 density 自動適配,避免硬寫 px / py-N 脫鉤 token;label → value(同 item 內)走 `--item-gap-label-desc-reading`(2px,見下表 row 1)。</Desc>
|
|
55
55
|
<div className="overflow-x-auto">
|
|
56
56
|
<table className="text-caption border-collapse">
|
|
57
|
-
<thead><tr><Th>
|
|
57
|
+
<thead><tr><Th>Orientation</Th><Th>位置</Th><Th>Value</Th><Th>Rationale</Th></tr></thead>
|
|
58
58
|
<tbody>
|
|
59
59
|
<tr><Td mono>vertical</Td><Td>label → value(同 item 內)</Td><Td mono>--item-gap-label-desc-reading(2px)</Td><Td>極小間距,視覺上 label 與 value 緊密配對(dt body + dd body → reading token)</Td></tr>
|
|
60
60
|
<tr><Td mono>vertical</Td><Td>items 之間垂直 gap</Td><Td mono>gap-y-[var(--layout-space-tight)]</Td><Td>density-aware;Gestalt proximity 群組</Td></tr>
|
|
@@ -73,16 +73,16 @@ export const Overview: Story = {
|
|
|
73
73
|
export const Inspector: Story = {
|
|
74
74
|
name: '元件檢閱器',
|
|
75
75
|
parameters: {
|
|
76
|
-
docs: { description: { story: '右側 Controls 切 props 即時 render,取代 Figma inspect。調整 `cols` / `
|
|
76
|
+
docs: { description: { story: '右側 Controls 切 props 即時 render,取代 Figma inspect。調整 `cols` / `orientation` / `divided` 看 CSS grid 配置變化。' } },
|
|
77
77
|
},
|
|
78
78
|
args: {
|
|
79
79
|
cols: 2,
|
|
80
|
-
|
|
80
|
+
orientation: 'vertical',
|
|
81
81
|
divided: false,
|
|
82
82
|
},
|
|
83
83
|
argTypes: {
|
|
84
84
|
cols: { control: 'radio', options: [1, 2, 3] },
|
|
85
|
-
|
|
85
|
+
orientation: { control: 'radio', options: ['vertical', 'horizontal'] },
|
|
86
86
|
divided: { control: 'boolean', description: 'horizontal 模式下,每個 item 下加 border-b 對齊 rows(長列表建議開)' },
|
|
87
87
|
},
|
|
88
88
|
render: (args) => (
|
|
@@ -197,7 +197,7 @@ export const LabelAlignmentRule: Story = {
|
|
|
197
197
|
<div>
|
|
198
198
|
<Rule
|
|
199
199
|
title="本系統採 stacked(label 在上、value 在下)— label 左對齊"
|
|
200
|
-
note="對齊 Atlassian / Shopify Polaris / Stripe 慣例——label 與 value 垂直堆疊,兩者都左對齊。閱讀節奏由上往下、由左往右,不需視線左右跳動。這是 vertical(預設)模式的結構;label 左 / value 右的 metadata 列改用既有 `
|
|
200
|
+
note="對齊 Atlassian / Shopify Polaris / Stripe 慣例——label 與 value 垂直堆疊,兩者都左對齊。閱讀節奏由上往下、由左往右,不需視線左右跳動。這是 vertical(預設)模式的結構;label 左 / value 右的 metadata 列改用既有 `orientation="horizontal"` prop(見 spec「Orientation」段)"
|
|
201
201
|
>
|
|
202
202
|
<Frame className="max-w-md">
|
|
203
203
|
<DescriptionList cols={2}>
|
|
@@ -225,7 +225,7 @@ export const LabelAlignmentRule: Story = {
|
|
|
225
225
|
|
|
226
226
|
<Rule
|
|
227
227
|
title="❌ 不要自己用 flex 改 horizontal layout"
|
|
228
|
-
note="手刻 flex 模擬 label 左 / value 右 → 失去 dl/dt/dd 語意,且多欄配置下 grid 對齊錯亂。有此需求 → 用既有 `
|
|
228
|
+
note="手刻 flex 模擬 label 左 / value 右 → 失去 dl/dt/dd 語意,且多欄配置下 grid 對齊錯亂。有此需求 → 用既有 `orientation="horizontal"` prop(dl/dt/dd 語意完整保留,見 showcase「水平佈局」story),不要自組 layout"
|
|
229
229
|
>
|
|
230
230
|
<Frame className="max-w-md">
|
|
231
231
|
<div className="flex justify-between py-1">
|
|
@@ -44,11 +44,11 @@ benchmark:
|
|
|
44
44
|
## 結構
|
|
45
45
|
|
|
46
46
|
- `DescriptionList`:外層 `dl`,vertical 模式為 CSS grid、horizontal 模式為 flex column
|
|
47
|
-
- `DescriptionItem`:一組 `dt`(label)+ `dd`(value),透過 context 知道當前
|
|
47
|
+
- `DescriptionItem`:一組 `dt`(label)+ `dd`(value),透過 context 知道當前 orientation 自動切 layout
|
|
48
48
|
|
|
49
|
-
##
|
|
49
|
+
## Orientation(2026-04-20 新增)
|
|
50
50
|
|
|
51
|
-
|
|
|
51
|
+
| orientation | Layout | 典型情境 | 世界級對照 |
|
|
52
52
|
|-----------|--------|---------|-----------|
|
|
53
53
|
| `vertical`(預設)| label 在上 / value 在下 | ProfileCard detail、sidebar 長 value(地址、bio) | Atlassian DescriptionList、Polaris DescriptionList |
|
|
54
54
|
| `horizontal` | label 左 / value 右對齊 | **file info panel / 訂單詳情 / settings summary**(短 value 的 metadata 列) | Google Drive file info、Notion file panel、iOS Settings | <!-- @benchmark-unverified: see frontmatter benchmark list for canonical DS source URL -->
|
|
@@ -63,13 +63,13 @@ benchmark:
|
|
|
63
63
|
|
|
64
64
|
```tsx
|
|
65
65
|
// 短 metadata 列,無需 divider
|
|
66
|
-
<DescriptionList
|
|
66
|
+
<DescriptionList orientation="horizontal">
|
|
67
67
|
<DescriptionItem label="建立">2026-04-20</DescriptionItem>
|
|
68
68
|
<DescriptionItem label="修改">2026-04-20</DescriptionItem>
|
|
69
69
|
</DescriptionList>
|
|
70
70
|
|
|
71
71
|
// 檔案資訊 — 多 row + key 長度不一 → divided 對齊格線
|
|
72
|
-
<DescriptionList
|
|
72
|
+
<DescriptionList orientation="horizontal" divided>
|
|
73
73
|
<DescriptionItem label="檔名">Q1 財報分析.xlsx</DescriptionItem>
|
|
74
74
|
<DescriptionItem label="類型">application/vnd.xlsx</DescriptionItem>
|
|
75
75
|
<DescriptionItem label="大小">1.2 MB</DescriptionItem>
|
|
@@ -86,18 +86,18 @@ benchmark:
|
|
|
86
86
|
|
|
87
87
|
## 間距
|
|
88
88
|
|
|
89
|
-
### Vertical
|
|
89
|
+
### Vertical orientation
|
|
90
90
|
|
|
91
91
|
- **label → value**(同 item 內):`--item-gap-label-desc-reading` token(2px)——極小間距,視覺上 label 與 value 緊密配對
|
|
92
92
|
- **items 之間垂直 gap**:`gap-y-[var(--layout-space-tight)]`——density-aware,跟隨系統密度設定
|
|
93
93
|
- **columns 之間水平 gap**:`gap-x-4`(16px)
|
|
94
94
|
|
|
95
|
-
### Horizontal
|
|
95
|
+
### Horizontal orientation(divided=false)
|
|
96
96
|
|
|
97
97
|
- **items 之間垂直 gap**:`mb-[var(--layout-space-tight)]` per item(last:mb-0)——density-aware,等同 vertical 的 items gap
|
|
98
98
|
- label ↔ value 水平距離:`justify-between` + `gap-4`(最小 16px,content 之間拉開)
|
|
99
99
|
|
|
100
|
-
### Horizontal
|
|
100
|
+
### Horizontal orientation(divided=true)
|
|
101
101
|
|
|
102
102
|
- 每個 item `py-[var(--layout-space-tight)]`(density-aware,形成 cell-like row 高度)
|
|
103
103
|
- 每個 item 底部 `border-b border-divider`,`last:border-b-0`——row 之間視覺格線,key 長度不一時易於對齊掃描
|
|
@@ -106,9 +106,9 @@ benchmark:
|
|
|
106
106
|
|
|
107
107
|
## Props
|
|
108
108
|
|
|
109
|
-
### `
|
|
109
|
+
### `orientation`:vertical / horizontal
|
|
110
110
|
|
|
111
|
-
見上「
|
|
111
|
+
見上「Orientation」段。
|
|
112
112
|
|
|
113
113
|
### `divided`:horizontal 專用 row divider
|
|
114
114
|
|
|
@@ -184,11 +184,11 @@ consumer 要在 DL 上方加 section heading(「基本資料」/「團隊資訊
|
|
|
184
184
|
|
|
185
185
|
DescriptionList 是**唯讀 label / value 資料呈現**(非互動 / 非 variant 驅動):
|
|
186
186
|
|
|
187
|
-
- **有 Inspector**:DL 雖唯讀,但有 layout prop 可即時切換——`Inspector` story 暴露 `cols`(1 / 2 / 3)/ `
|
|
187
|
+
- **有 Inspector**:DL 雖唯讀,但有 layout prop 可即時切換——`Inspector` story 暴露 `cols`(1 / 2 / 3)/ `orientation`(vertical / horizontal)/ `divided` 三個 prop 的 Controls,取代 Figma inspect。`orientation` 與 `divided` 是 `ColsMatrix`(只示範 cols)沒涵蓋的維度。
|
|
188
188
|
- **無 ColorMatrix**:DL 固定 semantic token(label `text-fg-secondary` / value `text-foreground`),無自己的色彩變體,dark mode 由 semantic token 自動切換。加 color variant 不符語意(DL 是資訊展示,非狀態載體)。
|
|
189
189
|
- **無 SizeMatrix**:DL 無 size prop——垂直間距隨 `layout-space` token 感知 density(見「間距」段),但 label / value typography 走 reading mode 固定 tier,不提供 sm / md / lg 變體。不同 density 由 token 自動處理,非 prop 切換。
|
|
190
190
|
|
|
191
|
-
對應 anatomy story(實際 5 個,對齊 6-canonical 結構;ColorMatrix / SizeMatrix N/A):`Overview`(anatomy + typography + 間距) + `Inspector`(Controls 即時切 `cols` / `
|
|
191
|
+
對應 anatomy story(實際 5 個,對齊 6-canonical 結構;ColorMatrix / SizeMatrix N/A):`Overview`(anatomy + typography + 間距) + `Inspector`(Controls 即時切 `cols` / `orientation` / `divided`) + `ColsMatrix`(元件特有 1 / 2 / 3 欄對照) + `StateBehavior`(空值 `-` / 長值 / 多行 / ReactNode value) + `Accessibility`(`dl/dt/dd` 語意 + 無互動說明)。
|
|
192
192
|
|
|
193
193
|
---
|
|
194
194
|
|
|
@@ -89,14 +89,14 @@ export const DetailPanel: Story = {
|
|
|
89
89
|
),
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
/* ── Horizontal
|
|
92
|
+
/* ── Horizontal orientation(label 左 / value 右,divided=false)──────── */
|
|
93
93
|
export const Horizontal: Story = {
|
|
94
94
|
name: '水平佈局',
|
|
95
95
|
render: () => (
|
|
96
96
|
<div className="border border-border rounded-lg p-[var(--layout-space-loose)] max-w-md">
|
|
97
97
|
{/* title 到第一個 item 的間距 = item 之間間距(Gestalt proximity canonical,見 spec) */}
|
|
98
98
|
<div className="text-body font-medium mb-[var(--layout-space-tight)]">檔案資訊</div>
|
|
99
|
-
<DescriptionList
|
|
99
|
+
<DescriptionList orientation="horizontal">
|
|
100
100
|
<DescriptionItem label="檔名">Q1-roadmap.pdf</DescriptionItem>
|
|
101
101
|
<DescriptionItem label="類型">application/pdf</DescriptionItem>
|
|
102
102
|
<DescriptionItem label="大小">2.4 MB</DescriptionItem>
|
|
@@ -107,7 +107,7 @@ export const Horizontal: Story = {
|
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
// @story-trait-rationale: HorizontalDivided retired 2026-05-17 per audit Dim 24/25 strict re-run —
|
|
110
|
-
// 違 story-rules.md L42「同 affordance 內 prop variations 用 Controls 不另開」。Horizontal
|
|
110
|
+
// 違 story-rules.md L42「同 affordance 內 prop variations 用 Controls 不另開」。Horizontal orientation
|
|
111
111
|
// 已展示;divided 是單一 prop toggle,anatomy Inspector 已 expose Controls (L85-86)。
|
|
112
112
|
// 原本內容 archive 於 git history(若要看 divided 視覺,進 anatomy Inspector 開 divided=true)。
|
|
113
113
|
// 2026-06-12:刪除 zombie export _RETIRED_HorizontalDivided,對齊 DS-wide comment-only 退役慣例(deep-audit dim25)。
|
|
@@ -12,7 +12,7 @@ import { cn } from '@/lib/utils'
|
|
|
12
12
|
* value (dd): text-body (14px) text-foreground (neutral-9)
|
|
13
13
|
* 兩者都是 14px × 1.5 行高——層級靠色彩區分,不靠字體大小。
|
|
14
14
|
*
|
|
15
|
-
* ──
|
|
15
|
+
* ── orientation(2026-04-20 新增)──
|
|
16
16
|
* vertical(預設):label 在上 / value 在下,適合長 value(地址、bio、說明段落)、
|
|
17
17
|
* form-like 資訊展示
|
|
18
18
|
* horizontal :label 左 / value 右對齊,適合短 value 的 metadata 列
|
|
@@ -30,15 +30,15 @@ import { cn } from '@/lib/utils'
|
|
|
30
30
|
* divided horizontal 模式:每 item py-[var(--layout-space-tight)](cell-like row 高度)
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
|
-
export type
|
|
33
|
+
export type DescriptionListOrientation = 'vertical' | 'horizontal'
|
|
34
34
|
|
|
35
35
|
interface DescriptionContextValue {
|
|
36
|
-
|
|
36
|
+
orientation: DescriptionListOrientation
|
|
37
37
|
divided: boolean
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
const DescriptionContext = React.createContext<DescriptionContextValue>({
|
|
41
|
-
|
|
41
|
+
orientation: 'vertical',
|
|
42
42
|
divided: false,
|
|
43
43
|
})
|
|
44
44
|
|
|
@@ -46,7 +46,7 @@ export interface DescriptionListProps extends React.HTMLAttributes<HTMLDListElem
|
|
|
46
46
|
/** grid 欄數(vertical 才生效;horizontal 永遠單欄),預設 1 */
|
|
47
47
|
cols?: 1 | 2 | 3
|
|
48
48
|
/** 項目排列方向,預設 vertical(label 在上 / value 在下) */
|
|
49
|
-
|
|
49
|
+
orientation?: DescriptionListOrientation
|
|
50
50
|
/**
|
|
51
51
|
* horizontal 模式下每個 item 下方加分隔線以對齊 rows。預設 false。
|
|
52
52
|
* 短列表(< 4 rows)不需要;檔案 metadata 等長列表、key 長度不一時建議開。
|
|
@@ -61,10 +61,10 @@ const colsClass: Record<number, string> = {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
const DescriptionList = React.forwardRef<HTMLDListElement, DescriptionListProps>(
|
|
64
|
-
({ cols = 1,
|
|
65
|
-
const isHorizontal =
|
|
64
|
+
({ cols = 1, orientation = 'vertical', divided = false, className, ...props }, ref) => {
|
|
65
|
+
const isHorizontal = orientation === 'horizontal'
|
|
66
66
|
// Memoize provider value(2026-04-22 D3 perf audit):避免每 render 重建 2-field object
|
|
67
|
-
const ctxValue = React.useMemo(() => ({
|
|
67
|
+
const ctxValue = React.useMemo(() => ({ orientation, divided }), [orientation, divided])
|
|
68
68
|
return (
|
|
69
69
|
<DescriptionContext.Provider value={ctxValue}>
|
|
70
70
|
<dl
|
|
@@ -90,8 +90,8 @@ export interface DescriptionItemProps extends React.HTMLAttributes<HTMLDivElemen
|
|
|
90
90
|
|
|
91
91
|
const DescriptionItem = React.forwardRef<HTMLDivElement, DescriptionItemProps>(
|
|
92
92
|
({ label, children, className, ...props }, ref) => {
|
|
93
|
-
const {
|
|
94
|
-
if (
|
|
93
|
+
const { orientation, divided } = React.useContext(DescriptionContext)
|
|
94
|
+
if (orientation === 'horizontal') {
|
|
95
95
|
return (
|
|
96
96
|
<div
|
|
97
97
|
ref={ref}
|
|
@@ -52,7 +52,10 @@ const DialogOverlay = React.forwardRef<
|
|
|
52
52
|
))
|
|
53
53
|
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
// asChild Omit(2026-07-18 決策2):DialogContent 是固定 surface chrome(overlay + 定位 +
|
|
56
|
+
// bg/rounded/shadow + onOpenAutoFocus),恆渲染 {children}(consumer body,通常 Header+Body+Footer
|
|
57
|
+
// 多節點)→ <Content asChild> Radix Slot React.Children.only crash。children 保留(consumer body)。
|
|
58
|
+
interface DialogContentProps extends Omit<React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>, 'asChild'> {
|
|
56
59
|
/** 最大寬度。預設 512px。傳 number 視為 px。 */
|
|
57
60
|
maxWidth?: string | number
|
|
58
61
|
/**
|