@qijenchen/design-system 0.1.0-beta.83 → 0.1.0-beta.85
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +8 -8
- package/README.md +3 -2
- package/dist/components/Alert/alert.js.map +1 -1
- package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -1
- package/dist/components/AppShell/app-shell.d.ts +1 -1
- package/dist/components/AppShell/app-shell.d.ts.map +1 -1
- package/dist/components/AppShell/app-shell.js +22 -2
- package/dist/components/AppShell/app-shell.js.map +1 -1
- package/dist/components/Avatar/avatar.d.ts.map +1 -1
- package/dist/components/Avatar/avatar.js +4 -4
- package/dist/components/Avatar/avatar.js.map +1 -1
- package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -1
- package/dist/components/Breadcrumb/breadcrumb.js +1 -1
- package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
- package/dist/components/Button/button.d.ts +2 -2
- package/dist/components/Button/button.d.ts.map +1 -1
- package/dist/components/Button/button.js +12 -3
- package/dist/components/Button/button.js.map +1 -1
- package/dist/components/Calendar/calendar.d.ts +13 -5
- package/dist/components/Calendar/calendar.d.ts.map +1 -1
- package/dist/components/Calendar/calendar.js +7 -1
- package/dist/components/Calendar/calendar.js.map +1 -1
- package/dist/components/Carousel/carousel.d.ts.map +1 -1
- package/dist/components/Carousel/carousel.js +8 -3
- package/dist/components/Carousel/carousel.js.map +1 -1
- package/dist/components/Chart/chart.d.ts.map +1 -1
- package/dist/components/Chart/chart.js +1 -0
- package/dist/components/Chart/chart.js.map +1 -1
- package/dist/components/Checkbox/checkbox.d.ts +1 -1
- package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox/checkbox.js +8 -4
- package/dist/components/Checkbox/checkbox.js.map +1 -1
- package/dist/components/Chip/chip.d.ts +1 -1
- package/dist/components/Chip/chip.d.ts.map +1 -1
- package/dist/components/Chip/chip.js.map +1 -1
- package/dist/components/Coachmark/coachmark.d.ts +10 -3
- package/dist/components/Coachmark/coachmark.d.ts.map +1 -1
- package/dist/components/Coachmark/coachmark.js.map +1 -1
- package/dist/components/Combobox/combobox.d.ts +5 -1
- package/dist/components/Combobox/combobox.d.ts.map +1 -1
- package/dist/components/Combobox/combobox.js +30 -13
- package/dist/components/Combobox/combobox.js.map +1 -1
- package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
- package/dist/components/DataTable/cell-registry.js +53 -62
- package/dist/components/DataTable/cell-registry.js.map +1 -1
- package/dist/components/DataTable/column-types.d.ts +10 -4
- 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 +1 -1
- package/dist/components/DataTable/data-table-column-visibility-panel.js +183 -0
- package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -0
- package/dist/components/DataTable/data-table-filter-group.d.ts +47 -0
- package/dist/components/DataTable/data-table-filter-group.d.ts.map +1 -0
- package/dist/components/DataTable/data-table-filter-group.js +154 -0
- package/dist/components/DataTable/data-table-filter-group.js.map +1 -0
- package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-filter-panel.js +285 -0
- package/dist/components/DataTable/data-table-filter-panel.js.map +1 -0
- package/dist/components/DataTable/data-table-filter-value-picker.d.ts +29 -0
- package/dist/components/DataTable/data-table-filter-value-picker.d.ts.map +1 -0
- package/dist/components/DataTable/data-table-filter-value-picker.js +187 -0
- package/dist/components/DataTable/data-table-filter-value-picker.js.map +1 -0
- package/dist/components/DataTable/data-table-interaction-layer.d.ts +11 -15
- package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-interaction-layer.js +1 -3
- package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
- package/dist/components/DataTable/data-table-sort-manager.js +140 -0
- package/dist/components/DataTable/data-table-sort-manager.js.map +1 -0
- package/dist/components/DataTable/data-table.d.ts +5 -6
- package/dist/components/DataTable/data-table.d.ts.map +1 -1
- package/dist/components/DataTable/data-table.js +36 -15
- package/dist/components/DataTable/data-table.js.map +1 -1
- package/dist/components/DataTable/filter-operators.js +140 -0
- package/dist/components/DataTable/filter-operators.js.map +1 -0
- package/dist/components/DataTable/filter-tree.js +312 -0
- package/dist/components/DataTable/filter-tree.js.map +1 -0
- package/dist/components/DataTable/index.d.ts +3 -0
- package/dist/components/DataTable/index.d.ts.map +1 -1
- package/dist/components/DataTable/index.js +12 -1
- package/dist/components/DataTable/index.js.map +1 -1
- package/dist/components/DataTable/lib/column-meta.js +25 -0
- package/dist/components/DataTable/lib/column-meta.js.map +1 -0
- package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
- package/dist/components/DateGrid/date-grid.js +3 -1
- package/dist/components/DateGrid/date-grid.js.map +1 -1
- package/dist/components/DatePicker/date-picker.d.ts +7 -1
- package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
- package/dist/components/DatePicker/date-picker.js +105 -74
- package/dist/components/DatePicker/date-picker.js.map +1 -1
- package/dist/components/Dialog/dialog.d.ts +20 -3
- package/dist/components/Dialog/dialog.d.ts.map +1 -1
- package/dist/components/Dialog/dialog.js +38 -20
- package/dist/components/Dialog/dialog.js.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.js +3 -1
- package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
- package/dist/components/Field/field-context.d.ts +45 -5
- package/dist/components/Field/field-context.d.ts.map +1 -1
- package/dist/components/Field/field-context.js +19 -0
- package/dist/components/Field/field-context.js.map +1 -1
- package/dist/components/Field/field-edit-keys.d.ts +21 -0
- package/dist/components/Field/field-edit-keys.d.ts.map +1 -0
- package/dist/components/Field/field-edit-keys.js +19 -0
- package/dist/components/Field/field-edit-keys.js.map +1 -0
- package/dist/components/Field/field-types.d.ts +20 -1
- 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 +3 -2
- package/dist/components/Field/field-wrapper.d.ts.map +1 -1
- package/dist/components/Field/field-wrapper.js +38 -39
- package/dist/components/Field/field-wrapper.js.map +1 -1
- package/dist/components/Field/field.d.ts +2 -1
- package/dist/components/Field/field.d.ts.map +1 -1
- package/dist/components/Field/field.js.map +1 -1
- package/dist/components/Field/index.d.ts +1 -0
- package/dist/components/Field/index.d.ts.map +1 -1
- package/dist/components/Field/index.js +2 -0
- package/dist/components/Field/index.js.map +1 -1
- package/dist/components/FieldControlGroup/field-control-group.d.ts +1 -1
- package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
- package/dist/components/FileItem/file-item.d.ts.map +1 -1
- package/dist/components/FileItem/file-item.js +1 -1
- package/dist/components/FileItem/file-item.js.map +1 -1
- package/dist/components/FileUpload/file-upload.d.ts +1 -1
- package/dist/components/FileUpload/file-upload.js.map +1 -1
- package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
- package/dist/components/FileViewer/file-viewer.js +7 -2
- package/dist/components/FileViewer/file-viewer.js.map +1 -1
- package/dist/components/FileViewer/image-renderer.d.ts.map +1 -1
- package/dist/components/FileViewer/image-renderer.js +22 -1
- package/dist/components/FileViewer/image-renderer.js.map +1 -1
- package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
- package/dist/components/HoverCard/hover-card.js +5 -3
- package/dist/components/HoverCard/hover-card.js.map +1 -1
- package/dist/components/InlineEdit/index.d.ts +2 -0
- package/dist/components/InlineEdit/index.d.ts.map +1 -0
- package/dist/components/InlineEdit/index.js +5 -0
- package/dist/components/InlineEdit/index.js.map +1 -0
- package/dist/components/InlineEdit/inline-edit.d.ts +59 -0
- package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -0
- package/dist/components/InlineEdit/inline-edit.js +164 -0
- package/dist/components/InlineEdit/inline-edit.js.map +1 -0
- package/dist/components/Input/input.d.ts +6 -11
- package/dist/components/Input/input.d.ts.map +1 -1
- package/dist/components/Input/input.js +43 -13
- package/dist/components/Input/input.js.map +1 -1
- package/dist/components/LinkInput/link-input.d.ts +2 -2
- package/dist/components/LinkInput/link-input.d.ts.map +1 -1
- package/dist/components/LinkInput/link-input.js +6 -5
- package/dist/components/LinkInput/link-input.js.map +1 -1
- package/dist/components/Menu/menu-item.d.ts +14 -2
- package/dist/components/Menu/menu-item.d.ts.map +1 -1
- package/dist/components/Menu/menu-item.js +25 -3
- package/dist/components/Menu/menu-item.js.map +1 -1
- package/dist/components/NumberInput/number-input.d.ts +3 -3
- package/dist/components/NumberInput/number-input.d.ts.map +1 -1
- package/dist/components/NumberInput/number-input.js +6 -5
- package/dist/components/NumberInput/number-input.js.map +1 -1
- package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
- package/dist/components/OverflowIndicator/overflow-indicator.js +2 -6
- package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
- package/dist/components/Pagination/pagination.js +1 -1
- package/dist/components/Pagination/pagination.js.map +1 -1
- package/dist/components/PeoplePicker/index.js +7 -1
- package/dist/components/PeoplePicker/index.js.map +1 -1
- package/dist/components/PeoplePicker/people-picker.d.ts +9 -2
- package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
- package/dist/components/PeoplePicker/people-picker.js +23 -10
- package/dist/components/PeoplePicker/people-picker.js.map +1 -1
- package/dist/components/PeoplePicker/person-display.d.ts +6 -3
- package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
- package/dist/components/PeoplePicker/person-display.js +19 -14
- package/dist/components/PeoplePicker/person-display.js.map +1 -1
- package/dist/components/Popover/popover.d.ts.map +1 -1
- package/dist/components/Popover/popover.js +3 -1
- package/dist/components/Popover/popover.js.map +1 -1
- package/dist/components/ProfileCard/profile-card.d.ts +2 -2
- package/dist/components/ProfileCard/profile-card.js +3 -3
- package/dist/components/ProfileCard/profile-card.js.map +1 -1
- package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
- package/dist/components/RadioGroup/radio-group.js +15 -9
- package/dist/components/RadioGroup/radio-group.js.map +1 -1
- package/dist/components/ScrollArea/scroll-area.d.ts +11 -1
- package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
- package/dist/components/ScrollArea/scroll-area.js +6 -3
- package/dist/components/ScrollArea/scroll-area.js.map +1 -1
- package/dist/components/Select/select.d.ts +46 -5
- package/dist/components/Select/select.d.ts.map +1 -1
- package/dist/components/Select/select.js +109 -28
- package/dist/components/Select/select.js.map +1 -1
- package/dist/components/SelectMenu/select-menu.d.ts +3 -1
- package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
- package/dist/components/SelectMenu/select-menu.js +8 -1
- package/dist/components/SelectMenu/select-menu.js.map +1 -1
- package/dist/components/SelectionControl/boolean-value.d.ts +11 -0
- package/dist/components/SelectionControl/boolean-value.d.ts.map +1 -0
- package/dist/components/SelectionControl/boolean-value.js +23 -0
- package/dist/components/SelectionControl/boolean-value.js.map +1 -0
- package/dist/components/SelectionControl/index.d.ts +1 -0
- package/dist/components/SelectionControl/index.d.ts.map +1 -1
- package/dist/components/SelectionControl/index.js +2 -0
- package/dist/components/SelectionControl/index.js.map +1 -1
- package/dist/components/Sheet/index.js +2 -1
- package/dist/components/Sheet/sheet.d.ts +7 -1
- package/dist/components/Sheet/sheet.d.ts.map +1 -1
- package/dist/components/Sheet/sheet.js +5 -2
- package/dist/components/Sheet/sheet.js.map +1 -1
- package/dist/components/Sidebar/sidebar.d.ts +9 -4
- package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
- package/dist/components/Sidebar/sidebar.js +8 -10
- 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.map +1 -1
- package/dist/components/Switch/switch.d.ts +6 -6
- package/dist/components/Switch/switch.d.ts.map +1 -1
- package/dist/components/Switch/switch.js +3 -2
- package/dist/components/Switch/switch.js.map +1 -1
- package/dist/components/Tabs/tabs.d.ts.map +1 -1
- package/dist/components/Tabs/tabs.js +15 -1
- package/dist/components/Tabs/tabs.js.map +1 -1
- package/dist/components/Textarea/textarea.d.ts +2 -2
- package/dist/components/Textarea/textarea.d.ts.map +1 -1
- package/dist/components/Textarea/textarea.js +50 -42
- package/dist/components/Textarea/textarea.js.map +1 -1
- package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
- package/dist/components/TimePicker/time-columns.js +42 -38
- package/dist/components/TimePicker/time-columns.js.map +1 -1
- package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
- package/dist/components/TimePicker/time-picker.js +8 -6
- 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 +7 -5
- package/dist/components/Tooltip/tooltip.js.map +1 -1
- package/dist/components/TreeView/tree-view.d.ts +56 -1
- package/dist/components/TreeView/tree-view.d.ts.map +1 -1
- package/dist/components/TreeView/tree-view.js +211 -12
- package/dist/components/TreeView/tree-view.js.map +1 -1
- package/dist/index.d.ts +115 -58
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +95 -108
- package/dist/index.js.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.d.ts +7 -6
- package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
- package/dist/tokens/categorical-color.js +15 -0
- package/dist/tokens/categorical-color.js.map +1 -1
- package/dist/tokens/motion/motion.d.ts +7 -6
- package/dist/tokens/motion/motion.d.ts.map +1 -1
- package/dist/tokens/motion/motion.js +6 -6
- package/dist/tokens/motion/motion.js.map +1 -1
- package/dist/tokens/motion/overlay-motion.d.ts +19 -0
- package/dist/tokens/motion/overlay-motion.d.ts.map +1 -0
- package/dist/tokens/motion/overlay-motion.js +9 -0
- package/dist/tokens/motion/overlay-motion.js.map +1 -0
- package/dist/tokens/uiSize/icon-size.js +5 -0
- package/dist/tokens/uiSize/icon-size.js.map +1 -0
- package/ds-canonical/fork/governance.lock +31 -19
- package/ds-canonical/fork/hooks/_log-fire.sh +46 -0
- package/ds-canonical/fork/hooks/block_prototype_imports.py +15 -4
- package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +145 -13
- package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +2 -1
- package/ds-canonical/fork/hooks/check_dynamic_tailwind_class.sh +47 -0
- package/ds-canonical/fork/hooks/check_escape_marker_abuse.sh +27 -0
- package/ds-canonical/fork/hooks/check_field_family_invariants.sh +61 -1
- package/ds-canonical/fork/hooks/check_layout_space_magic_numbers.sh +28 -4
- package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +28 -0
- package/ds-canonical/fork/hooks/check_story_determinism.sh +2 -0
- package/ds-canonical/fork/hooks/check_story_invariants.sh +119 -0
- package/ds-canonical/fork/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
- package/ds-canonical/fork/manifest.json +15 -0
- package/ds-canonical/fork/preamble.md +20 -18
- package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +3 -3
- package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +3 -3
- package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +1 -1
- package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +3 -3
- package/ds-canonical/fork/skills/propose-options/SKILL.md +3 -3
- package/ds-canonical/fork/skills/prototype/SKILL.md +1 -1
- package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +2 -2
- package/ds-canonical/fork/skills/visual-audit/SKILL.md +2 -2
- package/ds-canonical/hooks/README.md +1 -1
- package/ds-canonical/hooks/block_prototype_imports.py +15 -4
- package/ds-canonical/hooks/check_audit_post_report_validator.sh +65 -7
- package/ds-canonical/hooks/check_codex_brief_invariants.sh +28 -1
- package/ds-canonical/hooks/check_consumer_app_invariants.sh +145 -13
- package/ds-canonical/hooks/check_datatable_invariants.sh +6 -3
- package/ds-canonical/hooks/check_ds_anchor_preflight.sh +2 -1
- package/ds-canonical/hooks/check_dynamic_tailwind_class.sh +47 -0
- package/ds-canonical/hooks/check_escape_marker_abuse.sh +27 -0
- package/ds-canonical/hooks/check_field_family_invariants.sh +61 -1
- package/ds-canonical/hooks/check_layout_space_magic_numbers.sh +28 -4
- package/ds-canonical/hooks/check_naming_and_abstraction.sh +1 -1
- package/ds-canonical/hooks/check_opacity_token_usage.sh +28 -0
- package/ds-canonical/hooks/check_pixel_quantified_audit.sh +3 -2
- package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +6 -1
- package/ds-canonical/hooks/check_ssot_header_declaration.sh +3 -1
- package/ds-canonical/hooks/check_story_determinism.sh +2 -0
- package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +8 -7
- package/ds-canonical/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
- package/ds-canonical/hooks/lib/_story_compile_drift.sh +1 -1
- package/ds-canonical/hooks/lib/_token_hygiene.sh +10 -1
- package/ds-canonical/hooks/stop_self_audit.sh +31 -0
- package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +24 -0
- package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +44 -0
- package/ds-canonical/hooks/tests/test_check_codex_brief_invariants.sh +43 -2
- package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +112 -0
- package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +9 -2
- package/ds-canonical/hooks/tests/test_check_dynamic_tailwind_class.sh +76 -0
- package/ds-canonical/hooks/tests/test_check_escape_marker_abuse.sh +24 -0
- package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +27 -2
- package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +39 -0
- package/ds-canonical/hooks/tests/test_check_tabs_content_chrome_body_double_gap.sh +76 -0
- package/ds-canonical/references/audit-coverage-vs-24-checklist.md +1 -1
- package/ds-canonical/references/build-ui-canonicals.md +2 -1
- package/ds-canonical/references/failure-class-registry.json +145 -0
- package/ds-canonical/references/governance-audit-coverage.md +33 -0
- package/ds-canonical/references/item-anatomy-recipe.md +2 -2
- package/ds-canonical/references/scenario-definition.md +6 -9
- package/ds-canonical/references/ssot-consultation.md +2 -2
- package/ds-canonical/references/ssot-index.md +5 -4
- package/ds-canonical/references/story-baseline-registry.json +8 -2
- package/ds-canonical/references/structural-token-retention.md +6 -9
- package/ds-canonical/rules/meta-patterns.md +8 -8
- package/ds-canonical/rules/self-verify.md +4 -3
- package/ds-canonical/rules/story-rules.md +2 -2
- package/ds-canonical/rules/ui-development.md +2 -2
- package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +3 -3
- package/ds-canonical/skills/code-quality-audit/SKILL.md +3 -3
- package/ds-canonical/skills/codex-collab/SKILL.md +9 -7
- package/ds-canonical/skills/codex-collab/references/brief-template.md +1 -1
- package/ds-canonical/skills/codify-principle/SKILL.md +2 -2
- package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
- package/ds-canonical/skills/component-quality-gate/references/checklist.md +2 -2
- package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +51 -58
- package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +29 -0
- package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +29 -10
- package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +21 -0
- package/ds-canonical/skills/delivery-handoff/SKILL.md +1 -1
- package/ds-canonical/skills/design-system-audit/SKILL.md +26 -25
- package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +13 -1
- package/ds-canonical/skills/design-system-audit/references/rule-placement.md +1 -1
- package/ds-canonical/skills/governance-health/SKILL.md +1 -1
- package/ds-canonical/skills/knowledge-prune/SKILL.md +3 -0
- package/ds-canonical/skills/knowledge-prune/references/prune-dimensions-d5-d10.md +1 -0
- package/ds-canonical/skills/new-component/SKILL.md +5 -5
- package/ds-canonical/skills/new-component/references/new-component-checklist.md +1 -1
- package/ds-canonical/skills/product-ui-audit/SKILL.md +3 -3
- package/ds-canonical/skills/propose-options/SKILL.md +3 -3
- package/ds-canonical/skills/prototype/SKILL.md +1 -1
- package/ds-canonical/skills/scan-similar-bugs/SKILL.md +2 -2
- package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +3 -3
- package/ds-canonical/skills/story-writing/SKILL.md +3 -3
- package/ds-canonical/skills/visual-audit/SKILL.md +2 -2
- package/ds-story-manifest.json +29 -20
- package/llms-full.txt +22 -1
- package/llms.txt +5 -4
- package/package.json +7 -3
- package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
- package/src/components/Accordion/accordion.stories.tsx +16 -1
- package/src/components/Alert/alert.principles.stories.tsx +1 -1
- package/src/components/Alert/alert.spec.md +8 -10
- package/src/components/Alert/alert.stories.tsx +28 -28
- package/src/components/Alert/alert.tsx +1 -1
- package/src/components/AppShell/_demo-helpers.tsx +6 -3
- package/src/components/AppShell/app-shell.spec.md +4 -4
- package/src/components/AppShell/app-shell.tsx +28 -2
- package/src/components/AspectRatio/aspect-ratio.spec.md +1 -1
- package/src/components/AspectRatio/aspect-ratio.stories.tsx +7 -89
- package/src/components/Avatar/avatar.anatomy.stories.tsx +7 -3
- package/src/components/Avatar/avatar.principles.stories.tsx +19 -15
- package/src/components/Avatar/avatar.spec.md +2 -2
- package/src/components/Avatar/avatar.stories.tsx +8 -6
- package/src/components/Avatar/avatar.tsx +13 -5
- package/src/components/Badge/badge.principles.stories.tsx +1 -1
- package/src/components/Badge/badge.spec.md +2 -0
- package/src/components/Badge/badge.stories.tsx +4 -2
- package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +6 -4
- package/src/components/Breadcrumb/breadcrumb.stories.tsx +6 -5
- package/src/components/Breadcrumb/breadcrumb.tsx +3 -2
- package/src/components/BulkActionBar/bulk-action-bar.spec.md +4 -2
- package/src/components/Button/button.principles.stories.tsx +1 -1
- package/src/components/Button/button.spec.md +2 -2
- package/src/components/Button/button.tsx +18 -3
- package/src/components/Calendar/calendar.anatomy.stories.tsx +12 -10
- package/src/components/Calendar/calendar.principles.stories.tsx +14 -6
- package/src/components/Calendar/calendar.spec.md +5 -4
- package/src/components/Calendar/calendar.stories.tsx +7 -4
- package/src/components/Calendar/calendar.tsx +26 -7
- package/src/components/Carousel/carousel.anatomy.stories.tsx +5 -4
- package/src/components/Carousel/carousel.spec.md +2 -2
- package/src/components/Carousel/carousel.tsx +11 -3
- package/src/components/Chart/chart.anatomy.stories.tsx +7 -4
- package/src/components/Chart/chart.principles.stories.tsx +1 -1
- package/src/components/Chart/chart.stories.tsx +2 -8
- package/src/components/Chart/chart.tsx +3 -0
- package/src/components/Checkbox/checkbox.anatomy.stories.tsx +28 -49
- package/src/components/Checkbox/checkbox.principles.stories.tsx +1 -1
- package/src/components/Checkbox/checkbox.spec.md +13 -26
- package/src/components/Checkbox/checkbox.stories.tsx +11 -8
- package/src/components/Checkbox/checkbox.tsx +18 -13
- package/src/components/Chip/chip.anatomy.stories.tsx +44 -24
- package/src/components/Chip/chip.principles.stories.tsx +1 -1
- package/src/components/Chip/chip.spec.md +5 -4
- package/src/components/Chip/chip.tsx +5 -1
- package/src/components/CircularProgress/circular-progress.principles.stories.tsx +7 -4
- package/src/components/CircularProgress/circular-progress.spec.md +3 -3
- package/src/components/CircularProgress/circular-progress.stories.tsx +2 -2
- package/src/components/Coachmark/coachmark.anatomy.stories.tsx +2 -2
- package/src/components/Coachmark/coachmark.principles.stories.tsx +2 -1
- package/src/components/Coachmark/coachmark.spec.md +5 -5
- package/src/components/Coachmark/coachmark.stories.tsx +3 -1
- package/src/components/Coachmark/coachmark.tsx +10 -3
- package/src/components/Combobox/combobox.anatomy.stories.tsx +2 -2
- package/src/components/Combobox/combobox.tsx +53 -19
- package/src/components/Command/command.anatomy.stories.tsx +2 -2
- package/src/components/Command/command.principles.stories.tsx +1 -1
- package/src/components/Command/command.stories.tsx +42 -10
- package/src/components/DataTable/cell-registry.tsx +86 -63
- package/src/components/DataTable/column-types.ts +10 -1
- package/src/components/DataTable/data-table-column-visibility-panel.tsx +1 -1
- package/src/components/DataTable/data-table-filter-group.tsx +231 -0
- package/src/components/DataTable/data-table-filter-panel.tsx +16 -430
- package/src/components/DataTable/data-table-filter-value-picker.tsx +237 -0
- package/src/components/DataTable/data-table-interaction-layer.tsx +15 -19
- package/src/components/DataTable/data-table.anatomy.stories.tsx +15 -13
- package/src/components/DataTable/data-table.principles.stories.tsx +9 -9
- package/src/components/DataTable/data-table.spec.md +33 -13
- package/src/components/DataTable/data-table.stories.tsx +16 -17
- package/src/components/DataTable/data-table.tsx +107 -61
- package/src/components/DataTable/filter-operators.spec.md +3 -3
- package/src/components/DataTable/index.ts +3 -0
- package/src/components/DateGrid/date-grid.anatomy.stories.tsx +4 -4
- package/src/components/DateGrid/date-grid.principles.stories.tsx +1 -1
- package/src/components/DateGrid/date-grid.spec.md +1 -1
- package/src/components/DateGrid/date-grid.tsx +3 -1
- package/src/components/DatePicker/date-picker.anatomy.stories.tsx +8 -8
- package/src/components/DatePicker/date-picker.principles.stories.tsx +3 -3
- package/src/components/DatePicker/date-picker.spec.md +3 -3
- package/src/components/DatePicker/date-picker.stories.tsx +4 -5
- package/src/components/DatePicker/date-picker.tsx +99 -45
- package/src/components/DescriptionList/description-list.anatomy.stories.tsx +12 -10
- package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
- package/src/components/DescriptionList/description-list.spec.md +3 -3
- package/src/components/DescriptionList/description-list.stories.tsx +7 -6
- package/src/components/Dialog/dialog.anatomy.stories.tsx +1 -0
- package/src/components/Dialog/dialog.spec.md +9 -0
- package/src/components/Dialog/dialog.stories.tsx +66 -5
- package/src/components/Dialog/dialog.tsx +60 -25
- package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +1 -1
- package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +8 -6
- package/src/components/DropdownMenu/dropdown-menu.spec.md +5 -5
- package/src/components/DropdownMenu/dropdown-menu.tsx +18 -9
- package/src/components/Empty/empty.anatomy.stories.tsx +1 -1
- package/src/components/Empty/empty.spec.md +2 -2
- package/src/components/Field/field-context.ts +69 -5
- package/src/components/Field/field-controls.spec.md +62 -8
- package/src/components/Field/field-edit-keys.ts +66 -0
- package/src/components/Field/field-types.ts +58 -9
- package/src/components/Field/field-wrapper.tsx +50 -42
- package/src/components/Field/field.anatomy.stories.tsx +9 -6
- package/src/components/Field/field.spec.md +1 -1
- package/src/components/Field/field.stories.tsx +1 -1
- package/src/components/Field/field.tsx +2 -1
- package/src/components/Field/form-validation.spec.md +3 -3
- package/src/components/Field/index.ts +1 -0
- package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +6 -6
- package/src/components/FieldControlGroup/field-control-group.spec.md +9 -4
- package/src/components/FieldControlGroup/field-control-group.tsx +1 -1
- package/src/components/FileItem/file-item.anatomy.stories.tsx +1 -1
- package/src/components/FileItem/file-item.spec.md +5 -8
- package/src/components/FileItem/file-item.stories.tsx +36 -25
- package/src/components/FileItem/file-item.tsx +8 -6
- package/src/components/FileUpload/file-upload.anatomy.stories.tsx +6 -6
- package/src/components/FileUpload/file-upload.principles.stories.tsx +5 -5
- package/src/components/FileUpload/file-upload.spec.md +1 -1
- package/src/components/FileUpload/file-upload.tsx +1 -1
- package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +4 -3
- package/src/components/FileViewer/file-viewer.principles.stories.tsx +3 -3
- package/src/components/FileViewer/file-viewer.spec.md +30 -12
- package/src/components/FileViewer/file-viewer.stories.tsx +1 -2
- package/src/components/FileViewer/file-viewer.tsx +12 -4
- package/src/components/FileViewer/image-renderer.tsx +35 -7
- package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -2
- package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -3
- package/src/components/HoverCard/hover-card.spec.md +5 -5
- package/src/components/HoverCard/hover-card.stories.tsx +16 -16
- package/src/components/HoverCard/hover-card.tsx +5 -3
- package/src/components/InlineEdit/index.ts +5 -0
- package/src/components/InlineEdit/inline-edit.spec.md +149 -0
- package/src/components/InlineEdit/inline-edit.stories.tsx +246 -0
- package/src/components/InlineEdit/inline-edit.tsx +287 -0
- package/src/components/Input/input.anatomy.stories.tsx +8 -7
- package/src/components/Input/input.principles.stories.tsx +2 -12
- package/src/components/Input/input.spec.md +13 -18
- package/src/components/Input/input.tsx +69 -22
- package/src/components/LinkInput/link-input.anatomy.stories.tsx +1 -1
- package/src/components/LinkInput/link-input.principles.stories.tsx +2 -2
- package/src/components/LinkInput/link-input.tsx +11 -10
- package/src/components/Menu/menu-item.anatomy.stories.tsx +3 -3
- package/src/components/Menu/menu-item.principles.stories.tsx +1 -1
- package/src/components/Menu/menu-item.spec.md +22 -15
- package/src/components/Menu/menu-item.stories.tsx +39 -11
- package/src/components/Menu/menu-item.tsx +38 -4
- package/src/components/Notice/notice.principles.stories.tsx +1 -1
- package/src/components/Notice/notice.spec.md +16 -3
- package/src/components/NumberInput/number-input.anatomy.stories.tsx +3 -3
- package/src/components/NumberInput/number-input.principles.stories.tsx +1 -1
- package/src/components/NumberInput/number-input.spec.md +4 -4
- package/src/components/NumberInput/number-input.tsx +19 -12
- package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +10 -8
- package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +3 -3
- package/src/components/OverflowIndicator/overflow-indicator.spec.md +4 -2
- package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +71 -63
- package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -8
- package/src/components/Pagination/pagination.spec.md +1 -1
- package/src/components/Pagination/pagination.stories.tsx +2 -6
- package/src/components/Pagination/pagination.tsx +1 -1
- package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +4 -4
- package/src/components/PeoplePicker/people-picker.principles.stories.tsx +2 -2
- package/src/components/PeoplePicker/people-picker.spec.md +6 -6
- package/src/components/PeoplePicker/people-picker.tsx +56 -16
- package/src/components/PeoplePicker/person-display.tsx +32 -16
- package/src/components/Popover/popover.anatomy.stories.tsx +2 -2
- package/src/components/Popover/popover.tsx +3 -1
- package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +12 -23
- package/src/components/ProfileCard/profile-card.spec.md +3 -3
- package/src/components/ProfileCard/profile-card.tsx +6 -6
- package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +3 -1
- package/src/components/ProgressBar/progress-bar.principles.stories.tsx +1 -1
- package/src/components/ProgressBar/progress-bar.stories.tsx +50 -42
- package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +10 -28
- package/src/components/RadioGroup/radio-group.stories.tsx +29 -32
- package/src/components/RadioGroup/radio-group.tsx +41 -15
- package/src/components/Rating/rating.spec.md +11 -3
- package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
- package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
- package/src/components/ScrollArea/scroll-area.spec.md +7 -3
- package/src/components/ScrollArea/scroll-area.stories.tsx +1 -1
- package/src/components/ScrollArea/scroll-area.tsx +17 -4
- package/src/components/Select/select.anatomy.stories.tsx +3 -3
- package/src/components/Select/select.spec.md +29 -17
- package/src/components/Select/select.stories.tsx +33 -0
- package/src/components/Select/select.tsx +190 -36
- package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +4 -4
- package/src/components/SelectMenu/select-menu.spec.md +15 -7
- package/src/components/SelectMenu/select-menu.tsx +16 -3
- package/src/components/SelectionControl/boolean-value.tsx +39 -0
- package/src/components/SelectionControl/index.ts +1 -0
- package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +2 -2
- package/src/components/SelectionControl/selection-item.principles.stories.tsx +2 -2
- package/src/components/SelectionControl/selection-item.spec.md +3 -3
- package/src/components/SelectionControl/selection-item.stories.tsx +3 -3
- package/src/components/Separator/separator.spec.md +2 -2
- package/src/components/Separator/separator.stories.tsx +6 -27
- package/src/components/Sheet/sheet.anatomy.stories.tsx +1 -1
- package/src/components/Sheet/sheet.principles.stories.tsx +1 -1
- package/src/components/Sheet/sheet.spec.md +2 -2
- package/src/components/Sheet/sheet.tsx +9 -5
- package/src/components/Sidebar/sidebar.anatomy.stories.tsx +16 -12
- package/src/components/Sidebar/sidebar.principles.stories.tsx +10 -8
- package/src/components/Sidebar/sidebar.spec.md +13 -15
- package/src/components/Sidebar/sidebar.stories.tsx +8 -7
- package/src/components/Sidebar/sidebar.tsx +37 -25
- package/src/components/Skeleton/skeleton.stories.tsx +4 -11
- package/src/components/Slider/slider.anatomy.stories.tsx +3 -3
- package/src/components/Slider/slider.principles.stories.tsx +2 -2
- package/src/components/Slider/slider.spec.md +5 -5
- package/src/components/Slider/slider.tsx +3 -1
- package/src/components/Steps/steps.anatomy.stories.tsx +4 -4
- package/src/components/Steps/steps.principles.stories.tsx +1 -1
- package/src/components/Steps/steps.spec.md +1 -1
- package/src/components/Switch/switch.anatomy.stories.tsx +7 -7
- package/src/components/Switch/switch.principles.stories.tsx +4 -4
- package/src/components/Switch/switch.spec.md +8 -8
- package/src/components/Switch/switch.stories.tsx +9 -24
- package/src/components/Switch/switch.tsx +17 -13
- package/src/components/Tabs/tabs.anatomy.stories.tsx +10 -7
- package/src/components/Tabs/tabs.spec.md +1 -1
- package/src/components/Tabs/tabs.tsx +21 -1
- package/src/components/Textarea/textarea.anatomy.stories.tsx +1 -1
- package/src/components/Textarea/textarea.principles.stories.tsx +1 -1
- package/src/components/Textarea/textarea.spec.md +4 -4
- package/src/components/Textarea/textarea.tsx +72 -46
- package/src/components/TimePicker/time-columns.tsx +6 -2
- package/src/components/TimePicker/time-picker.principles.stories.tsx +1 -1
- package/src/components/TimePicker/time-picker.spec.md +3 -3
- package/src/components/TimePicker/time-picker.tsx +16 -10
- package/src/components/Toast/toast.stories.tsx +7 -4
- package/src/components/Tooltip/tooltip.anatomy.stories.tsx +4 -4
- package/src/components/Tooltip/tooltip.principles.stories.tsx +3 -3
- package/src/components/Tooltip/tooltip.spec.md +1 -1
- package/src/components/Tooltip/tooltip.stories.tsx +4 -39
- package/src/components/Tooltip/tooltip.tsx +8 -6
- package/src/components/TreeView/tree-view.anatomy.stories.tsx +6 -3
- package/src/components/TreeView/tree-view.spec.md +42 -11
- package/src/components/TreeView/tree-view.stories.tsx +1 -0
- package/src/components/TreeView/tree-view.tsx +322 -17
- package/src/index.ts +588 -60
- package/src/patterns/action-bar/action-bar.spec.md +9 -0
- package/src/patterns/action-bar/action-bar.stories.tsx +6 -3
- package/src/patterns/element-anatomy/inline-action.spec.md +2 -0
- package/src/patterns/element-anatomy/item-anatomy.spec.md +14 -5
- package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -4
- package/src/patterns/element-anatomy/item-anatomy.tsx +7 -6
- package/src/patterns/header-canonical/header-canonical.spec.md +5 -4
- package/src/patterns/overlay-surface/overlay-surface.spec.md +22 -1
- package/src/styles/tokens.css +3 -0
- package/src/tokens/README.md +1 -1
- package/src/tokens/color/color.spec.md +4 -4
- package/src/tokens/color/color.stories.tsx +3 -3
- package/src/tokens/density/density.stories.tsx +16 -3
- package/src/tokens/layoutSpace/layoutSpace.spec.md +3 -1
- package/src/tokens/motion/motion.css +33 -21
- package/src/tokens/motion/motion.spec.md +32 -15
- package/src/tokens/motion/motion.stories.tsx +58 -5
- package/src/tokens/motion/motion.ts +7 -6
- package/src/tokens/motion/overlay-motion.ts +26 -0
- package/src/tokens/orphan-tokens.spec.md +4 -4
- package/src/tokens/token-system.spec.md +1 -0
- package/src/tokens/uiSize/uiSize.css +1 -1
- package/src/tokens/uiSize/uiSize.spec.md +1 -1
- package/src/tokens/uiSize/uiSize.stories.tsx +4 -2
- package/src/tokens/utility-registry.json +160 -23
|
@@ -211,7 +211,7 @@ export const Overview = {
|
|
|
211
211
|
<span className="rounded px-2 py-1 text-[11px] font-mono border border-dashed"
|
|
212
212
|
style={{ borderColor: 'var(--success)', backgroundColor: 'var(--success-subtle)', color: 'var(--success)' }}>formatted text (flex-1)</span>
|
|
213
213
|
</div>
|
|
214
|
-
<span className="text-[10px] text-fg-muted font-mono">Intl.DateTimeFormat · null 顯示
|
|
214
|
+
<span className="text-[10px] text-fg-muted font-mono">Intl.DateTimeFormat · null 顯示 - (hyphen)</span>
|
|
215
215
|
</div>
|
|
216
216
|
</div>
|
|
217
217
|
</div>
|
|
@@ -416,8 +416,8 @@ const InspectorInner = () => {
|
|
|
416
416
|
)}
|
|
417
417
|
{!isEdit && mode === 'readonly' && !value && (
|
|
418
418
|
<PropRow label="Empty">
|
|
419
|
-
<TokenValue value="--
|
|
420
|
-
<span className="text-[10px] text-fg-muted ml-1">
|
|
419
|
+
<TokenValue value="--foreground" />
|
|
420
|
+
<span className="text-[10px] text-fg-muted ml-1">hyphen -</span>
|
|
421
421
|
</PropRow>
|
|
422
422
|
)}
|
|
423
423
|
</div>
|
|
@@ -750,7 +750,7 @@ export const StateBehavior = {
|
|
|
750
750
|
|
|
751
751
|
{/* Empty value display */}
|
|
752
752
|
<div className="flex flex-col gap-4">
|
|
753
|
-
<span className="text-caption font-medium text-fg-secondary">空值 —
|
|
753
|
+
<span className="text-caption font-medium text-fg-secondary">空值 — 統一半形 hyphen(-)+ foreground</span>
|
|
754
754
|
<div className="flex flex-col gap-3">
|
|
755
755
|
<div className="flex items-center gap-3">
|
|
756
756
|
<span className="text-[11px] text-fg-muted w-20 shrink-0">readonly</span>
|
|
@@ -939,11 +939,11 @@ export const Accessibility = {
|
|
|
939
939
|
</ul>
|
|
940
940
|
</section>
|
|
941
941
|
<section>
|
|
942
|
-
<h3 className="text-body font-bold mb-2"
|
|
942
|
+
<h3 className="text-body font-bold mb-2">鍵盤</h3>
|
|
943
943
|
<ul className="list-disc list-inside text-caption text-fg-secondary space-y-1">
|
|
944
|
-
<li>Trigger
|
|
945
|
-
<li>Popover
|
|
946
|
-
<li>DateGrid:<kbd>←</kbd> <kbd>→</kbd> 切日 / <kbd>PgUp</kbd> <kbd>PgDn</kbd> 切月 / <kbd>Home</kbd> <kbd>End</kbd> 行首尾</li>
|
|
944
|
+
<li>Trigger 開 popover(<kbd>Space</kbd> / <kbd>Enter</kbd>):單一 DatePicker 的 <code>{`<div role="combobox">`}</code> 無 native Enter/Space→click,由元件<strong>自建 <code>onKeyDown</code></strong> 補開(date-picker.tsx:554;Radix PopoverTrigger 只 compose onClick)。Range 雙 trigger 為 native <code>{`<button>`}</code> onClick 開啟(同非 Radix Popover 內建)</li>
|
|
945
|
+
<li>Popover 開啟 <kbd>Esc</kbd> 關閉 + 回焦:單一 DatePicker 用 PopoverTrigger → Radix <strong>內建</strong> <code>triggerRef.focus()</code> 回焦;Range 只有 PopoverAnchor(triggerRef 恆 null,內建回焦為 no-op),改由元件<strong>自建 <code>onCloseAutoFocus</code></strong> 手動回焦 active 端 button(date-picker.tsx:1020-1026,守 WCAG 2.4.3)</li>
|
|
946
|
+
<li>DateGrid(react-day-picker v9 內建):<kbd>←</kbd> <kbd>→</kbd> 切日 / <kbd>PgUp</kbd> <kbd>PgDn</kbd> 切月 / <kbd>Home</kbd> <kbd>End</kbd> 行首尾</li>
|
|
947
947
|
<li>showTime:<kbd>Tab</kbd> 從 calendar 跳到右側 time panel,各 column <kbd>↑</kbd> <kbd>↓</kbd> 切 option</li>
|
|
948
948
|
</ul>
|
|
949
949
|
</section>
|
|
@@ -67,7 +67,7 @@ export const UsageGuidance: Story = {
|
|
|
67
67
|
|
|
68
68
|
<Rule
|
|
69
69
|
title="❌ 不用其他 calendar library 平行實作"
|
|
70
|
-
note="
|
|
70
|
+
note="Date Range / DateTime 已內建(DatePicker.Range / showTime,見下方近親規則)且都基於本 DateGrid(`../DateGrid/date-grid.tsx`);未來任何日曆類擴充也走 DateGrid,而非引入第二個 library——避免兩套視覺語言在同一系統並存"
|
|
71
71
|
>
|
|
72
72
|
<Label>實作細節見 Design System / Components / DatePicker / 設計規格</Label>
|
|
73
73
|
</Rule>
|
|
@@ -169,8 +169,8 @@ export const FormattingRule: Story = {
|
|
|
169
169
|
</Rule>
|
|
170
170
|
|
|
171
171
|
<Rule
|
|
172
|
-
title="null
|
|
173
|
-
note="Display 模式 null / undefined
|
|
172
|
+
title="null 值統一顯示半形連字號"
|
|
173
|
+
note="Display 模式 null / undefined 顯示半形 -(foreground,同 readonly value 色),與其他 Field 元件一致"
|
|
174
174
|
>
|
|
175
175
|
<DatePicker mode="readonly" value={null} />
|
|
176
176
|
</Rule>
|
|
@@ -267,7 +267,7 @@ DateGrid cell 有 5 種語意視覺,每種用不同形狀/色彩語言避免混
|
|
|
267
267
|
`clearable` prop 在有值時顯示 clear 按鈕(endAction)。
|
|
268
268
|
|
|
269
269
|
- 只在 edit 模式顯示
|
|
270
|
-
- 清除後 value 變為 `null`(Display
|
|
270
|
+
- 清除後 value 變為 `null`(Display 顯示半形 -,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
|
---
|
|
@@ -295,7 +295,7 @@ DatePicker 套 `React.forwardRef` + `displayName`;`DatePickerProps` extends `Omi
|
|
|
295
295
|
- Trigger:`role="combobox"` + `aria-haspopup="dialog"` + `aria-expanded={open}` + 必含 accessible name(`aria-label` / 或外層 `<label>` / 或 fieldCtx label)
|
|
296
296
|
- Popover content:`role="dialog"`;單一日期 popover 不重覆 `aria-label`(由 trigger 的 `role="combobox"` accessible name 標示),Range popover 加 `aria-label="日期區間選擇"`
|
|
297
297
|
- DateGrid 鍵盤:Arrow keys 切日 / PageUp/Down 切月 / Home/End 行首尾(react-day-picker v9 內建)
|
|
298
|
-
- Trigger
|
|
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
|
|
300
300
|
|
|
301
301
|
---
|
|
@@ -317,7 +317,7 @@ DatePicker 套 `React.forwardRef` + `displayName`;`DatePickerProps` extends `Omi
|
|
|
317
317
|
- **Invalid date input**:Field validation 處理 `aria-invalid="true"` + error border + 下方 error message;DatePicker 本身不 own validation 規則。
|
|
318
318
|
- **極長格式化日期**:trigger 文字單行 `truncate`(ellipsis),不換行不撐高(Display / Edit / typeable / Range 雙 input 皆同)。
|
|
319
319
|
- **RTL**:未實作方向鏡像(trigger / Range 雙 input / DateGrid 皆以 LTR physical 方向設計);RTL 屬 DS-wide 決策,未定(與 Chip / Breadcrumb 同口徑)。
|
|
320
|
-
- **Dark mode / density**:走 Field + Popover SSOT 自動 adapt;DateGrid 內 cell
|
|
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
|
|
|
322
322
|
---
|
|
323
323
|
|
|
@@ -136,7 +136,7 @@ export const RangePicker: Story = {
|
|
|
136
136
|
return (
|
|
137
137
|
<div className="flex flex-col gap-4 max-w-md">
|
|
138
138
|
<p className="text-caption text-fg-muted">
|
|
139
|
-
|
|
139
|
+
兩個輸入框加中間箭頭:點開始欄開月曆選起日,選完自動跳到結束欄選迄日;有值時右側出現清除鈕。
|
|
140
140
|
</p>
|
|
141
141
|
<DatePicker.Range value={range} onChange={setRange} clearable />
|
|
142
142
|
<p className="text-caption text-fg-muted">
|
|
@@ -160,7 +160,7 @@ export const WithError: Story = {
|
|
|
160
160
|
render: () => (
|
|
161
161
|
<div className="flex flex-col gap-4 max-w-xs">
|
|
162
162
|
<p className="text-caption text-fg-muted">
|
|
163
|
-
|
|
163
|
+
驗證失敗時外框轉紅色,滑過或聚焦時同步用較深的紅。
|
|
164
164
|
</p>
|
|
165
165
|
<DatePicker error value="2026-04-02" onChange={() => {}} />
|
|
166
166
|
<DatePicker error value={null} onChange={() => {}} placeholder="必填日期" />
|
|
@@ -226,7 +226,7 @@ export const ShowTimePopoverOpen: Story = {
|
|
|
226
226
|
/* ── OpenSnapshot:needConfirm date-only(2026-07-05 D4 修 footer gate 死路)── */
|
|
227
227
|
export const NeedConfirmDateOnlyOpen: Story = {
|
|
228
228
|
name: 'needConfirm:合約生效日確認',
|
|
229
|
-
parameters: { docs: { description: { story: '
|
|
229
|
+
parameters: { docs: { description: { story: '需確認模式:選日期只會先暫存(輸入框即時顯示),要按下方「確定」才真正套用。適用選錯成本高的日期,例如合約生效日、帳單結算起算日。' } } },
|
|
230
230
|
render: () => {
|
|
231
231
|
const [effectiveDate, setEffectiveDate] = React.useState('2026-08-01')
|
|
232
232
|
return (
|
|
@@ -297,8 +297,7 @@ export const ShowTimeRange: Story = {
|
|
|
297
297
|
return (
|
|
298
298
|
<div className="flex flex-col gap-4 max-w-lg">
|
|
299
299
|
<p className="text-caption text-fg-muted">
|
|
300
|
-
|
|
301
|
-
兩端都填好 + 按確定才 commit(needConfirm=true 預設)。
|
|
300
|
+
範圍 + 時間:點開始欄選起始日期與時間,點結束欄選結束的日期與時間;兩端都選好、按下方「確定」才會套用。
|
|
302
301
|
</p>
|
|
303
302
|
<DatePicker.Range
|
|
304
303
|
showTime
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
import * as React from 'react'
|
|
4
4
|
import { X, Calendar as CalendarIcon, ArrowRight } from 'lucide-react'
|
|
5
5
|
import { cn } from '@/lib/utils'
|
|
6
|
-
import type { FieldMode, FieldVariant } from '@/design-system/components/Field/field-types'
|
|
7
|
-
import { fieldWrapperStyles, bareInputStyles,
|
|
6
|
+
import type { FieldMode, FieldVariant, FieldVariantInternal, FieldWidth } from '@/design-system/components/Field/field-types'
|
|
7
|
+
import { fieldWrapperStyles, bareInputStyles, nakedCellRowModeAlign, fieldDisplayTextClass } from '@/design-system/components/Field/field-wrapper'
|
|
8
8
|
import { ItemInlineAction, ItemSuffix } from '@/design-system/patterns/element-anatomy/item-anatomy'
|
|
9
9
|
import { Popover, PopoverTrigger, PopoverAnchor, PopoverContent } from '@/design-system/components/Popover/popover'
|
|
10
10
|
import { DateGrid } from '@/design-system/components/DateGrid/date-grid'
|
|
11
11
|
import { Button } from '@/design-system/components/Button/button'
|
|
12
12
|
import { SurfaceFooter } from '@/design-system/patterns/overlay-surface/overlay-surface'
|
|
13
|
-
import { useFieldContext, useResolvedFieldSize, useResolvedFieldDisabled, useResolvedFieldMode, useResolvedFieldVariant, useResolvedFieldInvalid } from '@/design-system/components/Field/field-context'
|
|
13
|
+
import { useFieldContext, useResolvedFieldSize, useResolvedFieldDisabled, useResolvedFieldMode, useResolvedFieldVariant, useResolvedFieldInvalid, useFieldEmptyDisplay, fieldEmptyColorClass } from '@/design-system/components/Field/field-context'
|
|
14
14
|
import {
|
|
15
15
|
TimeColumns,
|
|
16
16
|
isoToTimeParts,
|
|
@@ -53,7 +53,15 @@ function formatDate(
|
|
|
53
53
|
value: string | number | Date,
|
|
54
54
|
options: DateFormatOptions = {},
|
|
55
55
|
): string {
|
|
56
|
-
|
|
56
|
+
// TZ-safe:date-only / datetime ISO string 走 isoToDate(local-time 語意,new Date(y,m-1,d))
|
|
57
|
+
// 而非 new Date('YYYY-MM-DD')(ECMAScript 以 UTC 解析 → 負時區 off-by-one,如 LA 顯前一天)。
|
|
58
|
+
// 非 ISO string(RFC 'Mar 12 2025' 等)fallback new Date();number timestamp 直接 new Date()。
|
|
59
|
+
const date =
|
|
60
|
+
value instanceof Date
|
|
61
|
+
? value
|
|
62
|
+
: typeof value === 'string'
|
|
63
|
+
? (isoToDate(value) ?? new Date(value))
|
|
64
|
+
: new Date(value)
|
|
57
65
|
if (Number.isNaN(date.getTime())) return String(value)
|
|
58
66
|
// 若 consumer 顯式傳 formatOptions / locale → 走 Intl.DateTimeFormat
|
|
59
67
|
if (options.formatOptions || options.locale) {
|
|
@@ -103,11 +111,11 @@ function isoToDate(iso: string | null | undefined): Date | undefined {
|
|
|
103
111
|
* 或 ISO datetime(YYYY-MM-DDTHH:MM[:SS])。
|
|
104
112
|
*
|
|
105
113
|
* 支援 format(per Material X DatePicker / Ant DatePicker typed input idiom):
|
|
106
|
-
* - `YYYY-MM-DD` / `YYYY/MM/DD` / `YYYY.MM.DD`(ISO + 慣例 separator)
|
|
107
|
-
* - `MM/DD/YYYY` / `MM-DD-YYYY`(US locale)
|
|
108
|
-
* - `DD/MM/YYYY` / `DD-MM-YYYY`(EU locale)
|
|
114
|
+
* - `YYYY-MM-DD` / `YYYY/MM/DD` / `YYYY.MM.DD`(ISO + 慣例 separator,明確 parse branch)
|
|
109
115
|
* - `YYYY-MM-DD HH:MM[:SS]` / `YYYY-MM-DDTHH:MM[:SS]`(datetime,showTime 才接)
|
|
110
|
-
* - native `Date.parse()` fallback(handle 'Mar 12 2025' 等英文 RFC)
|
|
116
|
+
* - native `Date.parse()` fallback(handle 'Mar 12 2025' 等英文 RFC;US `MM/DD/YYYY` 亦由此判讀,ambiguous)
|
|
117
|
+
* ⚠️ 不支援 EU `DD/MM/YYYY`:無專屬 parser branch;native Date.parse 把 slash 日期當 US MM/DD,
|
|
118
|
+
* `31/12/2026`(月 > 12)直接 Invalid。v1 known-gap,需 EU 請走 formatOptions/locale 或另加 parser branch。
|
|
111
119
|
*
|
|
112
120
|
* Return:`{ iso, valid }`。Invalid → `valid=false` + `iso=null`,UI 顯 aria-invalid。
|
|
113
121
|
* Partial input(打到一半)→ valid=false 但不顯 error UI(consumer 用 onBlur / Enter 才檢驗)。
|
|
@@ -123,6 +131,9 @@ function parseDateInput(input: string, opts: { allowTime: boolean }): { iso: str
|
|
|
123
131
|
const [, y, m, d, hh, mm, ss] = isoDateMatch
|
|
124
132
|
const date = new Date(Number(y), Number(m) - 1, Number(d), Number(hh ?? 0), Number(mm ?? 0), Number(ss ?? 0))
|
|
125
133
|
if (isNaN(date.getTime()) || date.getMonth() !== Number(m) - 1) return { iso: null, valid: false }
|
|
134
|
+
// time 分量越界校驗:JS Date 會 silently normalize(25:99:99 → 隔日某時,getTime 仍 valid、
|
|
135
|
+
// getMonth 未必變),但回傳 iso 用的是原始越界字串 → 需在此擋掉 hh>23 / mm>59 / ss>59。
|
|
136
|
+
if (hh != null && (Number(hh) > 23 || Number(mm) > 59 || Number(ss ?? 0) > 59)) return { iso: null, valid: false }
|
|
126
137
|
const datePart = dateToIso(date)
|
|
127
138
|
if (hh != null && opts.allowTime) {
|
|
128
139
|
const h2 = String(Number(hh)).padStart(2, '0')
|
|
@@ -290,6 +301,9 @@ export interface DatePickerProps
|
|
|
290
301
|
mode?: FieldMode
|
|
291
302
|
/** Field chrome variant. Default = context.variant ?? 'default'. Per-prop override. */
|
|
292
303
|
variant?: FieldVariant
|
|
304
|
+
/** 寬度軸 — `fill` 填滿容器(default)/ `hug` 依內容收縮(value 寬 + slot 寬 + gap + 內 padding);
|
|
305
|
+
* chrome 與互動不變。SSOT → field-controls.spec.md「寬度軸(width: fill / hug)」。 */
|
|
306
|
+
width?: FieldWidth
|
|
293
307
|
error?: boolean
|
|
294
308
|
size?: 'sm' | 'md' | 'lg'
|
|
295
309
|
/** ISO date(YYYY-MM-DD)或 ISO datetime(YYYY-MM-DDTHH:MM:SS,當 showTime=true) */
|
|
@@ -362,6 +376,7 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
|
|
|
362
376
|
{
|
|
363
377
|
mode,
|
|
364
378
|
variant: variantProp,
|
|
379
|
+
width,
|
|
365
380
|
error: errorProp = false,
|
|
366
381
|
size: sizeProp,
|
|
367
382
|
value,
|
|
@@ -396,7 +411,8 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
|
|
|
396
411
|
const disabled = useResolvedFieldDisabled(disabledProp)
|
|
397
412
|
// 2026-06-08 SSOT:mode 經 useResolvedFieldMode;修 <Field mode="display"> 漏 cascade
|
|
398
413
|
const resolvedMode = useResolvedFieldMode({ mode, disabled })
|
|
399
|
-
const
|
|
414
|
+
const emptyDisplay = useFieldEmptyDisplay()
|
|
415
|
+
const variant: FieldVariantInternal = useResolvedFieldVariant(variantProp)
|
|
400
416
|
const isEditable = resolvedMode === 'edit'
|
|
401
417
|
// 2026-05-18 改 import ICON_SIZE SSOT(per user『做完』approval,消除 M17 違反 7+ 重複 ternary)
|
|
402
418
|
const iconSize = ICON_SIZE[size as 'sm' | 'md' | 'lg']
|
|
@@ -408,11 +424,14 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
|
|
|
408
424
|
// a11y:role="combobox" 必須有 accessible name(aria-label / labelledby / fieldCtx label)
|
|
409
425
|
const accessibleName = ariaLabelProp ?? (ariaLabelledByProp ? undefined : (fieldCtx?.id ? undefined : resolvedPlaceholder))
|
|
410
426
|
|
|
411
|
-
// Sync draft from value
|
|
412
|
-
// clobber user
|
|
427
|
+
// Sync draft from value:closed 期間恆跟隨 + open false→true 同步(避免 popover 開啟期間
|
|
428
|
+
// value 改變 clobber user 的編輯)。
|
|
429
|
+
// 2026-07-14 audit Dim 26(V4 state shadow):needConfirm trigger 讀 draft,原「只在 false→true
|
|
430
|
+
// 同步」使 controlled value 於關閉期間更新後,trigger 仍顯示舊值直到再次開啟 —— 改為
|
|
431
|
+
// 只要 open=false 就同步(與 range picker 分支 L83x 同款 canonical)。
|
|
413
432
|
const lastOpenRef = React.useRef(open)
|
|
414
433
|
React.useEffect(() => {
|
|
415
|
-
if (!lastOpenRef.current
|
|
434
|
+
if (!open || !lastOpenRef.current) setDraft(value ?? null)
|
|
416
435
|
lastOpenRef.current = open
|
|
417
436
|
}, [open, value])
|
|
418
437
|
|
|
@@ -464,16 +483,16 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
|
|
|
464
483
|
if (!showDisplayEndIcon) {
|
|
465
484
|
// 2026-05-14 I2 fix(spec contract (e) display typography canonical):bare span 套
|
|
466
485
|
// `fieldDisplayTextClass(size)`(sm/md→text-body,lg→text-body-lg)— 對齊 Field family 統一。
|
|
467
|
-
if (!value) return <span className={cn(fieldDisplayTextClass(size),
|
|
486
|
+
if (!value) return <span className={cn(fieldDisplayTextClass(size), fieldEmptyColorClass(resolvedMode), className)}>{emptyDisplay}</span>
|
|
468
487
|
return <span className={cn(fieldDisplayTextClass(size), 'truncate', className)}>{displayCommitted}</span>
|
|
469
488
|
}
|
|
470
489
|
return (
|
|
471
490
|
<div
|
|
472
|
-
className={cn(fieldWrapperStyles({ mode: 'display', variant, size }), className)}
|
|
491
|
+
className={cn(fieldWrapperStyles({ mode: 'display', variant, width, size }), className)}
|
|
473
492
|
data-field-mode="display"
|
|
474
493
|
>
|
|
475
|
-
<span className={cn(bareInputStyles, 'flex-1 min-w-0 truncate', !value &&
|
|
476
|
-
{value ? displayCommitted :
|
|
494
|
+
<span className={cn(bareInputStyles, 'flex-1 min-w-0 truncate', !value && fieldEmptyColorClass(resolvedMode))}>
|
|
495
|
+
{value ? displayCommitted : emptyDisplay}
|
|
477
496
|
</span>
|
|
478
497
|
<ItemSuffix className="pointer-events-none">
|
|
479
498
|
<CalendarIcon size={iconSize} className="text-fg-muted" aria-hidden />
|
|
@@ -486,7 +505,7 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
|
|
|
486
505
|
if (!isEditable) {
|
|
487
506
|
return (
|
|
488
507
|
<div
|
|
489
|
-
className={cn(fieldWrapperStyles({ mode: resolvedMode, variant: variant, size }), className)}
|
|
508
|
+
className={cn(fieldWrapperStyles({ mode: resolvedMode, variant: variant, width, size }), className)}
|
|
490
509
|
data-field-mode={resolvedMode}
|
|
491
510
|
aria-disabled={resolvedMode === 'disabled' ? true : undefined}
|
|
492
511
|
{...(props as React.HTMLAttributes<HTMLDivElement>)}
|
|
@@ -494,7 +513,7 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
|
|
|
494
513
|
<span className={cn('flex-1 min-w-0 truncate', resolvedMode === 'disabled' && 'text-fg-disabled')}>
|
|
495
514
|
{value
|
|
496
515
|
? displayCommitted
|
|
497
|
-
: <span className=
|
|
516
|
+
: <span className={fieldEmptyColorClass(resolvedMode)}>{emptyDisplay}</span>
|
|
498
517
|
}
|
|
499
518
|
</span>
|
|
500
519
|
{/* 2026-06-26 類型身份 indicator:edit 顯示 / readonly 不顯示(純值、不可開) / disabled 保留(fg-disabled,對齊原生 <select disabled>);
|
|
@@ -527,18 +546,22 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
|
|
|
527
546
|
<PopoverTrigger asChild>
|
|
528
547
|
<div
|
|
529
548
|
ref={ref}
|
|
530
|
-
|
|
531
|
-
role
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
aria-
|
|
538
|
-
aria-
|
|
539
|
-
aria-
|
|
540
|
-
aria-
|
|
541
|
-
aria-
|
|
549
|
+
// a11y(2026-07-14 dim-10 修):typeable 模式 combobox 語意(name / state / 鍵盤)
|
|
550
|
+
// 集中在內層 <input>(APG editable-combobox idiom)— 外層 div 移除 role / tabIndex
|
|
551
|
+
// / aria-*,否則形成「關掉鍵盤 handler 的假 combobox tab stop」+ 內層 input 變成
|
|
552
|
+
// 第二個未命名 tab stop(雙重焦點站)。非 typeable 維持原 div-as-combobox canonical。
|
|
553
|
+
id={typeable ? undefined : (idProp ?? fieldCtx?.id)}
|
|
554
|
+
role={typeable ? undefined : 'combobox'}
|
|
555
|
+
tabIndex={typeable ? undefined : (disabled ? -1 : 0)}
|
|
556
|
+
aria-disabled={typeable ? undefined : (disabled || undefined)}
|
|
557
|
+
aria-label={typeable ? undefined : accessibleName}
|
|
558
|
+
aria-labelledby={typeable ? undefined : (ariaLabelledByProp ?? fieldCtx?.labelId)}
|
|
559
|
+
aria-invalid={typeable ? undefined : (error || undefined)}
|
|
560
|
+
aria-required={typeable ? undefined : (fieldCtx?.required || undefined)}
|
|
561
|
+
aria-describedby={typeable ? undefined : (ariaDescribedByProp ?? fieldCtx?.descriptionId)}
|
|
562
|
+
aria-errormessage={typeable ? undefined : (ariaErrorMessageProp ?? (error ? fieldCtx?.errorId : undefined))}
|
|
563
|
+
aria-haspopup={typeable ? undefined : 'dialog'}
|
|
564
|
+
aria-expanded={typeable ? undefined : open}
|
|
542
565
|
data-field-mode="edit"
|
|
543
566
|
data-error={error ? '' : undefined}
|
|
544
567
|
// Radix PopoverTrigger 只 compose onClick(onOpenToggle),`<div>` trigger 無
|
|
@@ -551,7 +574,7 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
|
|
|
551
574
|
if (e.key === 'Escape') setOpen(false)
|
|
552
575
|
}}
|
|
553
576
|
className={cn(
|
|
554
|
-
fieldWrapperStyles({ mode: 'edit', variant: variant, size, error }),
|
|
577
|
+
fieldWrapperStyles({ mode: 'edit', variant: variant, width, size, error }),
|
|
555
578
|
'text-left cursor-pointer',
|
|
556
579
|
'focus-visible:outline-none',
|
|
557
580
|
className,
|
|
@@ -562,8 +585,21 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
|
|
|
562
585
|
// Issue 10 typed input(2026-05-10):real `<input>` 接 user 鍵盤打字。
|
|
563
586
|
// Click 在 input 上不 propagate 給外層 popover trigger(避免每次打字都開 popover)。
|
|
564
587
|
// Calendar icon `<ItemSuffix>` 點才開 popover(Material/Ant typed-date idiom)。
|
|
588
|
+
// a11y(2026-07-14 dim-10 修):input 持完整 combobox 語意(id/name/state,APG
|
|
589
|
+
// editable-combobox)— 外層 div 已讓位(見上方 role/tabIndex 註解);ArrowDown
|
|
590
|
+
// 開 popover 補鍵盤開啟路徑(原僅 icon click 可開,鍵盤 user 無入口)。
|
|
565
591
|
<input
|
|
566
592
|
type="text"
|
|
593
|
+
id={idProp ?? fieldCtx?.id}
|
|
594
|
+
role="combobox"
|
|
595
|
+
aria-haspopup="dialog"
|
|
596
|
+
aria-expanded={open}
|
|
597
|
+
aria-label={accessibleName}
|
|
598
|
+
aria-labelledby={ariaLabelledByProp ?? fieldCtx?.labelId}
|
|
599
|
+
aria-required={fieldCtx?.required || undefined}
|
|
600
|
+
aria-describedby={ariaDescribedByProp ?? fieldCtx?.descriptionId}
|
|
601
|
+
aria-errormessage={ariaErrorMessageProp ?? ((inputInvalid || error) ? fieldCtx?.errorId : undefined)}
|
|
602
|
+
disabled={disabled}
|
|
567
603
|
className={cn(bareInputStyles, 'truncate', !inputDraft && 'placeholder:text-fg-muted')}
|
|
568
604
|
value={inputDraft}
|
|
569
605
|
placeholder={resolvedPlaceholder}
|
|
@@ -575,6 +611,7 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
|
|
|
575
611
|
if (composingRef.current) return
|
|
576
612
|
if (e.key === 'Enter') { e.preventDefault(); handleInputCommit(inputDraft) }
|
|
577
613
|
if (e.key === 'Escape') { setInputDraft(displayLive); setInputInvalid(false); e.preventDefault() }
|
|
614
|
+
if (e.key === 'ArrowDown' && !open) { e.preventDefault(); setOpen(true) }
|
|
578
615
|
}}
|
|
579
616
|
onBlur={() => { if (!composingRef.current) handleInputCommit(inputDraft) }}
|
|
580
617
|
onClick={(e) => e.stopPropagation()}
|
|
@@ -607,12 +644,18 @@ const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
|
|
|
607
644
|
</ItemSuffix>
|
|
608
645
|
</div>
|
|
609
646
|
</PopoverTrigger>
|
|
610
|
-
<PopoverContent
|
|
611
|
-
|
|
612
|
-
|
|
647
|
+
<PopoverContent
|
|
648
|
+
className="w-auto p-0"
|
|
649
|
+
align="start"
|
|
650
|
+
aria-label="日期選擇" // i18n-allow: DS default dialog label
|
|
651
|
+
>
|
|
652
|
+
{/* a11y(2026-07-14 dim-10 修):Radix PopoverContent 自帶 role="dialog"(popover.tsx:58)
|
|
653
|
+
— 內層 div 原本重複 role="dialog" 形成雙層 nested unnamed dialog,改為純 layout div,
|
|
654
|
+
accessible name 收斂到外層 PopoverContent aria-label(單一 dialog 層)。
|
|
655
|
+
2026-05-06 v9.1:`flex flex-col flex-1 min-h-0` 完成 M25 chain — viewport
|
|
613
656
|
壓縮時 dialog 縮 + 內 calendar/footer 排序;原無 chain 致 calendar 末行被
|
|
614
657
|
overflow-hidden 切掉、footer 推出 popover(user 報「位置改變就壞掉」根因)。 */}
|
|
615
|
-
<div
|
|
658
|
+
<div className="flex flex-col flex-1 min-h-0">
|
|
616
659
|
{/* Calendar 區包 overflow-y-auto:viewport 壓縮時 calendar 內滾(Material / Carbon
|
|
617
660
|
date picker idiom)。footer 永遠 in-view(SurfaceFooter shrink-0)。 */}
|
|
618
661
|
<div className="flex-1 min-h-0 overflow-y-auto">
|
|
@@ -704,6 +747,9 @@ export interface DatePickerRangeProps
|
|
|
704
747
|
mode?: FieldMode
|
|
705
748
|
/** Field chrome variant. Default = context.variant ?? 'default'. Per-prop override. */
|
|
706
749
|
variant?: FieldVariant
|
|
750
|
+
/** 寬度軸 — `fill` 填滿容器(default)/ `hug` 依內容收縮(value 寬 + slot 寬 + gap + 內 padding);
|
|
751
|
+
* chrome 與互動不變。SSOT → field-controls.spec.md「寬度軸(width: fill / hug)」。 */
|
|
752
|
+
width?: FieldWidth
|
|
707
753
|
error?: boolean
|
|
708
754
|
size?: 'sm' | 'md' | 'lg'
|
|
709
755
|
/** 區間值:[start ISO, end ISO]。任一 null 代表尚未選。 */
|
|
@@ -728,6 +774,7 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
|
|
|
728
774
|
{
|
|
729
775
|
mode,
|
|
730
776
|
variant: variantProp,
|
|
777
|
+
width,
|
|
731
778
|
error: errorProp = false,
|
|
732
779
|
size: sizeProp,
|
|
733
780
|
value,
|
|
@@ -756,7 +803,8 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
|
|
|
756
803
|
const disabled = useResolvedFieldDisabled(disabledProp)
|
|
757
804
|
// 2026-06-08 SSOT:mode 經 useResolvedFieldMode;修 <Field mode="display"> 漏 cascade
|
|
758
805
|
const resolvedMode = useResolvedFieldMode({ mode, disabled })
|
|
759
|
-
const
|
|
806
|
+
const emptyDisplay = useFieldEmptyDisplay()
|
|
807
|
+
const variant: FieldVariantInternal = useResolvedFieldVariant(variantProp)
|
|
760
808
|
const isEditable = resolvedMode === 'edit'
|
|
761
809
|
// 2026-05-18 改 import ICON_SIZE SSOT(per user『做完』approval,消除 M17 違反 7+ 重複 ternary)
|
|
762
810
|
const iconSize = ICON_SIZE[size as 'sm' | 'md' | 'lg']
|
|
@@ -778,12 +826,15 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
|
|
|
778
826
|
const endBtnRef = React.useRef<HTMLButtonElement>(null)
|
|
779
827
|
const hasInteractedOutsideRef = React.useRef(false)
|
|
780
828
|
|
|
781
|
-
//
|
|
782
|
-
//
|
|
783
|
-
//
|
|
829
|
+
// Draft sync canonical(2026-07-14 dim-26 V4 修,升級 2026-05-02 v3):
|
|
830
|
+
// - open=false(關閉期間):controlled value 變更**必**同步 draft — needConfirm 顯示層讀
|
|
831
|
+
// draft(startIso/endIso),不同步會讓 trigger 持續顯示 stale 舊區間(外部 controlled
|
|
832
|
+
// update 被凍結)。關閉期間無編輯進行,直接鏡射無 clobber 風險。
|
|
833
|
+
// - open=true(開啟期間):只在 false→true 轉換時 seed 一次;開啟中 value reference 變更
|
|
834
|
+
// 不覆寫,保護 user 尚未確認的 draft 編輯(原 v3 canonical 保留)。
|
|
784
835
|
const lastOpenRef = React.useRef(open)
|
|
785
836
|
React.useEffect(() => {
|
|
786
|
-
if (!lastOpenRef.current
|
|
837
|
+
if (!open || !lastOpenRef.current) setDraft(value ?? [null, null])
|
|
787
838
|
lastOpenRef.current = open
|
|
788
839
|
}, [open, value])
|
|
789
840
|
|
|
@@ -888,7 +939,7 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
|
|
|
888
939
|
// mode='display'(Phase B2 2026-05-05):純內容輸出 — 無 Field wrapper / 無 Calendar icon。
|
|
889
940
|
if (resolvedMode === 'display') {
|
|
890
941
|
const hasAny = !!(startIso || endIso)
|
|
891
|
-
if (!hasAny) return <span className={cn(
|
|
942
|
+
if (!hasAny) return <span className={cn(fieldEmptyColorClass(resolvedMode), className)}>{emptyDisplay}</span>
|
|
892
943
|
return (
|
|
893
944
|
<span className={cn('inline-flex items-center min-w-0', nakedCellRowModeAlign, className)}>
|
|
894
945
|
<span className={cn('truncate', !startIso && 'text-fg-muted')}>
|
|
@@ -907,7 +958,7 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
|
|
|
907
958
|
return (
|
|
908
959
|
<div
|
|
909
960
|
ref={ref}
|
|
910
|
-
className={cn(fieldWrapperStyles({ mode: resolvedMode, variant: variant, size }), className)}
|
|
961
|
+
className={cn(fieldWrapperStyles({ mode: resolvedMode, variant: variant, width, size }), className)}
|
|
911
962
|
data-field-mode={resolvedMode}
|
|
912
963
|
aria-disabled={resolvedMode === 'disabled' ? true : undefined}
|
|
913
964
|
{...props}
|
|
@@ -943,7 +994,7 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
|
|
|
943
994
|
data-error={error ? '' : undefined}
|
|
944
995
|
data-state={open ? 'open' : 'closed'}
|
|
945
996
|
className={cn(
|
|
946
|
-
fieldWrapperStyles({ mode: 'edit', size, error }),
|
|
997
|
+
fieldWrapperStyles({ mode: 'edit', width, size, error }),
|
|
947
998
|
'cursor-text',
|
|
948
999
|
className,
|
|
949
1000
|
)}
|
|
@@ -1002,6 +1053,7 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
|
|
|
1002
1053
|
<PopoverContent
|
|
1003
1054
|
className="w-auto p-0"
|
|
1004
1055
|
align="start"
|
|
1056
|
+
aria-label="日期區間選擇" // i18n-allow: DS default dialog label
|
|
1005
1057
|
// 2026-07-05 D4 focus 回復(機制詳 :758 comment):outside-click 標記不搶焦(鏡射
|
|
1006
1058
|
// Radix non-modal 自家 hasInteractedOutside guard);其餘關閉路徑(Esc / 確定 /
|
|
1007
1059
|
// 選完自動關)preventDefault 掉內建 triggerRef.focus()(Anchor-only 恆 null no-op)
|
|
@@ -1015,8 +1067,10 @@ const DatePickerRange = React.forwardRef<HTMLDivElement, DatePickerRangeProps>(
|
|
|
1015
1067
|
hasInteractedOutsideRef.current = false
|
|
1016
1068
|
}}
|
|
1017
1069
|
>
|
|
1018
|
-
{/* 2026-
|
|
1019
|
-
|
|
1070
|
+
{/* a11y(2026-07-14 dim-10 修):accessible name 收斂到外層 PopoverContent(Radix 自帶
|
|
1071
|
+
role="dialog")— 原內層第二個 role="dialog" 移除,避免 nested dialog 且外層 dialog 無名。
|
|
1072
|
+
2026-05-06 v9.1 M25 chain — 同 single DatePicker 修法,viewport 壓縮 calendar 內滾 + footer 永遠 in-view */}
|
|
1073
|
+
<div className="flex flex-col flex-1 min-h-0">
|
|
1020
1074
|
<div className="flex-1 min-h-0 overflow-y-auto">
|
|
1021
1075
|
<CalendarTimeContainer
|
|
1022
1076
|
showTime={showTime}
|
|
@@ -156,23 +156,23 @@ export const StateBehavior: Story = {
|
|
|
156
156
|
render: () => (
|
|
157
157
|
<div className="flex flex-col gap-10">
|
|
158
158
|
<div>
|
|
159
|
-
<H3>空值呈現 —
|
|
159
|
+
<H3>空值呈現 — 一律用半形 `-` 字元(hyphen)</H3>
|
|
160
160
|
<Desc>
|
|
161
|
-
DescriptionList 是唯讀資訊展示,空值不留空白(會讓使用者以為資料沒載入完)
|
|
162
|
-
(
|
|
161
|
+
DescriptionList 是唯讀資訊展示,空值不留空白(會讓使用者以為資料沒載入完)。一律用半形連字號
|
|
162
|
+
(`-`,對齊 Field `EMPTY_DISPLAY`)明確表達「有查過,但這個欄位目前沒值」;色同 value `text-foreground`。對齊 Atlassian / Polaris / GitHub 的資訊卡慣例。
|
|
163
163
|
</Desc>
|
|
164
164
|
<div className="border border-dashed border-divider rounded-md p-4 max-w-md">
|
|
165
165
|
<DescriptionList cols={2}>
|
|
166
166
|
<DescriptionItem label="姓名">Ada Chen</DescriptionItem>
|
|
167
|
-
<DescriptionItem label="職稱"><span className="text-
|
|
167
|
+
<DescriptionItem label="職稱"><span className="text-foreground">-</span></DescriptionItem>
|
|
168
168
|
<DescriptionItem label="Email">user@example.com</DescriptionItem>
|
|
169
|
-
<DescriptionItem label="電話"><span className="text-
|
|
169
|
+
<DescriptionItem label="電話"><span className="text-foreground">-</span></DescriptionItem>
|
|
170
170
|
<DescriptionItem label="團隊">Engineering</DescriptionItem>
|
|
171
|
-
<DescriptionItem label="直屬主管"><span className="text-
|
|
171
|
+
<DescriptionItem label="直屬主管"><span className="text-foreground">-</span></DescriptionItem>
|
|
172
172
|
</DescriptionList>
|
|
173
173
|
</div>
|
|
174
174
|
<p className="text-footnote text-fg-muted mt-3">
|
|
175
|
-
空值不應該用「N/A」/「暫無」等字串——不同 consumer
|
|
175
|
+
空值不應該用「N/A」/「暫無」等字串——不同 consumer 會選不同字,破壞視覺一致。一律半形連字號 `-`。
|
|
176
176
|
</p>
|
|
177
177
|
</div>
|
|
178
178
|
|
|
@@ -180,14 +180,16 @@ export const StateBehavior: Story = {
|
|
|
180
180
|
<H3>長 value — 自然換行,撐高該 grid cell</H3>
|
|
181
181
|
<Desc>
|
|
182
182
|
`value` 是自然流文字,超過欄寬自然換行(CSS grid 會讓該 row 的 cell 變高,其他 cell 保持 label
|
|
183
|
-
top-aligned)。不使用 truncate——value
|
|
183
|
+
top-aligned)。不使用 truncate——value 是被讀的內容,截斷會讓使用者漏資訊。帶空白的文字(如職稱)
|
|
184
|
+
自然斷行;無空白長字串(email / URL / token)需在該 item 加 `break-all` 才會斷(此範例 Email 欄已加;
|
|
185
|
+
vertical dd 預設不強制斷字,長字串由 consumer 自加 break-all)。
|
|
184
186
|
</Desc>
|
|
185
187
|
<div className="border border-dashed border-divider rounded-md p-4 max-w-md">
|
|
186
188
|
<DescriptionList cols={2}>
|
|
187
189
|
<DescriptionItem label="姓名">Ada Chen</DescriptionItem>
|
|
188
190
|
<DescriptionItem label="職稱">Senior Staff Principal Engineer, Design Systems</DescriptionItem>
|
|
189
191
|
<DescriptionItem label="辦公地點">Taipei, Taiwan</DescriptionItem>
|
|
190
|
-
<DescriptionItem label="Email">very.long.email.address@subdomain.example.com</DescriptionItem>
|
|
192
|
+
<DescriptionItem label="Email" className="min-w-0 break-all">very.long.email.address@subdomain.example.com</DescriptionItem>
|
|
191
193
|
</DescriptionList>
|
|
192
194
|
</div>
|
|
193
195
|
</div>
|
|
@@ -246,7 +248,7 @@ export const Accessibility = {
|
|
|
246
248
|
render: () => (
|
|
247
249
|
<div className="max-w-3xl text-body text-fg-secondary">
|
|
248
250
|
<h3 className="text-h5 text-foreground mb-2">無障礙設計</h3>
|
|
249
|
-
<p className="whitespace-pre-line">{"詳 `description-list.spec.md`「無障礙」段。摘要:\n\n- 語意 HTML:外層 <dl>,每組 <dt>(term)+ <dd>(description)— screen reader 讀「term X, description Y」配對敘事\n- DT/DD 配對:DescriptionItem 強制一組配對,不分開暴露 <dt>/<dd> primitive\n- 空值:consumer
|
|
251
|
+
<p className="whitespace-pre-line">{"詳 `description-list.spec.md`「無障礙」段。摘要:\n\n- 語意 HTML:外層 <dl>,每組 <dt>(term)+ <dd>(description)— screen reader 讀「term X, description Y」配對敘事\n- DT/DD 配對:DescriptionItem 強制一組配對,不分開暴露 <dt>/<dd> primitive\n- 空值:consumer 傳半形 - 占位(裸 - SR 敘事弱,宜補 sr-only「無資料」,比空 <dd> 明確)\n- 多欄 cols>1:視覺 grid、DOM 仍 item 順序,SR 依 DOM 敘事\n- 無互動:純唯讀呈現,無 keyboard / focus state(無 ARIA 補強需求,語意由原生 dl/dt/dd 承載)"}</p>
|
|
250
252
|
</div>
|
|
251
253
|
),
|
|
252
254
|
}
|
|
@@ -185,7 +185,7 @@ export const LayoutRule: Story = {
|
|
|
185
185
|
<DescriptionItem label="職稱">Senior Design Engineer</DescriptionItem>
|
|
186
186
|
</DescriptionList>
|
|
187
187
|
</Frame>
|
|
188
|
-
<Label warn>↑ 窄容器配 cols=2 → email
|
|
188
|
+
<Label warn>↑ 窄容器配 cols=2 → 職稱被迫斷行、email 擠壓貼邊,節奏亂、可讀性差</Label>
|
|
189
189
|
</Rule>
|
|
190
190
|
</div>
|
|
191
191
|
),
|
|
@@ -238,7 +238,7 @@ export const LabelAlignmentRule: Story = {
|
|
|
238
238
|
</div>
|
|
239
239
|
</Frame>
|
|
240
240
|
<Label warn>
|
|
241
|
-
↑ 這是自訂 layout 模擬 key-
|
|
241
|
+
↑ 這是自訂 layout 模擬 label 左 / value 右(key-left-value-right)→ 不是 DescriptionList,也無 dl/dt/dd 語義
|
|
242
242
|
</Label>
|
|
243
243
|
</Rule>
|
|
244
244
|
</div>
|
|
@@ -173,7 +173,7 @@ consumer 要在 DL 上方加 section heading(「基本資料」/「團隊資訊
|
|
|
173
173
|
|
|
174
174
|
- **語意 HTML**:外層 `<dl>`,每組內 `<dt>` 為 term、`<dd>` 為 description——screen reader 會讀成「term X, description Y」對話,明確表達屬性-值關係
|
|
175
175
|
- **DT / DD 配對**:每個 `<dt>` 必須有對應的 `<dd>`(不可孤立),否則 SR 敘事會中斷;元件內建一組 `DescriptionItem` 強制配對,不分開暴露 `<dt>` / `<dd>` primitive
|
|
176
|
-
- **空值呈現**:value 空時由 **consumer 自行傳入** `<span className="text-
|
|
176
|
+
- **空值呈現**:value 空時由 **consumer 自行傳入** `<span className="text-foreground">-</span>` 占位(半形 hyphen `-`,對齊 Field `EMPTY_DISPLAY` DS-wide 空值符號,2026-07-08 user 拍板「空值都用"-"⋯我從頭到尾哪裡有說要用全形的」;元件不自動 normalize——`<dd>` 直接 render `children`),`text-foreground`(同 value 色——「-」是不可編輯供檢視的值,非 placeholder 提示,2026-07-09 user 拍板)。**a11y known follow-up**:裸 `-` SR 敘事弱(半形連字號多被 SR 略過),宜補 `<span className="sr-only">無資料</span>` 或 `aria-label`,比空 `<dd>` 更明確
|
|
177
177
|
- **多欄 `cols > 1`**:視覺為 grid 欄位,但 DOM 順序為 item 順序——SR 仍依 DOM 敘事(term1 → desc1 → term2 → desc2),不依視覺欄位;設計時確保 DOM 順序符合語意分組
|
|
178
178
|
- **長值換行**:horizontal 模式的 value(`<dd>`)以 `break-all min-w-0` 處理,讓 URL / ID 等無空白長字串能斷行,避免撐破單列;vertical 模式 value 佔滿整欄寬,自然流文字依字詞換行(不強制單行 truncate,長內容保留可讀完整性)。若 vertical 模式需展示無空白長字串(連續英數 token),由 consumer 自行於該 value 加 `break-all`
|
|
179
179
|
- **列表識別**:預設 `<dl>` 有部分瀏覽器 SR 不視為 list,若需明確 list 語意,DL 根容器可搭配 `role="list"` + `<div role="listitem">`(目前預設不加,保留標準 `<dl>` 語意,consumer 可自行加 role 覆蓋)
|
|
@@ -188,7 +188,7 @@ DescriptionList 是**唯讀 label / value 資料呈現**(非互動 / 非 variant
|
|
|
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` / `direction` / `divided`) + `ColsMatrix`(元件特有 1 / 2 / 3 欄對照) + `StateBehavior`(空值
|
|
191
|
+
對應 anatomy story(實際 5 個,對齊 6-canonical 結構;ColorMatrix / SizeMatrix N/A):`Overview`(anatomy + typography + 間距) + `Inspector`(Controls 即時切 `cols` / `direction` / `divided`) + `ColsMatrix`(元件特有 1 / 2 / 3 欄對照) + `StateBehavior`(空值 `-` / 長值 / 多行 / ReactNode value) + `Accessibility`(`dl/dt/dd` 語意 + 無互動說明)。
|
|
192
192
|
|
|
193
193
|
---
|
|
194
194
|
|
|
@@ -196,7 +196,7 @@ DescriptionList 是**唯讀 label / value 資料呈現**(非互動 / 非 variant
|
|
|
196
196
|
|
|
197
197
|
- **Disabled(action cell)**:DescriptionList 主體為唯讀資料呈現,本身無 disabled state。**dd 內互動內容 canonical(2026-07-04 Q9 拍板,三處立場收斂)**:操作型互動(Button / Input)**禁止**(見「禁止事項」— 需要動作 → Field read-only / inline-edit / action row / 卡片 header action);展示 / 導覽型 ReactNode(Tag / Badge / **Link**)**允許**,Link 自行 own disabled,DL 不干預。對齊 Polaris(ReactNode 型別 + 純敘述範例)/ Ant(action 放 extra 不放 dd)/ Carbon(read-only default)三家共識。
|
|
198
198
|
- **Loading**:DL 非 async surface,無 loading prop。若 page-level data 載入中,consumer 應在 DL 外層用 `<Skeleton>`(每組 dt/dd 對應一條 skeleton line)取代;DL 本體不渲染 loading state。
|
|
199
|
-
- **Empty(no items / empty value)**:no items → consumer 應 conditional 渲 `<Empty>` 取代 DL,不渲空 `<dl>`(SR 會讀「empty list」造成混淆);individual value 空 → consumer
|
|
199
|
+
- **Empty(no items / empty value)**:no items → consumer 應 conditional 渲 `<Empty>` 取代 DL,不渲空 `<dl>`(SR 會讀「empty list」造成混淆);individual value 空 → consumer 應自行傳入半形 `-`(hyphen,對齊 Field `EMPTY_DISPLAY`,2026-07-08 user 拍板;包 `text-foreground`(色同 value,2026-07-09);元件不自動 normalize,已在「無障礙」段 codify)。
|
|
200
200
|
- **長 label / 長值**:horizontal 模式 label(`dt`)`shrink-0` 不收縮、不截斷,value(`dd`)`break-all min-w-0` 斷行吸收擠壓;vertical 模式兩者佔滿欄寬自然換行。無空白長字串(URL / ID)詳「無障礙」段「長值換行」。
|
|
201
201
|
- **Dark mode**:走 semantic token(`text-fg-secondary` / `text-foreground`)自動 adapt。
|
|
202
202
|
- **Density**:垂直 gap 隨 `layout-space` token density-aware(見「間距」段),typography fixed reading mode tier 不變。
|