@qijenchen/design-system 0.1.0-beta.85 → 0.1.0-beta.86
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 +11 -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 +7 -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 +9 -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/Field/field-context.ts +17 -11
- package/src/components/Field/field-controls.spec.md +44 -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 +4 -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 +2 -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 +9 -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 +3 -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/element-anatomy/inline-action.spec.md +1 -1
- 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/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
|
@@ -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
|
/**
|
|
@@ -40,6 +40,7 @@ import { overlayMotion } from "@/design-system/tokens/motion/overlay-motion"
|
|
|
40
40
|
*/
|
|
41
41
|
|
|
42
42
|
// ── Floating layer 共用樣式 ──
|
|
43
|
+
/** @internal — menu 形浮層共用 class(DropdownMenu/SelectMenu/Command 內部);consumer 不 hand-craft menu surface,用元件本身。root barrel 排除(subpath 仍可 wrap 後用)。 */
|
|
43
44
|
const floatingLayerClass = [
|
|
44
45
|
'z-50 overflow-hidden rounded-lg border border-border bg-surface-raised',
|
|
45
46
|
overlayMotion,
|
|
@@ -121,11 +122,17 @@ const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
|
|
|
121
122
|
|
|
122
123
|
// ── Content ──
|
|
123
124
|
interface DropdownMenuContentProps
|
|
124
|
-
|
|
125
|
+
// asChild Omit(2026-07-18 決策2):Content 恆注入固定 <RowSizeProvider> + <ScrollArea>
|
|
126
|
+
// wrapper 於 Portal 內 → <Content asChild> 會把 Content props slot-merge 到非-DOM Provider 上而壞。
|
|
127
|
+
// children 保留(合法渲染於固定 wrapper 內)。
|
|
128
|
+
extends Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>, 'asChild'> {
|
|
125
129
|
size?: SizeKey
|
|
126
130
|
/** 最小寬度(px),預設 `max(180px, 觸發元件寬度)`——窄 trigger 時吃 180px 地板 */
|
|
127
131
|
minWidth?: number
|
|
128
|
-
/**
|
|
132
|
+
/**
|
|
133
|
+
* 最大高度(px)——**可選更低上限**。預設已 viewport-adaptive(夾到 trigger→視窗碰撞邊界的剩餘高度、
|
|
134
|
+
* 離窗 ≥8px、超過即捲動);傳 `maxHeight` 只在「想比視窗剩餘更矮」時用(取 `min(視窗剩餘, maxHeight)`)。
|
|
135
|
+
*/
|
|
129
136
|
maxHeight?: number
|
|
130
137
|
}
|
|
131
138
|
|
|
@@ -154,24 +161,26 @@ const DropdownMenuContent = React.forwardRef<
|
|
|
154
161
|
// close 後 programmatic refocus 在 Chromium 仍可 match `:focus-visible`(UA heuristic),
|
|
155
162
|
// 但與 shadcn 官方 live demo 同流程 DOM 比對 IDENTICAL — Radix 生態一致接受此
|
|
156
163
|
// tradeoff:APG keyboard focus-return 優先於 cosmetic ring。
|
|
157
|
-
className={cn(floatingLayerClass,
|
|
164
|
+
className={cn(floatingLayerClass, 'flex flex-col min-h-0', className)}
|
|
158
165
|
style={{
|
|
159
166
|
boxShadow: 'var(--elevation-200)',
|
|
160
167
|
minWidth: minWidth ?? 'max(180px, var(--radix-dropdown-menu-trigger-width))',
|
|
161
|
-
|
|
168
|
+
// 2026-07-18 viewport-adaptive max-h(對齊 HoverCard/Popover 既有 canonical):夾到「trigger 到
|
|
169
|
+
// 碰撞邊界(已內縮 collisionPadding=8px)的剩餘高度」→ 高選單不溢出視窗、離視窗邊 ≥8px、
|
|
170
|
+
// 短選單仍貼內容;consumer `maxHeight` 為**可選更低上限**(min 取小者)。inline style 非 class,
|
|
171
|
+
// 故動態 maxHeight 不觸 Tailwind 掃描陷阱。
|
|
172
|
+
maxHeight: maxHeight
|
|
173
|
+
? `min(var(--radix-dropdown-menu-content-available-height, 100vh), ${maxHeight}px)`
|
|
174
|
+
: 'var(--radix-dropdown-menu-content-available-height, 100vh)',
|
|
162
175
|
}}
|
|
163
176
|
{...props}
|
|
164
177
|
>
|
|
165
178
|
<RowSizeProvider value={size}>
|
|
166
|
-
{
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
<
|
|
170
|
-
|
|
171
|
-
</ScrollArea>
|
|
172
|
-
) : (
|
|
173
|
-
children
|
|
174
|
-
)}
|
|
179
|
+
{/* body 恆在 flex-1 ScrollArea 內:超過 clamped 高度即跨-OS 一致捲動(不吃寬度);
|
|
180
|
+
短選單 flex-1 貼內容不塌(同 HoverCard/Popover/DataTable panel 已驗)。py-2 在內層,整 padded 區可捲。 */}
|
|
181
|
+
<ScrollArea className="flex-1 min-h-0">
|
|
182
|
+
<div className="py-2">{children}</div>
|
|
183
|
+
</ScrollArea>
|
|
175
184
|
</RowSizeProvider>
|
|
176
185
|
</DropdownMenuPrimitive.Content>
|
|
177
186
|
</DropdownMenuPrimitive.Portal>
|
|
@@ -430,7 +439,11 @@ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
|
|
|
430
439
|
// Radix handles checked state;checked 底色套在外層 Radix RadioItem 本身(parent-bg
|
|
431
440
|
// pattern,詳下方 2026-05-31 #10 註解),內層 MenuItem 恆 !bg-transparent 讓它透出。
|
|
432
441
|
interface DropdownMenuRadioItemProps
|
|
433
|
-
|
|
442
|
+
// children Omit + redeclare required(2026-07-18 決策2 一致性):對齊 sibling Item/SubTrigger/
|
|
443
|
+
// CheckboxItem — menu item 必有 label,children 為 required 非 Radix optional。RadioItem 恆渲染
|
|
444
|
+
// 固定 <MenuItem>{children}</MenuItem>,children 是合法 label(非 lie),此為 required 化一致性修。
|
|
445
|
+
extends Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>, 'children'> {
|
|
446
|
+
children: React.ReactNode
|
|
434
447
|
/** Prefix icon(LucideIcon) */
|
|
435
448
|
startIcon?: LucideIcon
|
|
436
449
|
/** 次要說明文字 */
|
|
@@ -17,8 +17,14 @@ export type FieldControlLayout = 'inline' | 'block'
|
|
|
17
17
|
* - `'toolbar'`— Toolbar / Action bar inline Field(future,目前無 consumer)
|
|
18
18
|
* - `'table-cell'`— DataTable cell-as-input substrate(取代 variant='naked' cell-detection
|
|
19
19
|
* heuristic;canonical metrics 由 surface 推導,不再 hardcode in Field consumer)
|
|
20
|
+
* - `'inline-edit'`(2026-07-17)— InlineEdit view 委派 surface。**唯一語義 = 委派控件 view 態
|
|
21
|
+
* 左 px 統一 `--field-px`(不繼承 tagPadding / avatar inset / bare-span 0px)**,讓 InlineEdit
|
|
22
|
+
* 固定 `-mx-[--field-px]` 對齊盒精準抵銷 → 值/tag/avatar 左緣落 label 左緣(x=0)。edit 態**不套**
|
|
23
|
+
* 本 surface(edit 完全繼承原 field,含 tagPadding — Jira 式)。對齊 Atlassian inline-edit
|
|
24
|
+
* read-view「fixed negative margin + read=edit geometry by construction」。只 InlineEdit display
|
|
25
|
+
* box 注入;DataTable cell(table-cell)/ 純表單(form)的 tagPadding + bare-span 完全不受影響。
|
|
20
26
|
*/
|
|
21
|
-
type FieldSurface = 'form' | 'toolbar' | 'table-cell'
|
|
27
|
+
type FieldSurface = 'form' | 'toolbar' | 'table-cell' | 'inline-edit'
|
|
22
28
|
|
|
23
29
|
// ── Context ──
|
|
24
30
|
export interface FieldContextValue {
|
|
@@ -30,7 +36,7 @@ export interface FieldContextValue {
|
|
|
30
36
|
descriptionId: string
|
|
31
37
|
errorId: string
|
|
32
38
|
mode: FieldMode
|
|
33
|
-
/** 視覺外殼透傳(2026-05-05)。default = 含 border+bg;naked = cell-as-input(edit×naked 自畫 border-based state machine;
|
|
39
|
+
/** 視覺外殼透傳(2026-05-05)。default = 含 border+bg;naked = cell-as-input(edit×naked 自畫 border-based state machine;view×naked 用 transparent border 由 host cell 供邊框);`bare` 2026-07-09 退役;naked 2026-07-14 型別收窄至
|
|
34
40
|
* FieldVariantInternal(@internal)— 公開 `<Field variant>` 只收 default,故本欄位維持 FieldVariant。
|
|
35
41
|
* child Field control 自動繼承,per-control prop override 可覆寫。詳 field-types.ts。 */
|
|
36
42
|
variant: FieldVariant
|
|
@@ -175,13 +181,13 @@ export function useResolvedFieldDisabled(disabledProp?: boolean | null): boolean
|
|
|
175
181
|
}
|
|
176
182
|
|
|
177
183
|
/**
|
|
178
|
-
* Resolve Field control 的 **mode**(
|
|
184
|
+
* Resolve Field control 的 **mode**(view / readonly / disabled / edit)— 2026-06-08 SSOT,統一兩派散落:
|
|
179
185
|
* 舊 Input 派 `modeProp ?? fieldCtx?.mode ?? (...)` → `<Field disabled>` 時 ctx.mode 仍 'edit',漏 disabled chrome。
|
|
180
|
-
* 舊 picker 派 `disabled ? 'disabled' : mode`(mode 預設 'edit')→ 完全不讀 fieldCtx.mode,`<Field mode="
|
|
186
|
+
* 舊 picker 派 `disabled ? 'disabled' : mode`(mode 預設 'edit')→ 完全不讀 fieldCtx.mode,`<Field mode="view">` 失效。
|
|
181
187
|
* 統一優先序(world-class:MUI FormControl disabled 完整 cascade + 顯式 prop 永遠最優先):
|
|
182
|
-
* 1. 顯式 mode prop(caller / DataTable cell
|
|
188
|
+
* 1. 顯式 mode prop(caller / DataTable cell 傳 mode="view")→ **永遠最優先**,故表格等顯式場景 inert
|
|
183
189
|
* 2. 有效 disabled(prop 或 `<Field disabled>`)→ 'disabled'(完整 disabled chrome)
|
|
184
|
-
* 3. FieldContext.mode(`<Field mode="
|
|
190
|
+
* 3. FieldContext.mode(`<Field mode="view"/"readonly">`)→ 讓 mode cascade 真正生效
|
|
185
191
|
* 4. 本地 readOnly → 'readonly'
|
|
186
192
|
* 5. 'edit'
|
|
187
193
|
* cell:mode prop 必有 → step 1 命中、fieldCtx=null → 完全 inert(Δ=0)。`disabled` 傳已 resolve 的 boolean 或未預設 prop。
|
|
@@ -240,7 +246,7 @@ export function FieldSurfaceSizeProvider({
|
|
|
240
246
|
/**
|
|
241
247
|
* Table-cell 可編輯訊號(2026-07-08 user 拍板)— 獨立於 FieldSurfaceContext / FieldSurfaceSizeContext
|
|
242
248
|
* 的純 boolean context,由 host(DataTable cell registry)注入該 cell 是否可編輯,讓 useFieldEmptyDisplay
|
|
243
|
-
* 分流「可編輯 cell 空
|
|
249
|
+
* 分流「可編輯 cell 空 view → 空白」vs「不可編輯 cell 空 view → '-'」。
|
|
244
250
|
* value = boolean primitive(stable when unchanged),不破壞 cell memo identity(同 TableScrollContext /
|
|
245
251
|
* FieldSurfaceSizeContext L119-121 canonical);絕不污染 FieldContext(useFieldContext() 在 cell 內仍 null)。
|
|
246
252
|
*/
|
|
@@ -261,16 +267,16 @@ export function FieldSurfaceEditableProvider({
|
|
|
261
267
|
*
|
|
262
268
|
* | 情境 | 空值顯示 |
|
|
263
269
|
* |------------------------------------------------|----------|
|
|
264
|
-
* | table-cell **可編輯** 的
|
|
270
|
+
* | table-cell **可編輯** 的 view 靜止態 | **空白 `''`**(不佔位,affordance = hover outline)|
|
|
265
271
|
* | table-cell **不可編輯**(readonly cell) | **半形 `-`** |
|
|
266
|
-
* | standalone
|
|
272
|
+
* | standalone view / readonly / form / toolbar | **半形 `-`** |
|
|
267
273
|
*
|
|
268
274
|
* 收斂式:`surface==='table-cell' && isEditable ? '' : EMPTY_DISPLAY`。
|
|
269
275
|
* 可編輯 form / edit 輸入框走 native placeholder(不經此 hook)。boolean → unchecked / disabled →
|
|
270
276
|
* 同上文字 + text-fg-disabled(M24),各控件自理。
|
|
271
277
|
* 世界級對照:table-cell blank = MUI X / AG Grid / Ant core / Notion / Airtable grid 域共識;
|
|
272
278
|
* 非 table `-` = Ant ProTable `columnEmptyText`(見 field-wrapper.tsx EMPTY_DISPLAY 註)。
|
|
273
|
-
* SSOT 條文 → field-controls.spec.md「null / undefined 值」;全 Field family
|
|
279
|
+
* SSOT 條文 → field-controls.spec.md「null / undefined 值」;全 Field family view/readonly/disabled
|
|
274
280
|
* 空值渲染必經此 hook,禁直接引 EMPTY_DISPLAY 常數(genre 分流會漏)。
|
|
275
281
|
*/
|
|
276
282
|
export function useFieldEmptyDisplay(): string {
|
|
@@ -288,7 +294,7 @@ export function useFieldEmptyDisplay(): string {
|
|
|
288
294
|
* 提示」的裝飾語意;空值符號不是提示、是被檢視的值狀態)。
|
|
289
295
|
* disabled 態維持 `text-fg-disabled`(M24 disabled 顯著性 > foreground/muted,不可被蓋)。
|
|
290
296
|
*
|
|
291
|
-
* SSOT:全 Field family
|
|
297
|
+
* SSOT:全 Field family view/readonly/disabled 空值 span 消費此 helper,傳入已 resolve 的
|
|
292
298
|
* resolvedMode。純函式(非 hook)—— resolvedMode 已由 useResolvedFieldMode 解析(含控件自身
|
|
293
299
|
* disabled prop,context hook 讀不到);故以 resolvedMode 為入參,可條件呼叫、不受 Rules of Hooks 限制。
|
|
294
300
|
* 世界級對照:Ant read-only / Carbon read-only value = 正常前景色;placeholder 才 muted。
|