@qijenchen/design-system 0.1.0-beta.8 → 0.1.0-beta.81
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 +201 -0
- package/README.md +10 -9
- package/cli-init.mjs +90 -0
- package/dist/components/Accordion/accordion.d.ts +1 -1
- package/dist/components/Accordion/accordion.d.ts.map +1 -1
- package/dist/components/Accordion/accordion.js +4 -1
- package/dist/components/Accordion/accordion.js.map +1 -1
- package/dist/components/Accordion/index.d.ts +2 -0
- package/dist/components/Accordion/index.d.ts.map +1 -0
- package/dist/components/Accordion/index.js +9 -0
- package/dist/components/Accordion/index.js.map +1 -0
- package/dist/components/Alert/alert.d.ts +7 -2
- package/dist/components/Alert/alert.d.ts.map +1 -1
- package/dist/components/Alert/alert.js +12 -8
- package/dist/components/Alert/alert.js.map +1 -1
- package/dist/components/Alert/index.d.ts +2 -0
- package/dist/components/Alert/index.d.ts.map +1 -0
- package/dist/components/Alert/index.js +7 -0
- package/dist/components/Alert/index.js.map +1 -0
- package/dist/components/AppShell/_demo-helpers.d.ts +3 -1
- package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -1
- package/dist/components/AppShell/app-shell.d.ts +3 -3
- package/dist/components/AppShell/app-shell.d.ts.map +1 -1
- package/dist/components/AppShell/app-shell.js +9 -8
- package/dist/components/AppShell/app-shell.js.map +1 -1
- package/dist/components/AppShell/index.d.ts +2 -0
- package/dist/components/AppShell/index.d.ts.map +1 -0
- package/dist/components/AppShell/index.js +7 -0
- package/dist/components/AppShell/index.js.map +1 -0
- package/dist/components/AspectRatio/aspect-ratio.d.ts +3 -2
- package/dist/components/AspectRatio/aspect-ratio.d.ts.map +1 -1
- package/dist/components/AspectRatio/aspect-ratio.js +4 -2
- package/dist/components/AspectRatio/aspect-ratio.js.map +1 -1
- package/dist/components/AspectRatio/index.d.ts +2 -0
- package/dist/components/AspectRatio/index.d.ts.map +1 -0
- package/dist/components/AspectRatio/index.js +6 -0
- package/dist/components/AspectRatio/index.js.map +1 -0
- package/dist/components/Avatar/avatar.d.ts +14 -7
- package/dist/components/Avatar/avatar.d.ts.map +1 -1
- package/dist/components/Avatar/avatar.js +19 -24
- package/dist/components/Avatar/avatar.js.map +1 -1
- package/dist/components/Avatar/index.d.ts +2 -0
- package/dist/components/Avatar/index.d.ts.map +1 -0
- package/dist/components/Avatar/index.js +6 -0
- package/dist/components/Avatar/index.js.map +1 -0
- package/dist/components/Badge/badge.d.ts +20 -8
- package/dist/components/Badge/badge.d.ts.map +1 -1
- package/dist/components/Badge/badge.js +9 -6
- package/dist/components/Badge/badge.js.map +1 -1
- package/dist/components/Badge/index.d.ts +2 -0
- package/dist/components/Badge/index.d.ts.map +1 -0
- package/dist/components/Badge/index.js +7 -0
- package/dist/components/Badge/index.js.map +1 -0
- package/dist/components/Breadcrumb/breadcrumb.d.ts +15 -2
- package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -1
- package/dist/components/Breadcrumb/breadcrumb.js +9 -3
- package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
- package/dist/components/Breadcrumb/index.d.ts +2 -0
- package/dist/components/Breadcrumb/index.d.ts.map +1 -0
- package/dist/components/Breadcrumb/index.js +12 -0
- package/dist/components/Breadcrumb/index.js.map +1 -0
- package/dist/components/BulkActionBar/bulk-action-bar.d.ts +3 -3
- 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/BulkActionBar/index.d.ts +2 -0
- package/dist/components/BulkActionBar/index.d.ts.map +1 -0
- package/dist/components/BulkActionBar/index.js +7 -0
- package/dist/components/BulkActionBar/index.js.map +1 -0
- package/dist/components/Button/button.d.ts +10 -10
- package/dist/components/Button/button.d.ts.map +1 -1
- package/dist/components/Button/button.js +79 -50
- package/dist/components/Button/button.js.map +1 -1
- package/dist/components/Button/index.d.ts +3 -0
- package/dist/components/Button/index.d.ts.map +1 -0
- package/dist/components/Button/index.js +11 -0
- package/dist/components/Button/index.js.map +1 -0
- package/dist/components/Calendar/calendar.d.ts +9 -5
- package/dist/components/Calendar/calendar.d.ts.map +1 -1
- package/dist/components/Calendar/calendar.js +88 -76
- package/dist/components/Calendar/calendar.js.map +1 -1
- package/dist/components/Calendar/index.d.ts +2 -0
- package/dist/components/Calendar/index.d.ts.map +1 -0
- package/dist/components/Calendar/index.js +6 -0
- package/dist/components/Calendar/index.js.map +1 -0
- package/dist/components/Carousel/carousel.d.ts.map +1 -1
- package/dist/components/Carousel/carousel.js +11 -6
- package/dist/components/Carousel/carousel.js.map +1 -1
- package/dist/components/Carousel/index.d.ts +2 -0
- package/dist/components/Carousel/index.d.ts.map +1 -0
- package/dist/components/Carousel/index.js +11 -0
- package/dist/components/Carousel/index.js.map +1 -0
- package/dist/components/Chart/chart.d.ts +2 -2
- package/dist/components/Chart/chart.d.ts.map +1 -1
- package/dist/components/Chart/chart.js +4 -2
- package/dist/components/Chart/chart.js.map +1 -1
- package/dist/components/Chart/index.d.ts +2 -0
- package/dist/components/Chart/index.d.ts.map +1 -0
- package/dist/components/Chart/index.js +11 -0
- package/dist/components/Chart/index.js.map +1 -0
- package/dist/components/Checkbox/checkbox-group.d.ts +2 -1
- package/dist/components/Checkbox/checkbox-group.d.ts.map +1 -1
- package/dist/components/Checkbox/checkbox-group.js.map +1 -1
- package/dist/components/Checkbox/checkbox.d.ts +18 -9
- package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox/checkbox.js +70 -15
- package/dist/components/Checkbox/checkbox.js.map +1 -1
- package/dist/components/Checkbox/index.d.ts +3 -0
- package/dist/components/Checkbox/index.d.ts.map +1 -0
- package/dist/components/Checkbox/index.js +10 -0
- package/dist/components/Checkbox/index.js.map +1 -0
- package/dist/components/Chip/chip.d.ts +13 -7
- package/dist/components/Chip/chip.d.ts.map +1 -1
- package/dist/components/Chip/chip.js +9 -4
- package/dist/components/Chip/chip.js.map +1 -1
- package/dist/components/Chip/index.d.ts +2 -0
- package/dist/components/Chip/index.d.ts.map +1 -0
- package/dist/components/Chip/index.js +8 -0
- package/dist/components/Chip/index.js.map +1 -0
- package/dist/components/CircularProgress/circular-progress.d.ts +2 -3
- package/dist/components/CircularProgress/circular-progress.d.ts.map +1 -1
- package/dist/components/CircularProgress/circular-progress.js +4 -3
- package/dist/components/CircularProgress/circular-progress.js.map +1 -1
- package/dist/components/CircularProgress/index.d.ts +2 -0
- package/dist/components/CircularProgress/index.d.ts.map +1 -0
- package/dist/components/CircularProgress/index.js +6 -0
- package/dist/components/CircularProgress/index.js.map +1 -0
- package/dist/components/Coachmark/coachmark-story-helpers.d.ts +22 -0
- package/dist/components/Coachmark/coachmark-story-helpers.d.ts.map +1 -0
- package/dist/components/Coachmark/coachmark.d.ts +6 -4
- package/dist/components/Coachmark/coachmark.d.ts.map +1 -1
- package/dist/components/Coachmark/coachmark.js +13 -5
- package/dist/components/Coachmark/coachmark.js.map +1 -1
- package/dist/components/Coachmark/index.d.ts +2 -0
- package/dist/components/Coachmark/index.d.ts.map +1 -0
- package/dist/components/Coachmark/index.js +6 -0
- package/dist/components/Coachmark/index.js.map +1 -0
- package/dist/components/Combobox/combobox.d.ts +18 -7
- package/dist/components/Combobox/combobox.d.ts.map +1 -1
- package/dist/components/Combobox/combobox.js +81 -45
- package/dist/components/Combobox/combobox.js.map +1 -1
- package/dist/components/Combobox/index.d.ts +2 -0
- package/dist/components/Combobox/index.d.ts.map +1 -0
- package/dist/components/Combobox/index.js +6 -0
- package/dist/components/Combobox/index.js.map +1 -0
- package/dist/components/Command/command.d.ts +6 -2
- package/dist/components/Command/command.d.ts.map +1 -1
- package/dist/components/Command/command.js +8 -7
- package/dist/components/Command/command.js.map +1 -1
- package/dist/components/Command/index.d.ts +2 -0
- package/dist/components/Command/index.d.ts.map +1 -0
- package/dist/components/Command/index.js +14 -0
- package/dist/components/Command/index.js.map +1 -0
- package/dist/components/DataTable/active-editor-controller.d.ts +4 -3
- package/dist/components/DataTable/active-editor-controller.d.ts.map +1 -1
- package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
- package/dist/components/DataTable/cell-registry.js +9 -5
- package/dist/components/DataTable/cell-registry.js.map +1 -1
- package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-interaction-layer.d.ts +4 -3
- package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
- package/dist/components/DataTable/data-table.d.ts +37 -13
- package/dist/components/DataTable/data-table.d.ts.map +1 -1
- package/dist/components/DataTable/data-table.js +211 -89
- package/dist/components/DataTable/data-table.js.map +1 -1
- package/dist/components/DataTable/filter-operators.d.ts +1 -1
- package/dist/components/DataTable/filter-tree.d.ts +6 -1
- package/dist/components/DataTable/filter-tree.d.ts.map +1 -1
- package/dist/components/DataTable/index.d.ts +2 -0
- package/dist/components/DataTable/index.d.ts.map +1 -0
- package/dist/components/DataTable/index.js +8 -0
- package/dist/components/DataTable/index.js.map +1 -0
- package/dist/components/DateGrid/date-grid.d.ts +22 -18
- package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
- package/dist/components/DateGrid/date-grid.js +8 -6
- package/dist/components/DateGrid/date-grid.js.map +1 -1
- package/dist/components/DateGrid/index.d.ts +2 -0
- package/dist/components/DateGrid/index.d.ts.map +1 -0
- package/dist/components/DateGrid/index.js +6 -0
- package/dist/components/DateGrid/index.js.map +1 -0
- package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
- package/dist/components/DatePicker/date-picker.js +153 -124
- package/dist/components/DatePicker/date-picker.js.map +1 -1
- package/dist/components/DatePicker/index.d.ts +2 -0
- package/dist/components/DatePicker/index.d.ts.map +1 -0
- package/dist/components/DatePicker/index.js +8 -0
- package/dist/components/DatePicker/index.js.map +1 -0
- package/dist/components/DescriptionList/description-list.d.ts +3 -3
- package/dist/components/DescriptionList/description-list.js +4 -3
- package/dist/components/DescriptionList/description-list.js.map +1 -1
- package/dist/components/DescriptionList/index.d.ts +2 -0
- package/dist/components/DescriptionList/index.d.ts.map +1 -0
- package/dist/components/DescriptionList/index.js +7 -0
- package/dist/components/DescriptionList/index.js.map +1 -0
- package/dist/components/Dialog/dialog.d.ts +1 -1
- package/dist/components/Dialog/dialog.d.ts.map +1 -1
- package/dist/components/Dialog/dialog.js +2 -1
- package/dist/components/Dialog/dialog.js.map +1 -1
- package/dist/components/Dialog/index.d.ts +2 -0
- package/dist/components/Dialog/index.d.ts.map +1 -0
- package/dist/components/Dialog/index.js +16 -0
- package/dist/components/Dialog/index.js.map +1 -0
- package/dist/components/DropdownMenu/dropdown-menu.d.ts +4 -3
- package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.js +13 -7
- package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
- package/dist/components/DropdownMenu/index.d.ts +2 -0
- package/dist/components/DropdownMenu/index.d.ts.map +1 -0
- package/dist/components/DropdownMenu/index.js +21 -0
- package/dist/components/DropdownMenu/index.js.map +1 -0
- package/dist/components/Empty/empty.d.ts +11 -3
- package/dist/components/Empty/empty.d.ts.map +1 -1
- package/dist/components/Empty/empty.js +6 -6
- package/dist/components/Empty/empty.js.map +1 -1
- package/dist/components/Empty/index.d.ts +2 -0
- package/dist/components/Empty/index.d.ts.map +1 -0
- package/dist/components/Empty/index.js +6 -0
- package/dist/components/Empty/index.js.map +1 -0
- package/dist/components/Field/field-context.d.ts +49 -0
- package/dist/components/Field/field-context.d.ts.map +1 -1
- package/dist/components/Field/field-context.js +42 -0
- package/dist/components/Field/field-context.js.map +1 -1
- package/dist/components/Field/field-types.js.map +1 -1
- package/dist/components/Field/field-wrapper.d.ts +1 -0
- package/dist/components/Field/field-wrapper.d.ts.map +1 -1
- package/dist/components/Field/field-wrapper.js +32 -12
- package/dist/components/Field/field-wrapper.js.map +1 -1
- package/dist/components/Field/field.d.ts +4 -2
- package/dist/components/Field/field.d.ts.map +1 -1
- package/dist/components/Field/field.js +1 -0
- package/dist/components/Field/field.js.map +1 -1
- package/dist/components/Field/index.d.ts +2 -0
- package/dist/components/Field/index.d.ts.map +1 -0
- package/dist/components/Field/index.js +12 -0
- package/dist/components/Field/index.js.map +1 -0
- package/dist/components/Field/use-form-validation.d.ts +92 -0
- package/dist/components/Field/use-form-validation.d.ts.map +1 -0
- package/dist/components/Field/use-form-validation.js +139 -0
- package/dist/components/Field/use-form-validation.js.map +1 -0
- package/dist/components/FieldControlGroup/field-control-group.d.ts +8 -8
- package/dist/components/FieldControlGroup/field-control-group.d.ts.map +1 -1
- package/dist/components/FieldControlGroup/field-control-group.js +1 -1
- package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
- package/dist/components/FieldControlGroup/index.d.ts +2 -0
- package/dist/components/FieldControlGroup/index.d.ts.map +1 -0
- package/dist/components/FieldControlGroup/index.js +6 -0
- package/dist/components/FieldControlGroup/index.js.map +1 -0
- package/dist/components/FileItem/file-item.d.ts +12 -2
- package/dist/components/FileItem/file-item.d.ts.map +1 -1
- package/dist/components/FileItem/file-item.js +23 -8
- package/dist/components/FileItem/file-item.js.map +1 -1
- package/dist/components/FileItem/index.d.ts +2 -0
- package/dist/components/FileItem/index.d.ts.map +1 -0
- package/dist/components/FileItem/index.js +6 -0
- package/dist/components/FileItem/index.js.map +1 -0
- package/dist/components/FileUpload/file-upload.d.ts +32 -13
- package/dist/components/FileUpload/file-upload.d.ts.map +1 -1
- package/dist/components/FileUpload/file-upload.js +72 -22
- package/dist/components/FileUpload/file-upload.js.map +1 -1
- package/dist/components/FileUpload/index.d.ts +2 -0
- package/dist/components/FileUpload/index.d.ts.map +1 -0
- package/dist/components/FileUpload/index.js +6 -0
- package/dist/components/FileUpload/index.js.map +1 -0
- package/dist/components/FileViewer/file-viewer.d.ts +2 -2
- package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
- package/dist/components/FileViewer/file-viewer.js +32 -22
- package/dist/components/FileViewer/file-viewer.js.map +1 -1
- package/dist/components/FileViewer/index.d.ts +2 -0
- package/dist/components/FileViewer/index.d.ts.map +1 -0
- package/dist/components/FileViewer/index.js +7 -0
- package/dist/components/FileViewer/index.js.map +1 -0
- package/dist/components/HoverCard/hover-card.d.ts +7 -3
- package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
- package/dist/components/HoverCard/hover-card.js +4 -3
- package/dist/components/HoverCard/hover-card.js.map +1 -1
- package/dist/components/HoverCard/index.d.ts +2 -0
- package/dist/components/HoverCard/index.d.ts.map +1 -0
- package/dist/components/HoverCard/index.js +8 -0
- package/dist/components/HoverCard/index.js.map +1 -0
- package/dist/components/Input/index.d.ts +2 -0
- package/dist/components/Input/index.d.ts.map +1 -0
- package/dist/components/Input/index.js +6 -0
- package/dist/components/Input/index.js.map +1 -0
- package/dist/components/Input/input.d.ts +5 -2
- package/dist/components/Input/input.d.ts.map +1 -1
- package/dist/components/Input/input.js +11 -13
- package/dist/components/Input/input.js.map +1 -1
- package/dist/components/LinkInput/index.d.ts +2 -0
- package/dist/components/LinkInput/index.d.ts.map +1 -0
- package/dist/components/LinkInput/index.js +6 -0
- package/dist/components/LinkInput/index.js.map +1 -0
- 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 +36 -35
- package/dist/components/LinkInput/link-input.js.map +1 -1
- package/dist/components/Menu/index.d.ts +2 -0
- package/dist/components/Menu/index.d.ts.map +1 -0
- package/dist/components/Menu/index.js +9 -0
- package/dist/components/Menu/index.js.map +1 -0
- package/dist/components/Menu/menu-item.d.ts +6 -2
- package/dist/components/Menu/menu-item.d.ts.map +1 -1
- package/dist/components/Menu/menu-item.js +3 -2
- package/dist/components/Menu/menu-item.js.map +1 -1
- package/dist/components/Notice/index.d.ts +2 -0
- package/dist/components/Notice/index.d.ts.map +1 -0
- package/dist/components/Notice/index.js +8 -0
- package/dist/components/Notice/index.js.map +1 -0
- package/dist/components/Notice/notice.d.ts +18 -6
- package/dist/components/Notice/notice.d.ts.map +1 -1
- package/dist/components/Notice/notice.js +25 -9
- package/dist/components/Notice/notice.js.map +1 -1
- package/dist/components/NumberInput/index.d.ts +2 -0
- package/dist/components/NumberInput/index.d.ts.map +1 -0
- package/dist/components/NumberInput/index.js +7 -0
- package/dist/components/NumberInput/index.js.map +1 -0
- package/dist/components/NumberInput/number-input.d.ts.map +1 -1
- package/dist/components/NumberInput/number-input.js +23 -14
- package/dist/components/NumberInput/number-input.js.map +1 -1
- package/dist/components/OverflowIndicator/index.d.ts +2 -0
- package/dist/components/OverflowIndicator/index.d.ts.map +1 -0
- package/dist/components/OverflowIndicator/index.js +6 -0
- package/dist/components/OverflowIndicator/index.js.map +1 -0
- package/dist/components/OverflowIndicator/overflow-indicator.d.ts +6 -2
- package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
- package/dist/components/OverflowIndicator/overflow-indicator.js +15 -7
- package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
- package/dist/components/PeoplePicker/index.d.ts +2 -0
- package/dist/components/PeoplePicker/index.d.ts.map +1 -0
- package/dist/components/PeoplePicker/index.js +9 -0
- package/dist/components/PeoplePicker/index.js.map +1 -0
- package/dist/components/PeoplePicker/people-picker-helpers.d.ts.map +1 -1
- package/dist/components/PeoplePicker/people-picker-helpers.js +2 -2
- package/dist/components/PeoplePicker/people-picker-helpers.js.map +1 -1
- package/dist/components/PeoplePicker/people-picker.d.ts +2 -2
- package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
- package/dist/components/PeoplePicker/people-picker.js +56 -51
- package/dist/components/PeoplePicker/people-picker.js.map +1 -1
- package/dist/components/PeoplePicker/person-display.d.ts +7 -7
- package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
- package/dist/components/PeoplePicker/person-display.js +11 -11
- package/dist/components/PeoplePicker/person-display.js.map +1 -1
- package/dist/components/Popover/index.d.ts +2 -0
- package/dist/components/Popover/index.d.ts.map +1 -0
- package/dist/components/Popover/index.js +14 -0
- package/dist/components/Popover/index.js.map +1 -0
- package/dist/components/Popover/popover.d.ts +2 -2
- package/dist/components/Popover/popover.d.ts.map +1 -1
- package/dist/components/Popover/popover.js +12 -12
- package/dist/components/Popover/popover.js.map +1 -1
- package/dist/components/ProfileCard/index.d.ts +2 -0
- package/dist/components/ProfileCard/index.d.ts.map +1 -0
- package/dist/components/ProfileCard/index.js +8 -0
- package/dist/components/ProfileCard/index.js.map +1 -0
- package/dist/components/{NameCard/name-card.d.ts → ProfileCard/profile-card.d.ts} +29 -20
- package/dist/components/ProfileCard/profile-card.d.ts.map +1 -0
- package/dist/components/{NameCard/name-card.js → ProfileCard/profile-card.js} +11 -10
- package/dist/components/ProfileCard/profile-card.js.map +1 -0
- package/dist/components/ProgressBar/index.d.ts +2 -0
- package/dist/components/ProgressBar/index.d.ts.map +1 -0
- package/dist/components/ProgressBar/index.js +6 -0
- package/dist/components/ProgressBar/index.js.map +1 -0
- package/dist/components/ProgressBar/progress-bar.d.ts +2 -2
- package/dist/components/ProgressBar/progress-bar.js +3 -3
- package/dist/components/ProgressBar/progress-bar.js.map +1 -1
- package/dist/components/RadioGroup/index.d.ts +2 -0
- package/dist/components/RadioGroup/index.d.ts.map +1 -0
- package/dist/components/RadioGroup/index.js +8 -0
- package/dist/components/RadioGroup/index.js.map +1 -0
- package/dist/components/RadioGroup/radio-group.d.ts +16 -10
- package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
- package/dist/components/RadioGroup/radio-group.js +97 -35
- package/dist/components/RadioGroup/radio-group.js.map +1 -1
- package/dist/components/Rating/index.d.ts +2 -0
- package/dist/components/Rating/index.d.ts.map +1 -0
- package/dist/components/Rating/index.js +6 -0
- package/dist/components/Rating/index.js.map +1 -0
- package/dist/components/Rating/rating.d.ts +6 -2
- package/dist/components/Rating/rating.d.ts.map +1 -1
- package/dist/components/Rating/rating.js +13 -10
- package/dist/components/Rating/rating.js.map +1 -1
- package/dist/components/ScrollArea/index.d.ts +2 -0
- package/dist/components/ScrollArea/index.d.ts.map +1 -0
- package/dist/components/ScrollArea/index.js +7 -0
- package/dist/components/ScrollArea/index.js.map +1 -0
- package/dist/components/ScrollArea/scroll-area.d.ts +2 -2
- package/dist/components/ScrollArea/scroll-area.js +4 -4
- package/dist/components/ScrollArea/scroll-area.js.map +1 -1
- package/dist/components/SegmentedControl/index.d.ts +2 -0
- package/dist/components/SegmentedControl/index.d.ts.map +1 -0
- package/dist/components/SegmentedControl/index.js +9 -0
- package/dist/components/SegmentedControl/index.js.map +1 -0
- package/dist/components/SegmentedControl/segmented-control.d.ts +4 -4
- package/dist/components/SegmentedControl/segmented-control.d.ts.map +1 -1
- package/dist/components/SegmentedControl/segmented-control.js +18 -15
- package/dist/components/SegmentedControl/segmented-control.js.map +1 -1
- package/dist/components/Select/index.d.ts +2 -0
- package/dist/components/Select/index.d.ts.map +1 -0
- package/dist/components/Select/index.js +6 -0
- package/dist/components/Select/index.js.map +1 -0
- package/dist/components/Select/select.d.ts +9 -3
- package/dist/components/Select/select.d.ts.map +1 -1
- package/dist/components/Select/select.js +73 -29
- package/dist/components/Select/select.js.map +1 -1
- package/dist/components/SelectMenu/index.d.ts +2 -0
- package/dist/components/SelectMenu/index.d.ts.map +1 -0
- package/dist/components/SelectMenu/index.js +7 -0
- package/dist/components/SelectMenu/index.js.map +1 -0
- package/dist/components/SelectMenu/select-menu.d.ts +24 -6
- package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
- package/dist/components/SelectMenu/select-menu.js +51 -10
- package/dist/components/SelectMenu/select-menu.js.map +1 -1
- package/dist/components/SelectionControl/index.d.ts +2 -0
- package/dist/components/SelectionControl/index.d.ts.map +1 -0
- package/dist/components/SelectionControl/index.js +7 -0
- package/dist/components/SelectionControl/index.js.map +1 -0
- package/dist/components/SelectionControl/selection-item.d.ts +5 -1
- package/dist/components/SelectionControl/selection-item.d.ts.map +1 -1
- package/dist/components/SelectionControl/selection-item.js +3 -1
- package/dist/components/SelectionControl/selection-item.js.map +1 -1
- package/dist/components/Separator/index.d.ts +2 -0
- package/dist/components/Separator/index.d.ts.map +1 -0
- package/dist/components/Separator/index.js +6 -0
- package/dist/components/Separator/index.js.map +1 -0
- package/dist/components/Separator/separator.d.ts +2 -2
- package/dist/components/Separator/separator.js +4 -3
- package/dist/components/Separator/separator.js.map +1 -1
- package/dist/components/Sheet/index.d.ts +2 -0
- package/dist/components/Sheet/index.d.ts.map +1 -0
- package/dist/components/Sheet/index.js +17 -0
- package/dist/components/Sheet/index.js.map +1 -0
- package/dist/components/Sheet/sheet.d.ts +7 -6
- package/dist/components/Sheet/sheet.d.ts.map +1 -1
- package/dist/components/Sheet/sheet.js +3 -2
- package/dist/components/Sheet/sheet.js.map +1 -1
- package/dist/components/Sidebar/index.d.ts +2 -0
- package/dist/components/Sidebar/index.d.ts.map +1 -0
- package/dist/components/Sidebar/index.js +24 -0
- package/dist/components/Sidebar/index.js.map +1 -0
- package/dist/components/Sidebar/sidebar.d.ts +2 -2
- package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
- package/dist/components/Sidebar/sidebar.js +32 -13
- package/dist/components/Sidebar/sidebar.js.map +1 -1
- package/dist/components/Skeleton/index.d.ts +2 -0
- package/dist/components/Skeleton/index.d.ts.map +1 -0
- package/dist/components/Skeleton/index.js +6 -0
- package/dist/components/Skeleton/index.js.map +1 -0
- package/dist/components/Skeleton/skeleton.d.ts +2 -2
- package/dist/components/Skeleton/skeleton.js +4 -3
- package/dist/components/Skeleton/skeleton.js.map +1 -1
- package/dist/components/Slider/index.d.ts +2 -0
- package/dist/components/Slider/index.d.ts.map +1 -0
- package/dist/components/Slider/index.js +7 -0
- package/dist/components/Slider/index.js.map +1 -0
- package/dist/components/Slider/slider.d.ts +6 -6
- package/dist/components/Slider/slider.d.ts.map +1 -1
- package/dist/components/Slider/slider.js +25 -10
- package/dist/components/Slider/slider.js.map +1 -1
- package/dist/components/Steps/index.d.ts +2 -0
- package/dist/components/Steps/index.d.ts.map +1 -0
- package/dist/components/Steps/index.js +12 -0
- package/dist/components/Steps/index.js.map +1 -0
- package/dist/components/Steps/steps.d.ts +2 -2
- package/dist/components/Steps/steps.d.ts.map +1 -1
- package/dist/components/Steps/steps.js +54 -26
- package/dist/components/Steps/steps.js.map +1 -1
- package/dist/components/Switch/index.d.ts +2 -0
- package/dist/components/Switch/index.d.ts.map +1 -0
- package/dist/components/Switch/index.js +7 -0
- package/dist/components/Switch/index.js.map +1 -0
- package/dist/components/Switch/switch.d.ts +18 -16
- package/dist/components/Switch/switch.d.ts.map +1 -1
- package/dist/components/Switch/switch.js +81 -22
- package/dist/components/Switch/switch.js.map +1 -1
- package/dist/components/Tabs/index.d.ts +2 -0
- package/dist/components/Tabs/index.d.ts.map +1 -0
- package/dist/components/Tabs/index.js +10 -0
- package/dist/components/Tabs/index.js.map +1 -0
- package/dist/components/Tabs/tabs.d.ts +10 -7
- package/dist/components/Tabs/tabs.d.ts.map +1 -1
- package/dist/components/Tabs/tabs.js +30 -31
- package/dist/components/Tabs/tabs.js.map +1 -1
- package/dist/components/Tag/index.d.ts +2 -0
- package/dist/components/Tag/index.d.ts.map +1 -0
- package/dist/components/Tag/index.js +7 -0
- package/dist/components/Tag/index.js.map +1 -0
- package/dist/components/Tag/tag.d.ts +37 -23
- package/dist/components/Tag/tag.d.ts.map +1 -1
- package/dist/components/Tag/tag.js +43 -44
- package/dist/components/Tag/tag.js.map +1 -1
- package/dist/components/Textarea/index.d.ts +2 -0
- package/dist/components/Textarea/index.d.ts.map +1 -0
- package/dist/components/Textarea/index.js +7 -0
- package/dist/components/Textarea/index.js.map +1 -0
- package/dist/components/Textarea/textarea.d.ts +7 -11
- package/dist/components/Textarea/textarea.d.ts.map +1 -1
- package/dist/components/Textarea/textarea.js +34 -24
- package/dist/components/Textarea/textarea.js.map +1 -1
- package/dist/components/TimePicker/index.d.ts +2 -0
- package/dist/components/TimePicker/index.d.ts.map +1 -0
- package/dist/components/TimePicker/index.js +6 -0
- package/dist/components/TimePicker/index.js.map +1 -0
- package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
- package/dist/components/TimePicker/time-columns.js +4 -1
- package/dist/components/TimePicker/time-columns.js.map +1 -1
- package/dist/components/TimePicker/time-picker.d.ts +4 -3
- package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
- package/dist/components/TimePicker/time-picker.js +38 -39
- package/dist/components/TimePicker/time-picker.js.map +1 -1
- package/dist/components/Toast/index.d.ts +2 -0
- package/dist/components/Toast/index.d.ts.map +1 -0
- package/dist/components/Toast/index.js +7 -0
- package/dist/components/Toast/index.js.map +1 -0
- package/dist/components/Toast/toast.d.ts +2 -2
- package/dist/components/Toast/toast.d.ts.map +1 -1
- package/dist/components/Toast/toast.js +5 -4
- package/dist/components/Toast/toast.js.map +1 -1
- package/dist/components/Tooltip/index.d.ts +2 -0
- package/dist/components/Tooltip/index.d.ts.map +1 -0
- package/dist/components/Tooltip/index.js +9 -0
- package/dist/components/Tooltip/index.js.map +1 -0
- package/dist/components/Tooltip/tooltip.d.ts +1 -1
- package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
- package/dist/components/Tooltip/tooltip.js +3 -2
- package/dist/components/Tooltip/tooltip.js.map +1 -1
- package/dist/components/TreeView/index.d.ts +2 -0
- package/dist/components/TreeView/index.d.ts.map +1 -0
- package/dist/components/TreeView/index.js +8 -0
- package/dist/components/TreeView/index.js.map +1 -0
- package/dist/components/TreeView/tree-view.d.ts +11 -11
- package/dist/components/TreeView/tree-view.d.ts.map +1 -1
- package/dist/components/TreeView/tree-view.js +38 -10
- package/dist/components/TreeView/tree-view.js.map +1 -1
- package/dist/hooks/use-overflow-items.d.ts +10 -6
- package/dist/hooks/use-overflow-items.d.ts.map +1 -1
- package/dist/hooks/use-overflow-items.js.map +1 -1
- package/dist/index.d.ts +58 -67
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +38 -57
- package/dist/index.js.map +1 -1
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +3 -1
- package/dist/lib/utils.js.map +1 -1
- package/dist/patterns/element-anatomy/index.d.ts +2 -0
- package/dist/patterns/element-anatomy/index.d.ts.map +1 -0
- package/dist/patterns/element-anatomy/index.js +20 -0
- package/dist/patterns/element-anatomy/index.js.map +1 -0
- package/dist/patterns/element-anatomy/item-anatomy.d.ts +10 -6
- package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.js +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
- package/dist/patterns/header-canonical/chrome-header.d.ts +13 -4
- package/dist/patterns/header-canonical/chrome-header.d.ts.map +1 -1
- package/dist/patterns/header-canonical/chrome-header.js +4 -2
- package/dist/patterns/header-canonical/chrome-header.js.map +1 -1
- package/dist/patterns/header-canonical/index.d.ts +2 -0
- package/dist/patterns/header-canonical/index.d.ts.map +1 -0
- package/dist/patterns/header-canonical/index.js +6 -0
- package/dist/patterns/header-canonical/index.js.map +1 -0
- package/dist/patterns/horizontal-overflow/index.d.ts +2 -0
- package/dist/patterns/horizontal-overflow/index.d.ts.map +1 -0
- package/dist/patterns/horizontal-overflow/index.js +14 -0
- package/dist/patterns/horizontal-overflow/index.js.map +1 -0
- package/dist/patterns/overlay-surface/index.d.ts +2 -0
- package/dist/patterns/overlay-surface/index.d.ts.map +1 -0
- package/dist/patterns/overlay-surface/index.js +8 -0
- package/dist/patterns/overlay-surface/index.js.map +1 -0
- package/dist/patterns/overlay-surface/overlay-surface.d.ts +11 -2
- package/dist/patterns/overlay-surface/overlay-surface.d.ts.map +1 -1
- package/dist/patterns/overlay-surface/overlay-surface.js +5 -2
- package/dist/patterns/overlay-surface/overlay-surface.js.map +1 -1
- package/dist/patterns/resize-handle/index.d.ts +2 -0
- package/dist/patterns/resize-handle/index.d.ts.map +1 -0
- package/dist/patterns/resize-handle/index.js +5 -0
- package/dist/patterns/resize-handle/index.js.map +1 -0
- package/dist/story-governance/category-matrix.d.ts +35 -0
- package/dist/story-governance/category-matrix.d.ts.map +1 -0
- package/dist/tokens/categorical-color.d.ts +60 -0
- package/dist/tokens/categorical-color.d.ts.map +1 -0
- package/dist/tokens/categorical-color.js +110 -0
- package/dist/tokens/categorical-color.js.map +1 -0
- package/dist/tokens/motion/motion.d.ts +1 -1
- package/dist/tokens/motion/motion.d.ts.map +1 -1
- package/dist/tokens/motion/motion.js.map +1 -1
- package/dist/tokens/uiSize/icon-size.d.ts +3 -4
- package/dist/tokens/uiSize/icon-size.d.ts.map +1 -1
- package/ds-canonical/commands/README.md +26 -0
- package/ds-canonical/commands/gov-status.md +79 -0
- package/ds-canonical/fork/governance.lock +222 -0
- package/ds-canonical/fork/hooks/block_prototype_imports.py +111 -0
- package/ds-canonical/fork/hooks/check_chrome_header_avatar_canonical.sh +95 -0
- package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +349 -0
- package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +132 -0
- package/ds-canonical/fork/hooks/check_escape_marker_abuse.sh +140 -0
- package/ds-canonical/fork/hooks/check_field_family_invariants.sh +250 -0
- package/ds-canonical/fork/hooks/check_fork_product_quality.sh +36 -0
- package/ds-canonical/fork/hooks/check_item_list_gap.sh +54 -0
- package/ds-canonical/fork/hooks/check_layout_space_magic_numbers.sh +96 -0
- package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +158 -0
- package/ds-canonical/fork/hooks/check_pattern_invariants.sh +196 -0
- package/ds-canonical/fork/hooks/check_sidebar_menu_button_implicit_wrap.sh +86 -0
- package/ds-canonical/fork/hooks/check_tabs_content_chrome_body_double_gap.sh +183 -0
- package/ds-canonical/fork/hooks/check_tailwind_wildcard_in_docs.sh +79 -0
- package/ds-canonical/fork/hooks/inject_deploy_url_after_push.sh +238 -0
- package/ds-canonical/fork/launchers/fork-governance-dispatcher.sh +44 -0
- package/ds-canonical/fork/launchers/inject_fork_governance_preamble.sh +54 -0
- package/ds-canonical/fork/launchers/settings-hooks.json +58 -0
- package/ds-canonical/fork/manifest.json +98 -0
- package/ds-canonical/fork/preamble.md +495 -0
- package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +183 -0
- package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +65 -0
- package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +229 -0
- package/ds-canonical/fork/skills/delivery-handoff/references/flow-diagram.md +180 -0
- package/ds-canonical/fork/skills/delivery-handoff/references/handoff-template.md +177 -0
- package/ds-canonical/fork/skills/delivery-handoff/references/inventory-checklist.md +196 -0
- package/ds-canonical/fork/skills/performance-audit/SKILL.md +107 -0
- package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +232 -0
- package/ds-canonical/fork/skills/product-ui-audit/references/audit-checks.md +246 -0
- package/ds-canonical/fork/skills/product-ui-audit/references/common-misuses.md +329 -0
- package/ds-canonical/fork/skills/product-ui-audit/references/report-template.md +159 -0
- package/ds-canonical/fork/skills/propose-options/SKILL.md +177 -0
- package/ds-canonical/fork/skills/prototype/SKILL.md +244 -0
- package/ds-canonical/fork/skills/prototype/references/audit-checks.md +38 -0
- package/ds-canonical/fork/skills/prototype/references/benchmark-sources.md +94 -0
- package/ds-canonical/fork/skills/prototype/references/checkpoints.md +191 -0
- package/ds-canonical/fork/skills/prototype/references/evaluation-matrix.md +141 -0
- package/ds-canonical/fork/skills/prototype/references/ooux-template.md +198 -0
- package/ds-canonical/fork/skills/prototype/references/proposal-template.md +229 -0
- package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +200 -0
- package/ds-canonical/fork/skills/ux-audit/SKILL.md +130 -0
- package/ds-canonical/fork/skills/visual-audit/SKILL.md +247 -0
- package/ds-canonical/fork/skills/visual-audit/output/.gitkeep +0 -0
- package/ds-canonical/fork/skills/visual-audit/references/audit-architecture.md +101 -0
- package/ds-canonical/fork/skills/visual-audit/references/visual-checklist.md +297 -0
- package/ds-canonical/fork/skills/visual-audit/references/world-class-benchmarks.md +198 -0
- package/ds-canonical/hooks/README.md +145 -0
- package/ds-canonical/hooks/_log-fire.sh +46 -0
- package/ds-canonical/hooks/auto_regen_ds_barrel.sh +58 -0
- package/ds-canonical/hooks/block_prototype_imports.py +111 -0
- package/ds-canonical/hooks/check_audit_post_report_validator.sh +169 -0
- package/ds-canonical/hooks/check_audit_sample_escape.sh +76 -0
- package/ds-canonical/hooks/check_benchmark_citation.sh +106 -0
- package/ds-canonical/hooks/check_canonical_propagation.sh +189 -0
- package/ds-canonical/hooks/check_chrome_header_avatar_canonical.sh +95 -0
- package/ds-canonical/hooks/check_codex_brief_invariants.sh +115 -0
- package/ds-canonical/hooks/check_codex_collab_5step.sh +108 -0
- package/ds-canonical/hooks/check_consumer_app_invariants.sh +349 -0
- package/ds-canonical/hooks/check_datatable_invariants.sh +180 -0
- package/ds-canonical/hooks/check_dim_count_drift.sh +72 -0
- package/ds-canonical/hooks/check_ds_anchor_preflight.sh +132 -0
- package/ds-canonical/hooks/check_escape_marker_abuse.sh +140 -0
- package/ds-canonical/hooks/check_field_controls_contracts.sh +137 -0
- package/ds-canonical/hooks/check_field_family_invariants.sh +250 -0
- package/ds-canonical/hooks/check_file_size_budget.sh +60 -0
- package/ds-canonical/hooks/check_full_story_visual_interaction_sweep.sh +72 -0
- package/ds-canonical/hooks/check_item_list_gap.sh +54 -0
- package/ds-canonical/hooks/check_layout_space_magic_numbers.sh +96 -0
- package/ds-canonical/hooks/check_main_branch_workbench.sh +93 -0
- package/ds-canonical/hooks/check_naming_and_abstraction.sh +165 -0
- package/ds-canonical/hooks/check_opacity_token_usage.sh +158 -0
- package/ds-canonical/hooks/check_orphan_ds_css.sh +66 -0
- package/ds-canonical/hooks/check_overlay_open_focus_escape_probe.sh +75 -0
- package/ds-canonical/hooks/check_pattern_invariants.sh +196 -0
- package/ds-canonical/hooks/check_peoplepicker_ssot_drift.sh +56 -0
- package/ds-canonical/hooks/check_pixel_quantified_audit.sh +53 -0
- package/ds-canonical/hooks/check_plugin_fork_health.sh +145 -0
- package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +90 -0
- package/ds-canonical/hooks/check_propose_discipline.sh +147 -0
- package/ds-canonical/hooks/check_propose_pre_grep_verify.sh +70 -0
- package/ds-canonical/hooks/check_propose_without_benchmark.sh +63 -0
- package/ds-canonical/hooks/check_select_all_canonical.sh +58 -0
- package/ds-canonical/hooks/check_sidebar_menu_button_implicit_wrap.sh +86 -0
- package/ds-canonical/hooks/check_solo_workflow.sh +317 -0
- package/ds-canonical/hooks/check_spec_class_drift.sh +88 -0
- package/ds-canonical/hooks/check_story_invariants.sh +760 -0
- package/ds-canonical/hooks/check_storybook_addon_packaging.sh +151 -0
- package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +113 -0
- package/ds-canonical/hooks/check_tabs_content_chrome_body_double_gap.sh +183 -0
- package/ds-canonical/hooks/check_tailwind_wildcard_in_docs.sh +79 -0
- package/ds-canonical/hooks/check_wrapper_primitive_schema_drift.sh +104 -0
- package/ds-canonical/hooks/chrome_header_dispatcher.sh +56 -0
- package/ds-canonical/hooks/enforce_home_charter.sh +44 -0
- package/ds-canonical/hooks/inject_deploy_url_after_push.sh +238 -0
- package/ds-canonical/hooks/inject_pending_self_audit.sh +248 -0
- package/ds-canonical/hooks/lib/_app_shell_primary_header_consistency.sh +100 -0
- package/ds-canonical/hooks/lib/_approval_re.sh +33 -0
- package/ds-canonical/hooks/lib/_chrome_header_handcraft.sh +75 -0
- package/ds-canonical/hooks/lib/_code_quality.sh +73 -0
- package/ds-canonical/hooks/lib/_cva_default_sync.sh +69 -0
- package/ds-canonical/hooks/lib/_governance_coverage_check.sh +49 -0
- package/ds-canonical/hooks/lib/_hardcoded_strings.sh +163 -0
- package/ds-canonical/hooks/lib/_header_with_tabs_border.sh +87 -0
- package/ds-canonical/hooks/lib/_layout_space_canonical.sh +56 -0
- package/ds-canonical/hooks/lib/_overlay_handcraft.sh +162 -0
- package/ds-canonical/hooks/lib/_person_data_richness.sh +42 -0
- package/ds-canonical/hooks/lib/_story_compile_drift.sh +48 -0
- package/ds-canonical/hooks/lib/_tab_lg_chrome_header_equal.sh +70 -0
- package/ds-canonical/hooks/lib/_token_hygiene.sh +104 -0
- package/ds-canonical/hooks/log_governance_fires.sh +50 -0
- package/ds-canonical/hooks/log_skill_invokes.sh +41 -0
- package/ds-canonical/hooks/post_edit_dispatcher.sh +62 -0
- package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_addon_subdir_ship.sh +76 -0
- package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_consumer_app_story_title.sh +81 -0
- package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_consumer_ds_primitive_misuse.sh +120 -0
- package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_consumer_no_ds_catalog.sh +101 -0
- package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_consumer_story_baseline.sh +76 -0
- package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_data_table_size_num_to_meta_width.sh +68 -0
- package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_fork_user_plugin_install.sh +79 -0
- package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_plugin_freshness.sh +68 -0
- package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_propose_cite_required.sh +88 -0
- package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_propose_plain_chinese.sh +74 -0
- package/ds-canonical/hooks/retired/2026-06-11-prune-merge/check_storybook_addon_preset_cjs.sh +87 -0
- package/ds-canonical/hooks/retired/check_anatomy_section_numbering.sh +106 -0
- package/ds-canonical/hooks/retired/check_avatar_hovercard.sh +90 -0
- package/ds-canonical/hooks/retired/check_button_icon_literal.sh.retired-2026-04-28 +38 -0
- package/ds-canonical/hooks/retired/check_container_breathing.sh +142 -0
- package/ds-canonical/hooks/retired/check_governance_compliance.sh +61 -0
- package/ds-canonical/hooks/retired/check_icon_only_padding_formula.sh +104 -0
- package/ds-canonical/hooks/retired/check_item_content_primitive.sh +150 -0
- package/ds-canonical/hooks/retired/check_item_list_gap.sh +153 -0
- package/ds-canonical/hooks/retired/check_sideoffset_canonical.sh +65 -0
- package/ds-canonical/hooks/retired/check_spec_iteration_tag.sh +87 -0
- package/ds-canonical/hooks/retired/check_ssot_consultation.sh +88 -0
- package/ds-canonical/hooks/retired/check_sync_update.sh +20 -0
- package/ds-canonical/hooks/retired/check_third_party_dom_verified.sh +95 -0
- package/ds-canonical/hooks/retired/enforce_home_charter.sh +125 -0
- package/ds-canonical/hooks/retired/post_edit_canonical_interrogate.sh +109 -0
- package/ds-canonical/hooks/retired/pre_edit_spec_check.sh +68 -0
- package/ds-canonical/hooks/retired/pre_new_component_spec.sh +39 -0
- package/ds-canonical/hooks/retired/pre_write_subsumption_check.sh +112 -0
- package/ds-canonical/hooks/retired/stop_meta_self_audit.sh.retired-2026-05-13 +76 -0
- package/ds-canonical/hooks/retired/tests/test_check_anatomy_section_numbering.sh +14 -0
- package/ds-canonical/hooks/retired/tests/test_check_avatar_hovercard.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_container_breathing.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_governance_compliance.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_icon_only_padding_formula.sh +79 -0
- package/ds-canonical/hooks/retired/tests/test_check_item_content_primitive.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_item_list_gap.sh +163 -0
- package/ds-canonical/hooks/retired/tests/test_check_sideoffset_canonical.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_spec_iteration_tag.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_ssot_consultation.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_sync_update.sh +14 -0
- package/ds-canonical/hooks/retired/tests/test_check_third_party_dom_verified.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_enforce_home_charter.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_pre_edit_spec_check.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_pre_new_component_spec.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_pre_write_subsumption_check.sh +63 -0
- package/ds-canonical/hooks/session_start_governance_check.sh +310 -0
- package/ds-canonical/hooks/stop_passive_logging.sh +322 -0
- package/ds-canonical/hooks/stop_self_audit.sh +516 -0
- package/ds-canonical/hooks/tests/KNOWN-BROKEN.md +15 -0
- package/ds-canonical/hooks/tests/run-all.sh +76 -0
- package/ds-canonical/hooks/tests/test_auto_regen_ds_barrel.sh +180 -0
- package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +143 -0
- package/ds-canonical/hooks/tests/test_check_addon_subdir_ship.sh +171 -0
- package/ds-canonical/hooks/tests/test_check_app_shell_primary_header_consistency.sh +196 -0
- package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +127 -0
- package/ds-canonical/hooks/tests/test_check_audit_sample_escape.sh +93 -0
- package/ds-canonical/hooks/tests/test_check_benchmark_citation.sh +115 -0
- package/ds-canonical/hooks/tests/test_check_canonical_propagation.sh +133 -0
- package/ds-canonical/hooks/tests/test_check_chrome_header_avatar_canonical.sh +198 -0
- package/ds-canonical/hooks/tests/test_check_chrome_header_handcraft.sh +146 -0
- package/ds-canonical/hooks/tests/test_check_code_quality.sh +15 -0
- package/ds-canonical/hooks/tests/test_check_codex_brief_invariants.sh +208 -0
- package/ds-canonical/hooks/tests/test_check_codex_collab_5step.sh +96 -0
- package/ds-canonical/hooks/tests/test_check_consumer_app_invariants.sh +12 -0
- package/ds-canonical/hooks/tests/test_check_consumer_app_story_title.sh +164 -0
- package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +240 -0
- package/ds-canonical/hooks/tests/test_check_consumer_no_ds_catalog.sh +214 -0
- package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +202 -0
- package/ds-canonical/hooks/tests/test_check_cva_default_sync.sh +15 -0
- package/ds-canonical/hooks/tests/test_check_data_table_size_num_to_meta_width.sh +53 -0
- package/ds-canonical/hooks/tests/test_check_datatable_invariants.sh +122 -0
- package/ds-canonical/hooks/tests/test_check_dim_count_drift.sh +98 -0
- package/ds-canonical/hooks/tests/test_check_ds_anchor_preflight.sh +104 -0
- package/ds-canonical/hooks/tests/test_check_escape_marker_abuse.sh +192 -0
- package/ds-canonical/hooks/tests/test_check_field_controls_contracts.sh +126 -0
- package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +203 -0
- package/ds-canonical/hooks/tests/test_check_file_size_budget.sh +32 -0
- package/ds-canonical/hooks/tests/test_check_fork_user_plugin_install.sh +46 -0
- package/ds-canonical/hooks/tests/test_check_full_story_visual_interaction_sweep.sh +190 -0
- package/ds-canonical/hooks/tests/test_check_hardcoded_strings.sh +14 -0
- package/ds-canonical/hooks/tests/test_check_header_with_tabs_border.sh +110 -0
- package/ds-canonical/hooks/tests/test_check_item_list_gap.sh +44 -0
- package/ds-canonical/hooks/tests/test_check_layout_space_canonical.sh +73 -0
- package/ds-canonical/hooks/tests/test_check_layout_space_magic_numbers.sh +206 -0
- package/ds-canonical/hooks/tests/test_check_main_branch_workbench.sh +147 -0
- package/ds-canonical/hooks/tests/test_check_naming_and_abstraction.sh +136 -0
- package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +110 -0
- package/ds-canonical/hooks/tests/test_check_orphan_ds_css.sh +212 -0
- package/ds-canonical/hooks/tests/test_check_overlay_handcraft.sh +126 -0
- package/ds-canonical/hooks/tests/test_check_overlay_open_focus_escape_probe.sh +191 -0
- package/ds-canonical/hooks/tests/test_check_pattern_invariants.sh +148 -0
- package/ds-canonical/hooks/tests/test_check_peoplepicker_ssot_drift.sh +108 -0
- package/ds-canonical/hooks/tests/test_check_person_data_richness.sh +58 -0
- package/ds-canonical/hooks/tests/test_check_pixel_quantified_audit.sh +142 -0
- package/ds-canonical/hooks/tests/test_check_plugin_fork_health.sh +9 -0
- package/ds-canonical/hooks/tests/test_check_propose_cite_required.sh +181 -0
- package/ds-canonical/hooks/tests/test_check_propose_discipline.sh +10 -0
- package/ds-canonical/hooks/tests/test_check_propose_plain_chinese.sh +127 -0
- package/ds-canonical/hooks/tests/test_check_propose_pre_grep_verify.sh +117 -0
- package/ds-canonical/hooks/tests/test_check_propose_without_benchmark.sh +55 -0
- package/ds-canonical/hooks/tests/test_check_select_all_canonical.sh +125 -0
- package/ds-canonical/hooks/tests/test_check_sidebar_menu_button_implicit_wrap.sh +224 -0
- package/ds-canonical/hooks/tests/test_check_solo_workflow.sh +201 -0
- package/ds-canonical/hooks/tests/test_check_spec_class_drift.sh +135 -0
- package/ds-canonical/hooks/tests/test_check_story_anatomy.sh.broken +197 -0
- package/ds-canonical/hooks/tests/test_check_story_category.sh.broken +187 -0
- package/ds-canonical/hooks/tests/test_check_story_compile_drift.sh +15 -0
- package/ds-canonical/hooks/tests/test_check_story_invariants.sh +384 -0
- package/ds-canonical/hooks/tests/test_check_story_name_jargon.sh.broken +53 -0
- package/ds-canonical/hooks/tests/test_check_story_slot_split.sh +156 -0
- package/ds-canonical/hooks/tests/test_check_storybook_addon_packaging.sh +10 -0
- package/ds-canonical/hooks/tests/test_check_storybook_addon_preset_cjs.sh +200 -0
- package/ds-canonical/hooks/tests/test_check_substantive_edit_approval_preflight.sh +176 -0
- package/ds-canonical/hooks/tests/test_check_tab_lg_chrome_header_equal.sh +141 -0
- package/ds-canonical/hooks/tests/test_check_tailwind_wildcard_in_docs.sh +182 -0
- package/ds-canonical/hooks/tests/test_check_token_hygiene.sh +21 -0
- package/ds-canonical/hooks/tests/test_check_wrapper_primitive_schema_drift.sh +169 -0
- package/ds-canonical/hooks/tests/test_enforce_home_charter.sh +77 -0
- package/ds-canonical/hooks/tests/test_inject_deploy_url_after_push.sh +193 -0
- package/ds-canonical/hooks/tests/test_inject_pending_self_audit.sh +125 -0
- package/ds-canonical/hooks/tests/test_log_governance_fires.sh +10 -0
- package/ds-canonical/hooks/tests/test_log_skill_invokes.sh +7 -0
- package/ds-canonical/hooks/tests/test_post_edit_dispatcher.sh +108 -0
- package/ds-canonical/hooks/tests/test_session_start_governance_check.sh +154 -0
- package/ds-canonical/hooks/tests/test_stop_capture_metrics.sh +95 -0
- package/ds-canonical/hooks/tests/test_stop_governance_drift_check.sh.broken +125 -0
- package/ds-canonical/hooks/tests/test_stop_harvest_corrections.sh +10 -0
- package/ds-canonical/hooks/tests/test_stop_passive_logging.sh +100 -0
- package/ds-canonical/hooks/tests/test_stop_self_audit.sh +98 -0
- package/ds-canonical/hooks/tests/test_stop_tsc_sanity.sh +10 -0
- package/ds-canonical/references/README.md +46 -0
- package/ds-canonical/references/audit-coverage-vs-24-checklist.md +74 -0
- package/ds-canonical/references/build-ui-canonicals.md +72 -0
- package/ds-canonical/references/composition-fidelity.md +47 -0
- package/ds-canonical/references/cva-patterns.md +41 -0
- package/ds-canonical/references/drag-canonical.md +331 -0
- package/ds-canonical/references/item-anatomy-recipe.md +225 -0
- package/ds-canonical/references/naming-conventions.md +57 -0
- package/ds-canonical/references/principle-dim-map.json +613 -0
- package/ds-canonical/references/props-naming.md +59 -0
- package/ds-canonical/references/scenario-definition.md +146 -0
- package/ds-canonical/references/spec-rules.md +58 -0
- package/ds-canonical/references/ssot-consultation.md +63 -0
- package/ds-canonical/references/ssot-index.md +40 -0
- package/ds-canonical/references/story-baseline-registry.json +108 -0
- package/ds-canonical/references/structural-token-retention.md +42 -0
- package/ds-canonical/references/tailwind-gotchas.md +87 -0
- package/ds-canonical/references/ui-dev-rules.md +81 -0
- package/ds-canonical/rules/README.md +34 -0
- package/ds-canonical/rules/meta-patterns.md +87 -0
- package/ds-canonical/rules/self-verify.md +56 -0
- package/ds-canonical/rules/spec-rules.md +25 -0
- package/ds-canonical/rules/story-rules.md +67 -0
- package/ds-canonical/rules/ui-development.md +92 -0
- package/ds-canonical/skills/README.md +88 -0
- package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +181 -0
- package/ds-canonical/skills/code-quality-audit/SKILL.md +63 -0
- package/ds-canonical/skills/codex-collab/SKILL.md +249 -0
- package/ds-canonical/skills/codex-collab/references/brief-template.md +48 -0
- package/ds-canonical/skills/codex-collab/references/transport.md +58 -0
- package/ds-canonical/skills/codify-corrections/SKILL.md +184 -0
- package/ds-canonical/skills/codify-principle/SKILL.md +151 -0
- package/ds-canonical/skills/component-quality-gate/SKILL.md +102 -0
- package/ds-canonical/skills/component-quality-gate/references/checklist.md +79 -0
- package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +254 -0
- package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +123 -0
- package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +186 -0
- package/ds-canonical/skills/deep-audit-cross-codex/references/skill-relationships-antipatterns-benchmarks.md +30 -0
- package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +69 -0
- package/ds-canonical/skills/deep-audit-cross-codex/references/upstream-directives-r-mapping.md +33 -0
- package/ds-canonical/skills/delivery-handoff/SKILL.md +229 -0
- package/ds-canonical/skills/delivery-handoff/references/flow-diagram.md +180 -0
- package/ds-canonical/skills/delivery-handoff/references/handoff-template.md +177 -0
- package/ds-canonical/skills/delivery-handoff/references/inventory-checklist.md +196 -0
- package/ds-canonical/skills/design-system-audit/SKILL.md +386 -0
- package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +1325 -0
- package/ds-canonical/skills/design-system-audit/references/checkpoints.md +240 -0
- package/ds-canonical/skills/design-system-audit/references/historical-bugs.md +240 -0
- package/ds-canonical/skills/design-system-audit/references/principle-audit-protocol.md +378 -0
- package/ds-canonical/skills/design-system-audit/references/rule-placement.md +175 -0
- package/ds-canonical/skills/ensure-canonical/SKILL.md +196 -0
- package/ds-canonical/skills/governance-health/SKILL.md +147 -0
- package/ds-canonical/skills/knowledge-prune/SKILL.md +250 -0
- package/ds-canonical/skills/knowledge-prune/references/phase-z-cross-repo-ssot-propagation.md +11 -0
- package/ds-canonical/skills/knowledge-prune/references/prune-dimensions-d5-d10.md +55 -0
- package/ds-canonical/skills/knowledge-prune/references/world-class-prune-alignment.md +7 -0
- package/ds-canonical/skills/new-component/SKILL.md +170 -0
- package/ds-canonical/skills/new-component/references/new-component-checklist.md +85 -0
- package/ds-canonical/skills/performance-audit/SKILL.md +107 -0
- package/ds-canonical/skills/product-ui-audit/SKILL.md +230 -0
- package/ds-canonical/skills/product-ui-audit/references/audit-checks.md +246 -0
- package/ds-canonical/skills/product-ui-audit/references/common-misuses.md +329 -0
- package/ds-canonical/skills/product-ui-audit/references/report-template.md +159 -0
- package/ds-canonical/skills/propose-options/SKILL.md +177 -0
- package/ds-canonical/skills/prototype/SKILL.md +244 -0
- package/ds-canonical/skills/prototype/references/audit-checks.md +37 -0
- package/ds-canonical/skills/prototype/references/benchmark-sources.md +94 -0
- package/ds-canonical/skills/prototype/references/checkpoints.md +191 -0
- package/ds-canonical/skills/prototype/references/evaluation-matrix.md +141 -0
- package/ds-canonical/skills/prototype/references/ooux-template.md +198 -0
- package/ds-canonical/skills/prototype/references/proposal-template.md +229 -0
- package/ds-canonical/skills/scan-similar-bugs/SKILL.md +198 -0
- package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +159 -0
- package/ds-canonical/skills/story-writing/SKILL.md +122 -0
- package/ds-canonical/skills/story-writing/references/anatomy-standard.md +217 -0
- package/ds-canonical/skills/story-writing/references/category-templates.md +174 -0
- package/ds-canonical/skills/story-writing/references/example-selection.md +70 -0
- package/ds-canonical/skills/story-writing/references/self-check.md +20 -0
- package/ds-canonical/skills/ux-audit/SKILL.md +130 -0
- package/ds-canonical/skills/visual-audit/SKILL.md +245 -0
- package/ds-canonical/skills/visual-audit/output/.gitkeep +0 -0
- package/ds-canonical/skills/visual-audit/references/audit-architecture.md +100 -0
- package/ds-canonical/skills/visual-audit/references/visual-checklist.md +297 -0
- package/ds-canonical/skills/visual-audit/references/world-class-benchmarks.md +198 -0
- package/ds-canonical/templates/_README.md +23 -0
- package/ds-canonical/templates/dashboard-app.tsx +161 -0
- package/ds-story-manifest.json +1684 -0
- package/llms-full.txt +419 -0
- package/llms.txt +71 -0
- package/package.json +31 -8
- package/src/components/Accordion/accordion.anatomy.stories.tsx +496 -0
- package/src/components/Accordion/accordion.principles.stories.tsx +360 -0
- package/src/components/Accordion/accordion.spec.md +131 -0
- package/src/components/Accordion/accordion.stories.tsx +190 -0
- package/src/components/Accordion/accordion.tsx +4 -1
- package/src/components/Accordion/index.ts +5 -0
- package/src/components/Alert/alert.anatomy.stories.tsx +241 -0
- package/src/components/Alert/alert.principles.stories.tsx +220 -0
- package/src/components/Alert/alert.spec.md +202 -0
- package/src/components/Alert/alert.stories.tsx +139 -0
- package/src/components/Alert/alert.tsx +18 -7
- package/src/components/Alert/index.ts +5 -0
- package/src/components/AppShell/_demo-helpers.tsx +87 -11
- package/src/components/AppShell/app-shell.anatomy.stories.tsx +179 -0
- package/src/components/AppShell/app-shell.principles.stories.tsx +140 -0
- package/src/components/AppShell/app-shell.spec.md +358 -0
- package/src/components/AppShell/app-shell.stories.tsx +442 -0
- package/src/components/AppShell/app-shell.tsx +16 -10
- package/src/components/AppShell/index.ts +5 -0
- package/src/components/AspectRatio/aspect-ratio.anatomy.stories.tsx +208 -0
- package/src/components/AspectRatio/aspect-ratio.principles.stories.tsx +303 -0
- package/src/components/AspectRatio/aspect-ratio.spec.md +147 -0
- package/src/components/AspectRatio/aspect-ratio.stories.tsx +170 -0
- package/src/components/AspectRatio/aspect-ratio.tsx +6 -3
- package/src/components/AspectRatio/index.ts +5 -0
- package/src/components/Avatar/avatar.anatomy.stories.tsx +701 -0
- package/src/components/Avatar/avatar.principles.stories.tsx +245 -0
- package/src/components/Avatar/avatar.spec.md +312 -0
- package/src/components/Avatar/avatar.stories.tsx +135 -0
- package/src/components/Avatar/avatar.tsx +61 -54
- package/src/components/Avatar/index.ts +5 -0
- package/src/components/Badge/badge.anatomy.stories.tsx +591 -0
- package/src/components/Badge/badge.principles.stories.tsx +391 -0
- package/src/components/Badge/badge.spec.md +398 -0
- package/src/components/Badge/badge.stories.tsx +80 -0
- package/src/components/Badge/badge.tsx +38 -14
- package/src/components/Badge/index.ts +5 -0
- package/src/components/Breadcrumb/breadcrumb.anatomy.stories.tsx +458 -0
- package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +348 -0
- package/src/components/Breadcrumb/breadcrumb.spec.md +270 -0
- package/src/components/Breadcrumb/breadcrumb.stories.tsx +307 -0
- package/src/components/Breadcrumb/breadcrumb.tsx +12 -6
- package/src/components/Breadcrumb/index.ts +5 -0
- package/src/components/BulkActionBar/bulk-action-bar.anatomy.stories.tsx +225 -0
- package/src/components/BulkActionBar/bulk-action-bar.principles.stories.tsx +242 -0
- package/src/components/BulkActionBar/bulk-action-bar.spec.md +227 -0
- package/src/components/BulkActionBar/bulk-action-bar.stories.tsx +136 -0
- package/src/components/BulkActionBar/bulk-action-bar.tsx +14 -12
- package/src/components/BulkActionBar/index.ts +5 -0
- package/src/components/Button/button.anatomy.stories.tsx +710 -0
- package/src/components/Button/button.principles.stories.tsx +370 -0
- package/src/components/Button/button.spec.md +463 -0
- package/src/components/Button/button.stories.tsx +362 -0
- package/src/components/Button/button.tsx +86 -52
- package/src/components/Button/index.ts +6 -0
- package/src/components/Calendar/calendar.anatomy.stories.tsx +218 -0
- package/src/components/Calendar/calendar.principles.stories.tsx +143 -0
- package/src/components/Calendar/calendar.spec.md +270 -0
- package/src/components/Calendar/calendar.stories.tsx +88 -0
- package/src/components/Calendar/calendar.tsx +54 -40
- package/src/components/Calendar/index.ts +5 -0
- package/src/components/Carousel/carousel.anatomy.stories.tsx +516 -0
- package/src/components/Carousel/carousel.principles.stories.tsx +330 -0
- package/src/components/Carousel/carousel.spec.md +273 -0
- package/src/components/Carousel/carousel.stories.tsx +121 -0
- package/src/components/Carousel/carousel.tsx +27 -7
- package/src/components/Carousel/index.ts +5 -0
- package/src/components/Chart/chart.anatomy.stories.tsx +307 -0
- package/src/components/Chart/chart.principles.stories.tsx +436 -0
- package/src/components/Chart/chart.spec.md +174 -0
- package/src/components/Chart/chart.stories.tsx +268 -0
- package/src/components/Chart/chart.tsx +7 -3
- package/src/components/Chart/index.ts +5 -0
- package/src/components/Checkbox/checkbox-group.tsx +2 -1
- package/src/components/Checkbox/checkbox.anatomy.stories.tsx +626 -0
- package/src/components/Checkbox/checkbox.principles.stories.tsx +216 -0
- package/src/components/Checkbox/checkbox.spec.md +372 -0
- package/src/components/Checkbox/checkbox.stories.tsx +114 -0
- package/src/components/Checkbox/checkbox.tsx +115 -24
- package/src/components/Checkbox/index.ts +6 -0
- package/src/components/Chip/chip.anatomy.stories.tsx +422 -0
- package/src/components/Chip/chip.principles.stories.tsx +228 -0
- package/src/components/Chip/chip.spec.md +237 -0
- package/src/components/Chip/chip.stories.tsx +88 -0
- package/src/components/Chip/chip.tsx +10 -10
- package/src/components/Chip/index.ts +5 -0
- package/src/components/CircularProgress/circular-progress.anatomy.stories.tsx +176 -0
- package/src/components/CircularProgress/circular-progress.principles.stories.tsx +260 -0
- package/src/components/CircularProgress/circular-progress.spec.md +269 -0
- package/src/components/CircularProgress/circular-progress.stories.tsx +145 -0
- package/src/components/CircularProgress/circular-progress.tsx +4 -5
- package/src/components/CircularProgress/index.ts +5 -0
- package/src/components/Coachmark/coachmark-story-helpers.tsx +39 -0
- package/src/components/Coachmark/coachmark.anatomy.stories.tsx +356 -0
- package/src/components/Coachmark/coachmark.principles.stories.tsx +355 -0
- package/src/components/Coachmark/coachmark.spec.md +238 -0
- package/src/components/Coachmark/coachmark.stories.tsx +214 -0
- package/src/components/Coachmark/coachmark.tsx +26 -9
- package/src/components/Coachmark/index.ts +5 -0
- package/src/components/Combobox/combobox.anatomy.stories.tsx +919 -0
- package/src/components/Combobox/combobox.principles.stories.tsx +239 -0
- package/src/components/Combobox/combobox.spec.md +202 -0
- package/src/components/Combobox/combobox.stories.tsx +184 -0
- package/src/components/Combobox/combobox.tsx +109 -55
- package/src/components/Combobox/index.ts +5 -0
- package/src/components/Command/command.anatomy.stories.tsx +107 -0
- package/src/components/Command/command.principles.stories.tsx +86 -0
- package/src/components/Command/command.spec.md +181 -0
- package/src/components/Command/command.stories.tsx +280 -0
- package/src/components/Command/command.tsx +14 -9
- package/src/components/Command/index.ts +5 -0
- package/src/components/DataTable/active-editor-controller.ts +4 -3
- package/src/components/DataTable/cell-registry.tsx +27 -6
- package/src/components/DataTable/data-table-filter-panel.tsx +16 -10
- package/src/components/DataTable/data-table-interaction-layer.tsx +8 -7
- package/src/components/DataTable/data-table-sort-manager.tsx +4 -4
- package/src/components/DataTable/data-table.anatomy.stories.tsx +519 -0
- package/src/components/DataTable/data-table.css +3 -3
- package/src/components/DataTable/data-table.principles.stories.tsx +265 -0
- package/src/components/DataTable/data-table.spec.md +540 -0
- package/src/components/DataTable/data-table.stories.tsx +1942 -0
- package/src/components/DataTable/data-table.tsx +323 -104
- package/src/components/DataTable/filter-operators.spec.md +267 -0
- package/src/components/DataTable/filter-operators.ts +1 -1
- package/src/components/DataTable/filter-tree.ts +34 -11
- package/src/components/DataTable/index.ts +5 -0
- package/src/components/DateGrid/date-grid.anatomy.stories.tsx +583 -0
- package/src/components/DateGrid/date-grid.principles.stories.tsx +338 -0
- package/src/components/DateGrid/date-grid.spec.md +220 -0
- package/src/components/DateGrid/date-grid.stories.tsx +195 -0
- package/src/components/DateGrid/date-grid.tsx +29 -23
- package/src/components/DateGrid/index.ts +5 -0
- package/src/components/DatePicker/date-picker.anatomy.stories.tsx +952 -0
- package/src/components/DatePicker/date-picker.principles.stories.tsx +205 -0
- package/src/components/DatePicker/date-picker.spec.md +338 -0
- package/src/components/DatePicker/date-picker.stories.tsx +342 -0
- package/src/components/DatePicker/date-picker.tsx +79 -34
- package/src/components/DatePicker/index.ts +5 -0
- package/src/components/DescriptionList/description-list.anatomy.stories.tsx +252 -0
- package/src/components/DescriptionList/description-list.principles.stories.tsx +309 -0
- package/src/components/DescriptionList/description-list.spec.md +220 -0
- package/src/components/DescriptionList/description-list.stories.tsx +112 -0
- package/src/components/DescriptionList/description-list.tsx +3 -3
- package/src/components/DescriptionList/index.ts +5 -0
- package/src/components/Dialog/dialog.anatomy.stories.tsx +484 -0
- package/src/components/Dialog/dialog.principles.stories.tsx +313 -0
- package/src/components/Dialog/dialog.spec.md +216 -0
- package/src/components/Dialog/dialog.stories.tsx +483 -0
- package/src/components/Dialog/dialog.tsx +11 -10
- package/src/components/Dialog/index.ts +5 -0
- package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +971 -0
- package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +339 -0
- package/src/components/DropdownMenu/dropdown-menu.spec.md +262 -0
- package/src/components/DropdownMenu/dropdown-menu.stories.tsx +286 -0
- package/src/components/DropdownMenu/dropdown-menu.tsx +39 -9
- package/src/components/DropdownMenu/index.ts +5 -0
- package/src/components/Empty/empty.anatomy.stories.tsx +275 -0
- package/src/components/Empty/empty.principles.stories.tsx +314 -0
- package/src/components/Empty/empty.spec.md +217 -0
- package/src/components/Empty/empty.stories.tsx +69 -0
- package/src/components/Empty/empty.tsx +16 -7
- package/src/components/Empty/index.ts +5 -0
- package/src/components/Field/field-context.ts +98 -0
- package/src/components/Field/field-controls.spec.md +383 -0
- package/src/components/Field/field-types.ts +1 -1
- package/src/components/Field/field-wrapper.tsx +34 -14
- package/src/components/Field/field.anatomy.stories.tsx +544 -0
- package/src/components/Field/field.principles.stories.tsx +278 -0
- package/src/components/Field/field.spec.md +462 -0
- package/src/components/Field/field.stories.tsx +716 -0
- package/src/components/Field/field.tsx +12 -5
- package/src/components/Field/form-validation.spec.md +175 -0
- package/src/components/Field/index.ts +5 -0
- package/src/components/Field/use-form-validation.ts +266 -0
- package/src/components/FieldControlGroup/field-control-group.anatomy.stories.tsx +119 -0
- package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +121 -0
- package/src/components/FieldControlGroup/field-control-group.spec.md +195 -0
- package/src/components/FieldControlGroup/field-control-group.stories.tsx +161 -0
- package/src/components/FieldControlGroup/field-control-group.tsx +12 -11
- package/src/components/FieldControlGroup/index.ts +5 -0
- package/src/components/FileItem/file-item.anatomy.stories.tsx +346 -0
- package/src/components/FileItem/file-item.principles.stories.tsx +276 -0
- package/src/components/FileItem/file-item.spec.md +491 -0
- package/src/components/FileItem/file-item.stories.tsx +265 -0
- package/src/components/FileItem/file-item.tsx +40 -15
- package/src/components/FileItem/index.ts +5 -0
- package/src/components/FileUpload/file-upload.anatomy.stories.tsx +446 -0
- package/src/components/FileUpload/file-upload.principles.stories.tsx +312 -0
- package/src/components/FileUpload/file-upload.spec.md +166 -0
- package/src/components/FileUpload/file-upload.stories.tsx +167 -0
- package/src/components/FileUpload/file-upload.tsx +97 -31
- package/src/components/FileUpload/index.ts +5 -0
- package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +1129 -0
- package/src/components/FileViewer/file-viewer.principles.stories.tsx +636 -0
- package/src/components/FileViewer/file-viewer.spec.md +368 -0
- package/src/components/FileViewer/file-viewer.stories.tsx +407 -0
- package/src/components/FileViewer/file-viewer.tsx +62 -31
- package/src/components/FileViewer/index.ts +5 -0
- package/src/components/HoverCard/hover-card.anatomy.stories.tsx +145 -0
- package/src/components/HoverCard/hover-card.principles.stories.tsx +222 -0
- package/src/components/HoverCard/hover-card.spec.md +167 -0
- package/src/components/HoverCard/hover-card.stories.tsx +304 -0
- package/src/components/HoverCard/hover-card.tsx +15 -4
- package/src/components/HoverCard/index.ts +5 -0
- package/src/components/Input/index.ts +5 -0
- package/src/components/Input/input.anatomy.stories.tsx +763 -0
- package/src/components/Input/input.principles.stories.tsx +265 -0
- package/src/components/Input/input.spec.md +207 -0
- package/src/components/Input/input.stories.tsx +139 -0
- package/src/components/Input/input.tsx +18 -19
- package/src/components/LinkInput/index.ts +5 -0
- package/src/components/LinkInput/link-input.anatomy.stories.tsx +748 -0
- package/src/components/LinkInput/link-input.principles.stories.tsx +182 -0
- package/src/components/LinkInput/link-input.spec.md +144 -0
- package/src/components/LinkInput/link-input.stories.tsx +132 -0
- package/src/components/LinkInput/link-input.tsx +53 -40
- package/src/components/Menu/index.ts +5 -0
- package/src/components/Menu/menu-item.anatomy.stories.tsx +780 -0
- package/src/components/Menu/menu-item.principles.stories.tsx +81 -0
- package/src/components/Menu/menu-item.spec.md +305 -0
- package/src/components/Menu/menu-item.stories.tsx +214 -0
- package/src/components/Menu/menu-item.tsx +11 -4
- package/src/components/Notice/index.ts +5 -0
- package/src/components/Notice/notice.anatomy.stories.tsx +615 -0
- package/src/components/Notice/notice.principles.stories.tsx +102 -0
- package/src/components/Notice/notice.spec.md +159 -0
- package/src/components/Notice/notice.stories.tsx +257 -0
- package/src/components/Notice/notice.tsx +47 -14
- package/src/components/NumberInput/index.ts +5 -0
- package/src/components/NumberInput/number-input.anatomy.stories.tsx +788 -0
- package/src/components/NumberInput/number-input.principles.stories.tsx +200 -0
- package/src/components/NumberInput/number-input.spec.md +145 -0
- package/src/components/NumberInput/number-input.stories.tsx +142 -0
- package/src/components/NumberInput/number-input.tsx +32 -18
- package/src/components/OverflowIndicator/index.ts +5 -0
- package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +549 -0
- package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +77 -0
- package/src/components/OverflowIndicator/overflow-indicator.spec.md +127 -0
- package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +238 -0
- package/src/components/OverflowIndicator/overflow-indicator.tsx +21 -7
- package/src/components/PeoplePicker/index.ts +5 -0
- package/src/components/PeoplePicker/people-picker-helpers.ts +5 -5
- package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +427 -0
- package/src/components/PeoplePicker/people-picker.principles.stories.tsx +192 -0
- package/src/components/PeoplePicker/people-picker.spec.md +292 -0
- package/src/components/PeoplePicker/people-picker.stories.tsx +162 -0
- package/src/components/PeoplePicker/people-picker.tsx +92 -74
- package/src/components/PeoplePicker/person-display.tsx +35 -32
- package/src/components/Popover/index.ts +5 -0
- package/src/components/Popover/popover.anatomy.stories.tsx +279 -0
- package/src/components/Popover/popover.principles.stories.tsx +295 -0
- package/src/components/Popover/popover.spec.md +207 -0
- package/src/components/Popover/popover.stories.tsx +116 -0
- package/src/components/Popover/popover.tsx +19 -16
- package/src/components/ProfileCard/index.ts +5 -0
- package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +504 -0
- package/src/components/ProfileCard/profile-card.principles.stories.tsx +225 -0
- package/src/components/ProfileCard/profile-card.spec.md +190 -0
- package/src/components/ProfileCard/profile-card.stories.tsx +53 -0
- package/src/components/{NameCard/name-card.tsx → ProfileCard/profile-card.tsx} +39 -30
- package/src/components/ProgressBar/index.ts +5 -0
- package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +438 -0
- package/src/components/ProgressBar/progress-bar.principles.stories.tsx +339 -0
- package/src/components/ProgressBar/progress-bar.spec.md +240 -0
- package/src/components/ProgressBar/progress-bar.stories.tsx +119 -0
- package/src/components/ProgressBar/progress-bar.tsx +4 -4
- package/src/components/RadioGroup/index.ts +5 -0
- package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +681 -0
- package/src/components/RadioGroup/radio-group.principles.stories.tsx +163 -0
- package/src/components/RadioGroup/radio-group.spec.md +149 -0
- package/src/components/RadioGroup/radio-group.stories.tsx +103 -0
- package/src/components/RadioGroup/radio-group.tsx +150 -60
- package/src/components/Rating/index.ts +5 -0
- package/src/components/Rating/rating.anatomy.stories.tsx +498 -0
- package/src/components/Rating/rating.principles.stories.tsx +296 -0
- package/src/components/Rating/rating.spec.md +214 -0
- package/src/components/Rating/rating.stories.tsx +133 -0
- package/src/components/Rating/rating.tsx +32 -17
- package/src/components/ScrollArea/index.ts +5 -0
- package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +451 -0
- package/src/components/ScrollArea/scroll-area.principles.stories.tsx +331 -0
- package/src/components/ScrollArea/scroll-area.spec.md +144 -0
- package/src/components/ScrollArea/scroll-area.stories.tsx +243 -0
- package/src/components/ScrollArea/scroll-area.tsx +3 -3
- package/src/components/SegmentedControl/index.ts +5 -0
- package/src/components/SegmentedControl/segmented-control.anatomy.stories.tsx +295 -0
- package/src/components/SegmentedControl/segmented-control.principles.stories.tsx +281 -0
- package/src/components/SegmentedControl/segmented-control.spec.md +297 -0
- package/src/components/SegmentedControl/segmented-control.stories.tsx +33 -0
- package/src/components/SegmentedControl/segmented-control.tsx +25 -16
- package/src/components/Select/index.ts +5 -0
- package/src/components/Select/select.anatomy.stories.tsx +828 -0
- package/src/components/Select/select.principles.stories.tsx +311 -0
- package/src/components/Select/select.spec.md +338 -0
- package/src/components/Select/select.stories.tsx +198 -0
- package/src/components/Select/select.tsx +72 -30
- package/src/components/SelectMenu/index.ts +5 -0
- package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +812 -0
- package/src/components/SelectMenu/select-menu.principles.stories.tsx +107 -0
- package/src/components/SelectMenu/select-menu.spec.md +232 -0
- package/src/components/SelectMenu/select-menu.stories.tsx +155 -0
- package/src/components/SelectMenu/select-menu.tsx +123 -16
- package/src/components/SelectionControl/index.ts +5 -0
- package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +571 -0
- package/src/components/SelectionControl/selection-item.principles.stories.tsx +77 -0
- package/src/components/SelectionControl/selection-item.spec.md +142 -0
- package/src/components/SelectionControl/selection-item.stories.tsx +137 -0
- package/src/components/SelectionControl/selection-item.tsx +8 -2
- package/src/components/Separator/index.ts +5 -0
- package/src/components/Separator/separator.anatomy.stories.tsx +125 -0
- package/src/components/Separator/separator.principles.stories.tsx +141 -0
- package/src/components/Separator/separator.spec.md +115 -0
- package/src/components/Separator/separator.stories.tsx +127 -0
- package/src/components/Separator/separator.tsx +2 -2
- package/src/components/Sheet/index.ts +5 -0
- package/src/components/Sheet/sheet.anatomy.stories.tsx +269 -0
- package/src/components/Sheet/sheet.principles.stories.tsx +351 -0
- package/src/components/Sheet/sheet.spec.md +146 -0
- package/src/components/Sheet/sheet.stories.tsx +168 -0
- package/src/components/Sheet/sheet.tsx +9 -7
- package/src/components/Sidebar/index.ts +5 -0
- package/src/components/Sidebar/sidebar.anatomy.stories.tsx +772 -0
- package/src/components/Sidebar/sidebar.principles.stories.tsx +505 -0
- package/src/components/Sidebar/sidebar.spec.md +725 -0
- package/src/components/Sidebar/sidebar.stories.tsx +500 -0
- package/src/components/Sidebar/sidebar.tsx +56 -20
- package/src/components/Skeleton/index.ts +5 -0
- package/src/components/Skeleton/skeleton.anatomy.stories.tsx +145 -0
- package/src/components/Skeleton/skeleton.principles.stories.tsx +234 -0
- package/src/components/Skeleton/skeleton.spec.md +105 -0
- package/src/components/Skeleton/skeleton.stories.tsx +137 -0
- package/src/components/Skeleton/skeleton.tsx +2 -2
- package/src/components/Slider/index.ts +5 -0
- package/src/components/Slider/slider.anatomy.stories.tsx +236 -0
- package/src/components/Slider/slider.principles.stories.tsx +250 -0
- package/src/components/Slider/slider.spec.md +358 -0
- package/src/components/Slider/slider.stories.tsx +99 -0
- package/src/components/Slider/slider.tsx +54 -16
- package/src/components/Steps/index.ts +5 -0
- package/src/components/Steps/steps.anatomy.stories.tsx +448 -0
- package/src/components/Steps/steps.principles.stories.tsx +300 -0
- package/src/components/Steps/steps.spec.md +480 -0
- package/src/components/Steps/steps.stories.tsx +335 -0
- package/src/components/Steps/steps.tsx +67 -29
- package/src/components/Switch/index.ts +5 -0
- package/src/components/Switch/switch.anatomy.stories.tsx +227 -0
- package/src/components/Switch/switch.principles.stories.tsx +174 -0
- package/src/components/Switch/switch.spec.md +238 -0
- package/src/components/Switch/switch.stories.tsx +107 -0
- package/src/components/Switch/switch.tsx +116 -38
- package/src/components/Tabs/index.ts +5 -0
- package/src/components/Tabs/tabs.anatomy.stories.tsx +415 -0
- package/src/components/Tabs/tabs.principles.stories.tsx +259 -0
- package/src/components/Tabs/tabs.spec.md +332 -0
- package/src/components/Tabs/tabs.stories.tsx +155 -0
- package/src/components/Tabs/tabs.tsx +49 -35
- package/src/components/Tag/index.ts +5 -0
- package/src/components/Tag/tag.anatomy.stories.tsx +664 -0
- package/src/components/Tag/tag.principles.stories.tsx +270 -0
- package/src/components/Tag/tag.spec.md +324 -0
- package/src/components/Tag/tag.stories.tsx +69 -0
- package/src/components/Tag/tag.tsx +59 -57
- package/src/components/Textarea/index.ts +5 -0
- package/src/components/Textarea/textarea.anatomy.stories.tsx +304 -0
- package/src/components/Textarea/textarea.principles.stories.tsx +175 -0
- package/src/components/Textarea/textarea.spec.md +163 -0
- package/src/components/Textarea/textarea.stories.tsx +53 -0
- package/src/components/Textarea/textarea.tsx +36 -27
- package/src/components/TimePicker/index.ts +5 -0
- package/src/components/TimePicker/time-columns.tsx +8 -1
- package/src/components/TimePicker/time-picker.anatomy.stories.tsx +282 -0
- package/src/components/TimePicker/time-picker.principles.stories.tsx +140 -0
- package/src/components/TimePicker/time-picker.spec.md +290 -0
- package/src/components/TimePicker/time-picker.stories.tsx +193 -0
- package/src/components/TimePicker/time-picker.tsx +46 -30
- package/src/components/Toast/index.ts +5 -0
- package/src/components/Toast/toast.anatomy.stories.tsx +323 -0
- package/src/components/Toast/toast.principles.stories.tsx +216 -0
- package/src/components/Toast/toast.spec.md +181 -0
- package/src/components/Toast/toast.stories.tsx +129 -0
- package/src/components/Toast/toast.tsx +11 -8
- package/src/components/Tooltip/index.ts +5 -0
- package/src/components/Tooltip/tooltip.anatomy.stories.tsx +413 -0
- package/src/components/Tooltip/tooltip.principles.stories.tsx +204 -0
- package/src/components/Tooltip/tooltip.spec.md +142 -0
- package/src/components/Tooltip/tooltip.stories.tsx +116 -0
- package/src/components/Tooltip/tooltip.tsx +5 -2
- package/src/components/TreeView/index.ts +5 -0
- package/src/components/TreeView/tree-view.anatomy.stories.tsx +431 -0
- package/src/components/TreeView/tree-view.principles.stories.tsx +190 -0
- package/src/components/TreeView/tree-view.spec.md +390 -0
- package/src/components/TreeView/tree-view.stories.tsx +299 -0
- package/src/components/TreeView/tree-view.tsx +79 -27
- package/src/hooks/use-overflow-items.ts +10 -6
- package/src/index.ts +73 -69
- package/src/lib/utils.ts +2 -1
- package/src/patterns/README.md +15 -11
- package/src/patterns/action-bar/action-bar.spec.md +465 -0
- package/src/patterns/action-bar/action-bar.stories.tsx +612 -0
- package/src/patterns/element-anatomy/element-anatomy.spec.md +217 -0
- package/src/patterns/element-anatomy/index.ts +5 -0
- package/src/patterns/element-anatomy/inline-action.spec.md +320 -0
- package/src/patterns/element-anatomy/item-anatomy.spec.md +1043 -0
- package/src/patterns/element-anatomy/item-anatomy.stories.tsx +1623 -0
- package/src/patterns/element-anatomy/item-anatomy.tsx +10 -6
- package/src/patterns/header-canonical/chrome-header.tsx +16 -5
- package/src/patterns/header-canonical/header-canonical.css +3 -4
- package/src/patterns/header-canonical/header-canonical.spec.md +326 -0
- package/src/patterns/header-canonical/header-canonical.stories.tsx +150 -0
- package/src/patterns/header-canonical/index.ts +5 -0
- package/src/patterns/horizontal-overflow/horizontal-overflow.spec.md +212 -0
- package/src/patterns/horizontal-overflow/index.ts +5 -0
- package/src/patterns/overlay-surface/index.ts +5 -0
- package/src/patterns/overlay-surface/overlay-surface.spec.md +443 -0
- package/src/patterns/overlay-surface/overlay-surface.tsx +31 -16
- package/src/patterns/resize-handle/index.ts +5 -0
- package/src/patterns/resize-handle/resize-handle.spec.md +120 -0
- package/src/patterns/resize-handle/resize-handle.stories.tsx +71 -0
- package/src/story-governance/category-matrix.json +132 -0
- package/src/story-governance/category-matrix.ts +55 -0
- package/src/styles/base.css +92 -0
- package/src/styles/tokens.css +11 -0
- package/src/tokens/README.md +7 -2
- package/src/tokens/categorical-color.ts +164 -0
- package/src/tokens/color/color.spec.md +801 -0
- package/src/tokens/color/color.stories.tsx +363 -0
- package/src/tokens/color/primitives.css +14 -5
- package/src/tokens/color/semantic.css +28 -13
- package/src/tokens/density/density.spec.md +130 -0
- package/src/tokens/density/density.stories.tsx +240 -0
- package/src/tokens/elevation/elevation.spec.md +78 -0
- package/src/tokens/elevation/elevation.stories.tsx +98 -0
- package/src/tokens/layoutSpace/layoutSpace.css +1 -1
- package/src/tokens/layoutSpace/layoutSpace.spec.md +324 -0
- package/src/tokens/layoutSpace/layoutSpace.stories.tsx +75 -0
- package/src/tokens/motion/motion.css +2 -2
- package/src/tokens/motion/motion.spec.md +105 -0
- package/src/tokens/motion/motion.ts +1 -1
- package/src/tokens/opacity/opacity.spec.md +73 -0
- package/src/tokens/opacity/opacity.stories.tsx +65 -0
- package/src/tokens/orphan-tokens.spec.md +128 -0
- package/src/tokens/radius/radius.spec.md +126 -0
- package/src/tokens/radius/radius.stories.tsx +86 -0
- package/src/tokens/token-system.spec.md +240 -0
- package/src/tokens/typography/typography.css +1 -1
- package/src/tokens/typography/typography.spec.md +204 -0
- package/src/tokens/typography/typography.stories.tsx +133 -0
- package/src/tokens/uiSize/icon-size.ts +3 -4
- package/src/tokens/uiSize/uiSize.css +21 -0
- package/src/tokens/uiSize/uiSize.spec.md +466 -0
- package/src/tokens/utility-registry.json +125 -0
- package/dist/components/NameCard/name-card.d.ts.map +0 -1
- package/dist/components/NameCard/name-card.js.map +0 -1
|
@@ -0,0 +1,1623 @@
|
|
|
1
|
+
// @benchmark-unverified-blanket: file-level retraction per M22 (d) — claims herein not individually URL-cited; treat as unverified visual/usage rumor unless retrofit per-claim. Hook escape preserved.
|
|
2
|
+
// @anatomy-exempt: Item Anatomy pattern spec 的教學 story,使用 raw <table> 呈現 token/align/primitive 對照表(類似 Figma inspect)。DataTable 的密度 / row 交互行為不適合純文件靜態對照;此為 pattern 自身 anatomy 檔,屬合理例外。
|
|
3
|
+
import type { Meta } from '@storybook/react'
|
|
4
|
+
import { useState } from 'react'
|
|
5
|
+
import {
|
|
6
|
+
Mail, Bell, Settings, Star, ChevronRight, Globe, Lock,
|
|
7
|
+
Trash2, X, MoreVertical, Download, RotateCw, Share2, RefreshCw,
|
|
8
|
+
} from 'lucide-react'
|
|
9
|
+
import type { LucideIcon } from 'lucide-react'
|
|
10
|
+
import { MenuItem } from '@/design-system/components/Menu/menu-item'
|
|
11
|
+
import { SelectionItem } from '@/design-system/components/SelectionControl/selection-item'
|
|
12
|
+
import { Checkbox } from '@/design-system/components/Checkbox/checkbox'
|
|
13
|
+
import { Tag } from '@/design-system/components/Tag/tag'
|
|
14
|
+
import { Avatar, type AvatarData } from '@/design-system/components/Avatar/avatar'
|
|
15
|
+
import { ProfileCard, ProfileCardDefaultActions } from '@/design-system/components/ProfileCard/profile-card'
|
|
16
|
+
|
|
17
|
+
/** Person avatar hover canonical helper — avatar.spec.md DS-wide rule:
|
|
18
|
+
* profile-card.spec.md 重要資訊 canonical(status / statusMessage / fields 皆必含) */
|
|
19
|
+
const personHover = (name: string, subtitle?: string) => (
|
|
20
|
+
<ProfileCard
|
|
21
|
+
name={name}
|
|
22
|
+
subtitle={subtitle ?? 'Design|D-0042|EMP-1001'}
|
|
23
|
+
avatar={{ alt: name }}
|
|
24
|
+
status="online"
|
|
25
|
+
statusMessage="Out of Office: Back on Monday!"
|
|
26
|
+
actions={<ProfileCardDefaultActions />}
|
|
27
|
+
fields={[
|
|
28
|
+
{ label: 'ID', value: 'YHANAX' },
|
|
29
|
+
{ label: 'Employee number', value: '1234567' },
|
|
30
|
+
]}
|
|
31
|
+
onViewMore={() => {}}
|
|
32
|
+
/>
|
|
33
|
+
)
|
|
34
|
+
import { Button } from '@/design-system/components/Button/button'
|
|
35
|
+
import { Separator } from '@/design-system/components/Separator/separator'
|
|
36
|
+
import { ItemInlineActionButton } from '@/design-system/patterns/element-anatomy/item-anatomy'
|
|
37
|
+
import { cn } from '@/lib/utils'
|
|
38
|
+
|
|
39
|
+
const meta: Meta = {
|
|
40
|
+
title: 'Design System/Patterns/Item Anatomy',
|
|
41
|
+
parameters: { layout: 'padded' },
|
|
42
|
+
}
|
|
43
|
+
export default meta
|
|
44
|
+
|
|
45
|
+
/* ═══════════════════════════════════════════════════════════════════════════
|
|
46
|
+
Types & Data
|
|
47
|
+
═══════════════════════════════════════════════════════════════════════════ */
|
|
48
|
+
|
|
49
|
+
type SizeKey = 'sm' | 'md' | 'lg'
|
|
50
|
+
type ConsumerKey = 'MenuItem' | 'SelectionItem' | 'ListItem'
|
|
51
|
+
type PrefixType = 'icon' | 'avatar'
|
|
52
|
+
|
|
53
|
+
const SIZES: SizeKey[] = ['sm', 'md', 'lg']
|
|
54
|
+
|
|
55
|
+
/** Consumer preset definitions — spacing varies by consumer, structure is shared */
|
|
56
|
+
interface ConsumerPreset {
|
|
57
|
+
label: string
|
|
58
|
+
desc: string
|
|
59
|
+
mode: 'scanning' | 'reading'
|
|
60
|
+
py: string
|
|
61
|
+
pyDesc: string
|
|
62
|
+
px: string
|
|
63
|
+
pxDesc: string
|
|
64
|
+
gap: string
|
|
65
|
+
gapDesc: string
|
|
66
|
+
suffixGap: string
|
|
67
|
+
suffixGapDesc: string
|
|
68
|
+
/**
|
|
69
|
+
* Label / description 的截斷政策(per-consumer 設計決定)。
|
|
70
|
+
* `undefined` = 不截斷(自然 wrap 到任意行數)。
|
|
71
|
+
* `1` = line-clamp-1(用 truncate / line-clamp css 截斷,顯示 ellipsis)。
|
|
72
|
+
* `2` = line-clamp-2(最多兩行)。
|
|
73
|
+
*/
|
|
74
|
+
labelMaxLines: number | undefined
|
|
75
|
+
descMaxLines: number | undefined
|
|
76
|
+
/** 預留最少行數(避免 layout shift)。預設 0(完全不預留,內容沒有就高度為 0) */
|
|
77
|
+
labelMinLines: number
|
|
78
|
+
descMinLines: number
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Consumer tab 顯示名(情境導向,不用元件名) */
|
|
82
|
+
const CONSUMER_DISPLAY: Record<ConsumerKey, { tab: string; sub: string }> = {
|
|
83
|
+
MenuItem: { tab: '選單', sub: 'MenuItem · 浮層內快速掃視' },
|
|
84
|
+
SelectionItem: { tab: '表單選項', sub: 'SelectionItem · Checkbox / RadioGroup' },
|
|
85
|
+
ListItem: { tab: '列表', sub: 'ListItem · 頁面內瀏覽' },
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const CONSUMERS: Record<ConsumerKey, ConsumerPreset> = {
|
|
89
|
+
MenuItem: {
|
|
90
|
+
label: 'MenuItem',
|
|
91
|
+
desc: '浮層選單(DropdownMenu / ComboBox)',
|
|
92
|
+
mode: 'scanning',
|
|
93
|
+
py: '(field-height − 一行文字高度) / 2',
|
|
94
|
+
pyDesc: '單行 = field-height',
|
|
95
|
+
px: 'px-3 (12px)',
|
|
96
|
+
pxDesc: '選單標準水平間距',
|
|
97
|
+
gap: 'gap-2 (8px)',
|
|
98
|
+
gapDesc: 'prefix-content 間距',
|
|
99
|
+
suffixGap: 'gap-2 (8px)',
|
|
100
|
+
suffixGapDesc: 'value + endContent(menu-item.tsx 用 gap-2,同 prefix gap)',
|
|
101
|
+
// Source: menu-item.tsx — label / description 都截到 1 行,維持掃視節奏
|
|
102
|
+
labelMaxLines: 1,
|
|
103
|
+
descMaxLines: 1,
|
|
104
|
+
labelMinLines: 0,
|
|
105
|
+
descMinLines: 0,
|
|
106
|
+
},
|
|
107
|
+
SelectionItem: {
|
|
108
|
+
label: 'SelectionItem',
|
|
109
|
+
desc: '表單 Checkbox / RadioGroup',
|
|
110
|
+
mode: 'reading',
|
|
111
|
+
py: '(field-height − 一行文字高度) / 2',
|
|
112
|
+
pyDesc: '單行 = field-height',
|
|
113
|
+
px: 'none',
|
|
114
|
+
pxDesc: '由外層容器決定',
|
|
115
|
+
gap: 'gap-2 (8px)',
|
|
116
|
+
gapDesc: '控件與 label 間距',
|
|
117
|
+
suffixGap: '--',
|
|
118
|
+
suffixGapDesc: '無 suffix',
|
|
119
|
+
// Source: selection-item.tsx — 兩者皆無 clamp,form 欄位允許任意長度
|
|
120
|
+
labelMaxLines: undefined,
|
|
121
|
+
descMaxLines: undefined,
|
|
122
|
+
labelMinLines: 0,
|
|
123
|
+
descMinLines: 0,
|
|
124
|
+
},
|
|
125
|
+
ListItem: {
|
|
126
|
+
label: 'ListItem',
|
|
127
|
+
desc: '頁面列表(未來元件)',
|
|
128
|
+
mode: 'reading',
|
|
129
|
+
py: 'py-3 (12px)',
|
|
130
|
+
pyDesc: '觸控友好的列表行高',
|
|
131
|
+
px: 'px-4 (16px)',
|
|
132
|
+
pxDesc: '頁面標準水平間距',
|
|
133
|
+
gap: 'gap-3 (12px)',
|
|
134
|
+
gapDesc: '適合較大的 avatar',
|
|
135
|
+
suffixGap: 'gap-2 (8px)',
|
|
136
|
+
suffixGapDesc: '後綴元素間距',
|
|
137
|
+
// Convention: label 截到 1 行,description 截到 2 行(觸控列表常見做法)
|
|
138
|
+
labelMaxLines: 1,
|
|
139
|
+
descMaxLines: 2,
|
|
140
|
+
labelMinLines: 0,
|
|
141
|
+
descMinLines: 0,
|
|
142
|
+
},
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
interface TypoSpec {
|
|
146
|
+
labelFont: string
|
|
147
|
+
labelSize: string
|
|
148
|
+
labelLh: string
|
|
149
|
+
descFont: string
|
|
150
|
+
descSize: string
|
|
151
|
+
descLh: string
|
|
152
|
+
iconPx: number
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const SCANNING_SPECS: Record<SizeKey, TypoSpec> = {
|
|
156
|
+
sm: { labelFont: 'text-body leading-compact', labelSize: '14px', labelLh: '1.3', descFont: 'text-caption', descSize: '12px', descLh: '1.3', iconPx: 16 },
|
|
157
|
+
md: { labelFont: 'text-body leading-compact', labelSize: '14px', labelLh: '1.3', descFont: 'text-caption', descSize: '12px', descLh: '1.3', iconPx: 16 },
|
|
158
|
+
lg: { labelFont: 'text-body-lg leading-compact', labelSize: '16px', labelLh: '1.3', descFont: 'text-body leading-compact', descSize: '14px', descLh: '1.3', iconPx: 20 },
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const READING_SPECS: Record<SizeKey, TypoSpec> = {
|
|
162
|
+
sm: { labelFont: 'text-body', labelSize: '14px', labelLh: '1.5', descFont: 'text-body', descSize: '14px', descLh: '1.5', iconPx: 16 },
|
|
163
|
+
md: { labelFont: 'text-body', labelSize: '14px', labelLh: '1.5', descFont: 'text-body', descSize: '14px', descLh: '1.5', iconPx: 16 },
|
|
164
|
+
lg: { labelFont: 'text-body-lg', labelSize: '16px', labelLh: '1.5', descFont: 'text-body', descSize: '14px', descLh: '1.5', iconPx: 20 },
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* ═══════════════════════════════════════════════════════════════════════════
|
|
168
|
+
Shared UI Components
|
|
169
|
+
═══════════════════════════════════════════════════════════════════════════ */
|
|
170
|
+
|
|
171
|
+
const H3 = ({ children }: { children: React.ReactNode }) => (
|
|
172
|
+
<h3 className="text-h6 font-semibold text-foreground">{children}</h3>
|
|
173
|
+
)
|
|
174
|
+
const Desc = ({ children }: { children: React.ReactNode }) => (
|
|
175
|
+
<p className="text-caption text-fg-muted max-w-[720px]">{children}</p>
|
|
176
|
+
)
|
|
177
|
+
const Th = ({ children }: { children: React.ReactNode }) => (
|
|
178
|
+
<th className="text-left p-2 border-b border-divider text-fg-muted font-medium text-caption whitespace-nowrap">{children}</th>
|
|
179
|
+
)
|
|
180
|
+
const Td = ({ children, mono }: { children: React.ReactNode; mono?: boolean }) => (
|
|
181
|
+
<td className={`p-2 border-b border-divider align-top whitespace-nowrap text-caption ${mono ? 'font-mono' : ''}`}>{children}</td>
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
const TkVal = ({ token, value }: { token: string; value?: string }) => (
|
|
185
|
+
<div className="flex flex-col gap-0.5">
|
|
186
|
+
<span className="font-mono text-[12px] text-fg-secondary">{token}</span>
|
|
187
|
+
{value && <span className="font-mono text-[10px] text-fg-muted">{value}</span>}
|
|
188
|
+
</div>
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
const Swatch = ({ value, size = 'md' }: { value: string; size?: 'sm' | 'md' }) => {
|
|
192
|
+
const s = size === 'sm' ? 'w-3 h-3' : 'w-4 h-4'
|
|
193
|
+
if (value === 'transparent') {
|
|
194
|
+
return <span className={`${s} rounded-md shrink-0 border border-border`}
|
|
195
|
+
style={{ backgroundImage: 'linear-gradient(45deg,#ddd 25%,transparent 25%,transparent 75%,#ddd 75%),linear-gradient(45deg,#ddd 25%,transparent 25%,transparent 75%,#ddd 75%)', backgroundSize: '6px 6px', backgroundPosition: '0 0,3px 3px' }} />
|
|
196
|
+
}
|
|
197
|
+
return <span className={`${s} rounded-md shrink-0 border border-black/10`} style={{ backgroundColor: `var(${value})` }} />
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const Tab = ({ active, onClick, children }: { active: boolean; onClick: () => void; children: React.ReactNode }) => (
|
|
201
|
+
<button type="button" onClick={onClick}
|
|
202
|
+
className={`px-2.5 py-1 text-[12px] font-mono rounded-md cursor-pointer transition-colors ${
|
|
203
|
+
active ? 'bg-primary text-white font-semibold' : 'bg-neutral-hover text-fg-secondary hover:bg-neutral-active'
|
|
204
|
+
}`}>
|
|
205
|
+
{children}
|
|
206
|
+
</button>
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
const PropRow = ({ label, dot, children }: { label: string; dot?: string; children: React.ReactNode }) => (
|
|
210
|
+
<div className="flex items-start gap-3 py-2 border-b border-divider last:border-b-0">
|
|
211
|
+
<span className="text-[11px] text-fg-muted font-medium w-[88px] shrink-0 pt-0.5 flex items-center gap-1.5">
|
|
212
|
+
{dot && <span className="w-2 h-2 rounded-full shrink-0" style={{ backgroundColor: dot }} />}
|
|
213
|
+
{label}
|
|
214
|
+
</span>
|
|
215
|
+
<div className="flex-1 text-[12px] font-mono text-fg-secondary">{children}</div>
|
|
216
|
+
</div>
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
/** Blueprint zone colors
|
|
220
|
+
* Text colors darkened 2026-04-22 to pass WCAG 4.5:1 contrast on 0.6-alpha tint bgs
|
|
221
|
+
* (previous text 3.41-4.25 ratio failed Layer A audit — `pad/icon/gap/label`).
|
|
222
|
+
*/
|
|
223
|
+
const Z = {
|
|
224
|
+
pad: { bg: 'rgba(194,225,154,0.6)', border: 'rgba(139,179,91,0.9)', text: '#3d5520' },
|
|
225
|
+
/** Control slot(SelectionItem 的 Checkbox / RadioGroupItem,永遠 inline) */
|
|
226
|
+
control: { bg: 'rgba(170,222,180,0.6)', border: 'rgba(85,165,110,0.9)', text: '#1f5030' },
|
|
227
|
+
icon: { bg: 'rgba(166,208,245,0.6)', border: 'rgba(80,145,210,0.9)', text: '#1f4d82' },
|
|
228
|
+
gap: { bg: 'rgba(253,218,158,0.6)', border: 'rgba(218,165,60,0.9)', text: '#664500' },
|
|
229
|
+
label: { bg: 'rgba(199,178,230,0.6)', border: 'rgba(138,103,190,0.9)', text: '#452578' },
|
|
230
|
+
dim: { text: '#d04040' },
|
|
231
|
+
suffix: { bg: 'rgba(253,186,186,0.5)', border: 'rgba(210,80,80,0.7)', text: '#a03030' },
|
|
232
|
+
/** flex-1 spacer:把 suffix 推到右邊的可擴展區域。用斜紋背景表達「會撐開」的性質,跟其他固定寬度的彩色區塊區隔 */
|
|
233
|
+
spacer: {
|
|
234
|
+
bg: 'repeating-linear-gradient(45deg, rgba(160,160,160,0.12) 0 6px, rgba(160,160,160,0.22) 6px 12px)',
|
|
235
|
+
border: 'rgba(140,140,140,0.6)',
|
|
236
|
+
text: '#666666',
|
|
237
|
+
},
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** Menu container — role=listbox 滿足內部 MenuItem role=option 的 parent(axe aria-required-parent)。 */
|
|
241
|
+
const MenuFrame = ({ children, width = 320 }: { children: React.ReactNode; width?: number }) => (
|
|
242
|
+
<div
|
|
243
|
+
role="listbox"
|
|
244
|
+
aria-label="Anatomy inspector menu preview"
|
|
245
|
+
className="rounded-lg bg-surface-raised border border-border overflow-hidden py-2"
|
|
246
|
+
style={{ width, boxShadow: 'var(--elevation-200)' }}
|
|
247
|
+
>
|
|
248
|
+
{children}
|
|
249
|
+
</div>
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
/** 把 maxLines 轉成 line-clamp class;'none' / 0 → 空字串 */
|
|
254
|
+
function lineClampClass(maxLines: number | 'none'): string {
|
|
255
|
+
if (maxLines === 'none' || !maxLines) return ''
|
|
256
|
+
if (maxLines === 1) return 'line-clamp-1'
|
|
257
|
+
if (maxLines === 2) return 'line-clamp-2'
|
|
258
|
+
if (maxLines === 3) return 'line-clamp-3'
|
|
259
|
+
return ''
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** ListItem preview (simulated — component not yet built) */
|
|
263
|
+
const ListItemPreview = ({ size, startIcon: StartIcon, avatar, label, description, suffix, labelMaxLines = 1, descMaxLines = 2 }: {
|
|
264
|
+
size: SizeKey
|
|
265
|
+
startIcon?: LucideIcon
|
|
266
|
+
avatar?: AvatarData
|
|
267
|
+
label: string
|
|
268
|
+
description?: string
|
|
269
|
+
suffix?: React.ReactNode
|
|
270
|
+
labelMaxLines?: number | 'none'
|
|
271
|
+
descMaxLines?: number | 'none'
|
|
272
|
+
}) => {
|
|
273
|
+
const iconPx = size === 'lg' ? 20 : 16
|
|
274
|
+
const hasBlockPrefix = !!avatar && !!description
|
|
275
|
+
const alignClass = hasBlockPrefix
|
|
276
|
+
? (size === 'lg' ? 'h-[calc(1lh+var(--item-gap-label-desc-reading)+var(--font-body-size)*1.5)]' : 'h-[calc(1lh+var(--item-gap-label-desc-reading)+var(--font-body-size)*1.5)]')
|
|
277
|
+
: 'h-[1lh]'
|
|
278
|
+
|
|
279
|
+
return (
|
|
280
|
+
<div className={`flex items-start gap-3 px-4 py-3 ${size === 'lg' ? 'text-body-lg' : 'text-body'}`}>
|
|
281
|
+
{(StartIcon || avatar) && (
|
|
282
|
+
<div className={`${alignClass} flex items-center shrink-0`}>
|
|
283
|
+
{StartIcon && <StartIcon size={iconPx} aria-hidden />}
|
|
284
|
+
{avatar && (
|
|
285
|
+
<Avatar
|
|
286
|
+
src={avatar.src}
|
|
287
|
+
alt={avatar.alt}
|
|
288
|
+
color={avatar.color}
|
|
289
|
+
hoverCard={avatar.hoverCard}
|
|
290
|
+
size={hasBlockPrefix ? (size === 'lg' ? 40 : 32) : 24}
|
|
291
|
+
/>
|
|
292
|
+
)}
|
|
293
|
+
</div>
|
|
294
|
+
)}
|
|
295
|
+
<div className="flex flex-col min-w-0 flex-1">
|
|
296
|
+
<span className={cn('break-words', lineClampClass(labelMaxLines))}>{label}</span>
|
|
297
|
+
{description && (
|
|
298
|
+
<p
|
|
299
|
+
className={cn('mt-[var(--item-gap-label-desc-reading)] text-fg-secondary break-words', lineClampClass(descMaxLines))}
|
|
300
|
+
// ── 規則(item-anatomy.spec.md 閱讀模式) ──
|
|
301
|
+
// ListItem 是 reading mode:description 字體**最小 14px**(spec「14→14px, 16→14px」)。
|
|
302
|
+
// sm/md/lg 全部 14px,行高跟 label 同(預設 1.5,不套 leading-compact)。
|
|
303
|
+
//
|
|
304
|
+
// ── 為什麼用 inline style ──
|
|
305
|
+
// tailwind-merge 會把 font-size utility(text-body)和 color utility
|
|
306
|
+
// (text-fg-secondary)誤判成同組衝突,strip 掉 text-body。inline style 直接繞過。
|
|
307
|
+
style={{ fontSize: 'var(--font-body-size)' }}
|
|
308
|
+
>
|
|
309
|
+
{description}
|
|
310
|
+
</p>
|
|
311
|
+
)}
|
|
312
|
+
</div>
|
|
313
|
+
{/* Suffix: 24px 閾值獨立於 prefix。ChevronRight ≤24px → 永遠 h-[1lh] 對齊 label 第一行 */}
|
|
314
|
+
{suffix && (
|
|
315
|
+
<div className="h-[1lh] flex items-center ml-auto shrink-0">
|
|
316
|
+
{suffix}
|
|
317
|
+
</div>
|
|
318
|
+
)}
|
|
319
|
+
</div>
|
|
320
|
+
)
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/* ═══════════════════════════════════════════════════════════════════════════
|
|
324
|
+
1. 檢閱器
|
|
325
|
+
═══════════════════════════════════════════════════════════════════════════ */
|
|
326
|
+
|
|
327
|
+
type ContentLength = 'short' | 'medium' | 'long'
|
|
328
|
+
type DescContent = 'none' | ContentLength
|
|
329
|
+
type ClampOverride = 'preset' | 'unbounded' | 1 | 2 | 3
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* 真實內容字串——長度遞增,放進固定寬度的容器後 wrap 行為是 emergent 的。
|
|
333
|
+
* 容器寬度約 200px(藍圖) / 300px(live preview),md size text-body(14px)。
|
|
334
|
+
* - short:約 6 字 → 1 行
|
|
335
|
+
* - medium:約 14 字 → 2 行
|
|
336
|
+
* - long:約 28 字 → 3+ 行
|
|
337
|
+
*
|
|
338
|
+
* 注意:**不指定行數**——行數由「容器寬度 + 內容長度 + clamp 政策」共同決定。
|
|
339
|
+
*/
|
|
340
|
+
const LABEL_TEXT: Record<ContentLength, string> = {
|
|
341
|
+
short: '電子郵件通知',
|
|
342
|
+
medium: '電子郵件通知與每週重點摘要信件',
|
|
343
|
+
long: '電子郵件通知與每週重點摘要信件以及帳戶異常即時警示提醒功能',
|
|
344
|
+
}
|
|
345
|
+
const DESC_TEXT: Record<ContentLength, string> = {
|
|
346
|
+
short: '每日摘要',
|
|
347
|
+
medium: '每日寄送摘要信件到您的電子信箱',
|
|
348
|
+
long: '每日寄送摘要信件到您的電子信箱,可在帳戶設定中隨時調整或關閉此功能',
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* 解析 clamp override → 顯示用的 effective value(`undefined` = ∞,for inspect panel display)。
|
|
353
|
+
*/
|
|
354
|
+
function resolveClamp(override: ClampOverride, presetVal: number | undefined): number | undefined {
|
|
355
|
+
if (override === 'preset') return presetVal
|
|
356
|
+
if (override === 'unbounded') return undefined
|
|
357
|
+
return override
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* 解析 clamp override → 傳給元件 prop 的值(永遠是 `number | 'none'`,絕不傳 undefined)。
|
|
362
|
+
*
|
|
363
|
+
* 為什麼不能傳 undefined?React props 的 destructure default 在 undefined 時會接管,
|
|
364
|
+
* 例如 `<MenuItem labelMaxLines={undefined}>` 等同沒傳,fallback 到元件預設。
|
|
365
|
+
* 要明確覆寫成「不截斷」,必須傳 `'none'` 這個非 undefined 的 sentinel。
|
|
366
|
+
*/
|
|
367
|
+
function resolveClampProp(override: ClampOverride, presetVal: number | undefined): number | 'none' {
|
|
368
|
+
if (override === 'preset') return presetVal ?? 'none'
|
|
369
|
+
if (override === 'unbounded') return 'none'
|
|
370
|
+
return override
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const InspectorInner = () => {
|
|
374
|
+
const [consumer, setConsumer] = useState<ConsumerKey>('MenuItem')
|
|
375
|
+
const [size, setSize] = useState<SizeKey>('md')
|
|
376
|
+
const [hasPrefix, setHasPrefix] = useState(true)
|
|
377
|
+
const [prefixType, setPrefixType] = useState<PrefixType>('icon')
|
|
378
|
+
// (SelectionItem 沒有 block 模式,prefix 永遠 inline)
|
|
379
|
+
const [labelLength, setLabelLength] = useState<ContentLength>('short')
|
|
380
|
+
const [descContent, setDescContent] = useState<DescContent>('short')
|
|
381
|
+
const [labelClampOverride, setLabelClampOverride] = useState<ClampOverride>('preset')
|
|
382
|
+
const [descClampOverride, setDescClampOverride] = useState<ClampOverride>('preset')
|
|
383
|
+
const [hasSuffix, setHasSuffix] = useState(false)
|
|
384
|
+
|
|
385
|
+
const hasDescription = descContent !== 'none'
|
|
386
|
+
|
|
387
|
+
const preset = CONSUMERS[consumer]
|
|
388
|
+
const spec = preset.mode === 'scanning' ? SCANNING_SPECS[size] : READING_SPECS[size]
|
|
389
|
+
|
|
390
|
+
// SelectionItem 也支援 icon/avatar prefix(在 control 之後、label 之前),
|
|
391
|
+
// 套用同樣的 24px 閾值對齊規則。所以這幾個 toggle 對 SelectionItem 完全有效。
|
|
392
|
+
// SelectionItem 沒有 suffix(form 欄位通常不用 suffix),強制 hasSuffix=false。
|
|
393
|
+
const effectiveHasPrefix = hasPrefix
|
|
394
|
+
const effectivePrefixType: PrefixType = prefixType
|
|
395
|
+
const effectiveHasSuffix = consumer === 'SelectionItem' ? false : hasSuffix
|
|
396
|
+
|
|
397
|
+
// Control slot 只有 SelectionItem 有(Checkbox/RadioGroupItem),其他 consumer 無
|
|
398
|
+
const hasControl = consumer === 'SelectionItem'
|
|
399
|
+
|
|
400
|
+
// 解析有效的 clamp:
|
|
401
|
+
// - effective*Clamp:用於 inspect panel 顯示(undefined = ∞)
|
|
402
|
+
// - prop*Clamp:直接傳給元件 prop(用 'none' sentinel,避免 undefined 觸發 destructure default)
|
|
403
|
+
const effectiveLabelClamp = resolveClamp(labelClampOverride, preset.labelMaxLines)
|
|
404
|
+
const effectiveDescClamp = resolveClamp(descClampOverride, preset.descMaxLines)
|
|
405
|
+
const propLabelClamp = resolveClampProp(labelClampOverride, preset.labelMaxLines)
|
|
406
|
+
const propDescClamp = resolveClampProp(descClampOverride, preset.descMaxLines)
|
|
407
|
+
|
|
408
|
+
// Block 對齊規則:所有 consumer 統一——avatar + desc → block。
|
|
409
|
+
// SelectionItem 的差異:block 時 control 也跟著走 block 高度(跟 prefix 同步),不會歪斜。
|
|
410
|
+
const isBlockAlign = effectivePrefixType === 'avatar' && hasDescription
|
|
411
|
+
const alignContainer = isBlockAlign ? '= label 文字塊 + 2px + desc 文字塊' : '= 一行文字高度'
|
|
412
|
+
const alignDesc = isBlockAlign
|
|
413
|
+
? consumer === 'SelectionItem'
|
|
414
|
+
? 'avatar + desc → block;**control 跟 prefix 同高度**(都在 text block center,不歪斜)'
|
|
415
|
+
: 'prefix > 24px(avatar)+ description → 對齊 label + description 文字塊中心'
|
|
416
|
+
: 'prefix ≤ 24px(或無 description)→ 對齊第一行 label 中線'
|
|
417
|
+
|
|
418
|
+
// 真實內容字串
|
|
419
|
+
const labelText = LABEL_TEXT[labelLength]
|
|
420
|
+
const descText = hasDescription ? DESC_TEXT[descContent as ContentLength] : ''
|
|
421
|
+
|
|
422
|
+
const PY_ZONE = 20
|
|
423
|
+
const hasPx = consumer !== 'SelectionItem'
|
|
424
|
+
const gapLabel = consumer === 'ListItem' ? 'gap-3' : 'gap-2'
|
|
425
|
+
const gapPx = consumer === 'ListItem' ? '12px' : '8px'
|
|
426
|
+
const pxLabel = consumer === 'ListItem' ? 'px-4' : 'px-3'
|
|
427
|
+
const pxPx = consumer === 'ListItem' ? '16px' : '12px'
|
|
428
|
+
|
|
429
|
+
// line-clamp 產生的 CSS class
|
|
430
|
+
const labelClampClass =
|
|
431
|
+
effectiveLabelClamp === 1 ? 'line-clamp-1' :
|
|
432
|
+
effectiveLabelClamp === 2 ? 'line-clamp-2' :
|
|
433
|
+
effectiveLabelClamp === 3 ? 'line-clamp-3' : ''
|
|
434
|
+
const descClampClass =
|
|
435
|
+
effectiveDescClamp === 1 ? 'line-clamp-1' :
|
|
436
|
+
effectiveDescClamp === 2 ? 'line-clamp-2' :
|
|
437
|
+
effectiveDescClamp === 3 ? 'line-clamp-3' : ''
|
|
438
|
+
|
|
439
|
+
return (
|
|
440
|
+
<div className="flex flex-col gap-6">
|
|
441
|
+
{/* Controls */}
|
|
442
|
+
<div className="flex flex-col gap-2.5">
|
|
443
|
+
<div className="flex items-center gap-2">
|
|
444
|
+
<span className="text-[11px] text-fg-muted w-24 shrink-0">情境</span>
|
|
445
|
+
<div className="flex gap-1.5">
|
|
446
|
+
{(Object.keys(CONSUMERS) as ConsumerKey[]).map((c) => (
|
|
447
|
+
<Tab key={c} active={consumer === c} onClick={() => setConsumer(c)}>{CONSUMER_DISPLAY[c].tab}</Tab>
|
|
448
|
+
))}
|
|
449
|
+
</div>
|
|
450
|
+
<span className="text-[10px] text-fg-muted font-mono">{CONSUMER_DISPLAY[consumer].sub}</span>
|
|
451
|
+
</div>
|
|
452
|
+
<div className="flex items-center gap-2">
|
|
453
|
+
<span className="text-[11px] text-fg-muted w-24 shrink-0">Size</span>
|
|
454
|
+
<div className="flex gap-1.5">
|
|
455
|
+
{SIZES.map((sz) => <Tab key={sz} active={size === sz} onClick={() => setSize(sz)}>{sz}</Tab>)}
|
|
456
|
+
</div>
|
|
457
|
+
</div>
|
|
458
|
+
<div className="flex items-center gap-2">
|
|
459
|
+
<span className="text-[11px] text-fg-muted w-24 shrink-0">hasPrefix</span>
|
|
460
|
+
<div className="flex gap-1.5">
|
|
461
|
+
<Tab active={hasPrefix} onClick={() => setHasPrefix(true)}>on</Tab>
|
|
462
|
+
<Tab active={!hasPrefix} onClick={() => setHasPrefix(false)}>off</Tab>
|
|
463
|
+
</div>
|
|
464
|
+
{consumer === 'SelectionItem' && (
|
|
465
|
+
<span className="text-[11px] text-fg-muted">
|
|
466
|
+
SelectionItem 的 prefix 是<strong>除了 control 之外</strong>的視覺輔助
|
|
467
|
+
</span>
|
|
468
|
+
)}
|
|
469
|
+
</div>
|
|
470
|
+
{hasPrefix && (
|
|
471
|
+
<div className="flex items-center gap-2">
|
|
472
|
+
<span className="text-[11px] text-fg-muted w-24 shrink-0">prefixType</span>
|
|
473
|
+
<div className="flex gap-1.5">
|
|
474
|
+
<Tab active={prefixType === 'icon'} onClick={() => setPrefixType('icon')}>icon</Tab>
|
|
475
|
+
<Tab active={prefixType === 'avatar'} onClick={() => setPrefixType('avatar')}>avatar</Tab>
|
|
476
|
+
</div>
|
|
477
|
+
</div>
|
|
478
|
+
)}
|
|
479
|
+
{/* SelectionItem avatar 沒有 block 模式(left checkbox + block avatar = 歪斜) */}
|
|
480
|
+
<div className="flex items-center gap-2">
|
|
481
|
+
<span className="text-[11px] text-fg-muted w-24 shrink-0">label 內容長度</span>
|
|
482
|
+
<div className="flex gap-1.5">
|
|
483
|
+
<Tab active={labelLength === 'short'} onClick={() => setLabelLength('short')}>short</Tab>
|
|
484
|
+
<Tab active={labelLength === 'medium'} onClick={() => setLabelLength('medium')}>medium</Tab>
|
|
485
|
+
<Tab active={labelLength === 'long'} onClick={() => setLabelLength('long')}>long</Tab>
|
|
486
|
+
</div>
|
|
487
|
+
</div>
|
|
488
|
+
<div className="flex items-center gap-2">
|
|
489
|
+
<span className="text-[11px] text-fg-muted w-24 shrink-0">label clamp</span>
|
|
490
|
+
<div className="flex gap-1.5">
|
|
491
|
+
<Tab active={labelClampOverride === 'preset'} onClick={() => setLabelClampOverride('preset')}>
|
|
492
|
+
preset({preset.labelMaxLines ?? '∞'})
|
|
493
|
+
</Tab>
|
|
494
|
+
<Tab active={labelClampOverride === 1} onClick={() => setLabelClampOverride(1)}>1</Tab>
|
|
495
|
+
<Tab active={labelClampOverride === 2} onClick={() => setLabelClampOverride(2)}>2</Tab>
|
|
496
|
+
<Tab active={labelClampOverride === 'unbounded'} onClick={() => setLabelClampOverride('unbounded')}>∞</Tab>
|
|
497
|
+
</div>
|
|
498
|
+
</div>
|
|
499
|
+
<div className="flex items-center gap-2">
|
|
500
|
+
<span className="text-[11px] text-fg-muted w-24 shrink-0">description</span>
|
|
501
|
+
<div className="flex gap-1.5">
|
|
502
|
+
<Tab active={descContent === 'none'} onClick={() => setDescContent('none')}>none</Tab>
|
|
503
|
+
<Tab active={descContent === 'short'} onClick={() => setDescContent('short')}>short</Tab>
|
|
504
|
+
<Tab active={descContent === 'medium'} onClick={() => setDescContent('medium')}>medium</Tab>
|
|
505
|
+
<Tab active={descContent === 'long'} onClick={() => setDescContent('long')}>long</Tab>
|
|
506
|
+
</div>
|
|
507
|
+
</div>
|
|
508
|
+
{hasDescription && (
|
|
509
|
+
<div className="flex items-center gap-2">
|
|
510
|
+
<span className="text-[11px] text-fg-muted w-24 shrink-0">desc clamp</span>
|
|
511
|
+
<div className="flex gap-1.5">
|
|
512
|
+
<Tab active={descClampOverride === 'preset'} onClick={() => setDescClampOverride('preset')}>
|
|
513
|
+
preset({preset.descMaxLines ?? '∞'})
|
|
514
|
+
</Tab>
|
|
515
|
+
<Tab active={descClampOverride === 1} onClick={() => setDescClampOverride(1)}>1</Tab>
|
|
516
|
+
<Tab active={descClampOverride === 2} onClick={() => setDescClampOverride(2)}>2</Tab>
|
|
517
|
+
<Tab active={descClampOverride === 'unbounded'} onClick={() => setDescClampOverride('unbounded')}>∞</Tab>
|
|
518
|
+
</div>
|
|
519
|
+
</div>
|
|
520
|
+
)}
|
|
521
|
+
<div className="flex items-center gap-2">
|
|
522
|
+
<span className="text-[11px] text-fg-muted w-24 shrink-0">hasSuffix</span>
|
|
523
|
+
<div className="flex gap-1.5">
|
|
524
|
+
<Tab active={hasSuffix} onClick={() => setHasSuffix(true)}>on</Tab>
|
|
525
|
+
<Tab active={!hasSuffix} onClick={() => setHasSuffix(false)}>off</Tab>
|
|
526
|
+
</div>
|
|
527
|
+
</div>
|
|
528
|
+
</div>
|
|
529
|
+
|
|
530
|
+
{/* Preview + Panel */}
|
|
531
|
+
<div className="flex gap-8 items-start">
|
|
532
|
+
{/* Left: live preview + blueprint */}
|
|
533
|
+
<div className="flex flex-col gap-6 min-w-[440px]">
|
|
534
|
+
{/* Live preview */}
|
|
535
|
+
<div className="px-8 py-8 rounded-lg bg-canvas border border-divider flex items-center justify-center">
|
|
536
|
+
{consumer === 'MenuItem' && (
|
|
537
|
+
<MenuFrame width={360}>
|
|
538
|
+
<MenuItem
|
|
539
|
+
size={size}
|
|
540
|
+
startIcon={effectiveHasPrefix && effectivePrefixType === 'icon' ? Mail : undefined}
|
|
541
|
+
avatar={effectiveHasPrefix && effectivePrefixType === 'avatar' ? { alt: "Alice", color: "indigo" as const, hoverCard: personHover("Alice", "Design team lead") } : undefined}
|
|
542
|
+
description={hasDescription ? descText : undefined}
|
|
543
|
+
tag={effectiveHasSuffix ? <Tag size={size} color="blue">Pro</Tag> : undefined}
|
|
544
|
+
labelMaxLines={propLabelClamp}
|
|
545
|
+
descMaxLines={propDescClamp}
|
|
546
|
+
>
|
|
547
|
+
{labelText}
|
|
548
|
+
</MenuItem>
|
|
549
|
+
</MenuFrame>
|
|
550
|
+
)}
|
|
551
|
+
{consumer === 'SelectionItem' && (
|
|
552
|
+
<div className="w-[360px]">
|
|
553
|
+
<SelectionItem
|
|
554
|
+
size={size}
|
|
555
|
+
control={<Checkbox size={size} checked={true} />}
|
|
556
|
+
icon={effectiveHasPrefix && effectivePrefixType === 'icon' ? Mail : undefined}
|
|
557
|
+
avatar={effectiveHasPrefix && effectivePrefixType === 'avatar' ? { alt: "Alice", color: "indigo" as const, hoverCard: personHover("Alice", "Design team lead") } : undefined}
|
|
558
|
+
label={labelText}
|
|
559
|
+
description={hasDescription ? descText : undefined}
|
|
560
|
+
labelMaxLines={propLabelClamp}
|
|
561
|
+
descMaxLines={propDescClamp}
|
|
562
|
+
/>
|
|
563
|
+
</div>
|
|
564
|
+
)}
|
|
565
|
+
{consumer === 'ListItem' && (
|
|
566
|
+
<div className="w-[360px] rounded-lg border border-divider overflow-hidden bg-surface">
|
|
567
|
+
<ListItemPreview
|
|
568
|
+
size={size}
|
|
569
|
+
startIcon={effectiveHasPrefix && effectivePrefixType === 'icon' ? Mail : undefined}
|
|
570
|
+
avatar={effectiveHasPrefix && effectivePrefixType === 'avatar' ? { alt: "Alice", color: "indigo" as const, hoverCard: personHover("Alice", "Design team lead") } : undefined}
|
|
571
|
+
label={labelText}
|
|
572
|
+
description={hasDescription ? descText : undefined}
|
|
573
|
+
suffix={effectiveHasSuffix ? <ChevronRight size={spec.iconPx} className="text-fg-muted" /> : undefined}
|
|
574
|
+
labelMaxLines={propLabelClamp}
|
|
575
|
+
descMaxLines={propDescClamp}
|
|
576
|
+
/>
|
|
577
|
+
</div>
|
|
578
|
+
)}
|
|
579
|
+
</div>
|
|
580
|
+
|
|
581
|
+
{/* Blueprint */}
|
|
582
|
+
<div className="flex flex-col gap-3">
|
|
583
|
+
{/* Legend */}
|
|
584
|
+
<div className="flex items-center gap-4 text-[11px] flex-wrap">
|
|
585
|
+
{[
|
|
586
|
+
...(hasPx ? [{ c: Z.pad, l: 'Padding' }] : []),
|
|
587
|
+
...(hasControl ? [{ c: Z.control, l: 'Control' }] : []),
|
|
588
|
+
...(effectiveHasPrefix ? [{ c: Z.icon, l: 'Prefix' }] : []),
|
|
589
|
+
{ c: Z.gap, l: 'Gap' },
|
|
590
|
+
{ c: Z.label, l: 'Content' },
|
|
591
|
+
{ c: Z.spacer, l: 'flex-1 spacer' },
|
|
592
|
+
...(effectiveHasSuffix ? [{ c: Z.suffix, l: 'Suffix' }] : []),
|
|
593
|
+
].map(({ c, l }) => (
|
|
594
|
+
<span key={l} className="inline-flex items-center gap-1.5">
|
|
595
|
+
<span className="w-3 h-3 rounded-md" style={{ background: c.bg, border: `1.5px dashed ${c.border}` }} />
|
|
596
|
+
<span className="font-medium" style={{ color: c.text }}>{l}</span>
|
|
597
|
+
</span>
|
|
598
|
+
))}
|
|
599
|
+
</div>
|
|
600
|
+
|
|
601
|
+
{/*
|
|
602
|
+
Diagram — 2D: vertical padding-y + horizontal zones
|
|
603
|
+
────────────────────────────────────────────────────
|
|
604
|
+
Container 寬度固定 520px,讓 flex-1 spacer 真的能撐開,
|
|
605
|
+
如實反映真實元件的 layout 行為(避免 fit-content 造成的視覺混淆)。
|
|
606
|
+
|
|
607
|
+
Row 結構:
|
|
608
|
+
[px] [prefix] [gap] [Label/desc, 220px 固定寬] [flex-1 spacer] [suffix] [px]
|
|
609
|
+
|
|
610
|
+
Label box 高度由「真實字串 + 容器寬 + line-clamp」共同決定,
|
|
611
|
+
padding-y 區域固定 PY_ZONE(20px),演示「padding 不變,內容自然撐高」的 calc() 公式。
|
|
612
|
+
*/}
|
|
613
|
+
<div className="flex items-start">
|
|
614
|
+
<div className="flex flex-col rounded-lg overflow-hidden" style={{ width: 520, outline: `2px solid ${Z.dim.text}22` }}>
|
|
615
|
+
{/* Top padding zone */}
|
|
616
|
+
<div className="flex items-center justify-center"
|
|
617
|
+
style={{ height: PY_ZONE, background: Z.pad.bg, borderBottom: `1.5px dashed ${Z.pad.border}` }}>
|
|
618
|
+
<span className="text-[10px] font-mono font-bold" style={{ color: Z.pad.text }}>padding-y</span>
|
|
619
|
+
</div>
|
|
620
|
+
{/*
|
|
621
|
+
Horizontal content row — 高度由 Label box 內容決定(text 自然 wrap)
|
|
622
|
+
items-stretch:讓 prefix / spacer / suffix / px 都跟 Label box 同高
|
|
623
|
+
*/}
|
|
624
|
+
<div className="flex items-stretch">
|
|
625
|
+
{hasPx && (
|
|
626
|
+
<div className="flex items-center justify-center shrink-0"
|
|
627
|
+
style={{ width: 48, background: Z.pad.bg, borderRight: `1.5px dashed ${Z.pad.border}` }}>
|
|
628
|
+
<span className="text-[12px] font-mono font-bold" style={{ color: Z.pad.text }}>{pxLabel}</span>
|
|
629
|
+
</div>
|
|
630
|
+
)}
|
|
631
|
+
{hasControl && (
|
|
632
|
+
<>
|
|
633
|
+
<div
|
|
634
|
+
className="flex shrink-0 items-center justify-center"
|
|
635
|
+
style={{
|
|
636
|
+
width: 50,
|
|
637
|
+
background: Z.control.bg,
|
|
638
|
+
borderLeft: `1.5px dashed ${Z.control.border}`,
|
|
639
|
+
borderRight: `1.5px dashed ${Z.control.border}`,
|
|
640
|
+
}}
|
|
641
|
+
>
|
|
642
|
+
<span className="text-[11px] font-mono font-bold text-center leading-tight" style={{ color: Z.control.text, whiteSpace: 'pre-line' }}>
|
|
643
|
+
{`control\n${spec.iconPx}px`}
|
|
644
|
+
</span>
|
|
645
|
+
</div>
|
|
646
|
+
<div className="flex items-center justify-center shrink-0"
|
|
647
|
+
style={{ width: 32, background: Z.gap.bg, borderRight: `1.5px dashed ${Z.gap.border}` }}>
|
|
648
|
+
<span className="text-[10px] font-mono font-bold" style={{ color: Z.gap.text }}>gap-2</span>
|
|
649
|
+
</div>
|
|
650
|
+
</>
|
|
651
|
+
)}
|
|
652
|
+
{effectiveHasPrefix && (
|
|
653
|
+
<>
|
|
654
|
+
<div
|
|
655
|
+
className="flex shrink-0 items-center justify-center"
|
|
656
|
+
style={{
|
|
657
|
+
width: 52,
|
|
658
|
+
background: Z.icon.bg,
|
|
659
|
+
borderLeft: `1.5px dashed ${Z.icon.border}`,
|
|
660
|
+
borderRight: `1.5px dashed ${Z.icon.border}`,
|
|
661
|
+
}}
|
|
662
|
+
>
|
|
663
|
+
<span className="text-[11px] font-mono font-bold text-center leading-tight" style={{ color: Z.icon.text, whiteSpace: 'pre-line' }}>
|
|
664
|
+
{effectivePrefixType === 'icon'
|
|
665
|
+
? `icon\n${spec.iconPx}px`
|
|
666
|
+
: isBlockAlign
|
|
667
|
+
? `avatar\n${size === 'lg' ? '40' : '32'}px`
|
|
668
|
+
: `avatar\n${size === 'sm' ? '20' : '24'}px`}
|
|
669
|
+
</span>
|
|
670
|
+
</div>
|
|
671
|
+
<div className="flex items-center justify-center shrink-0"
|
|
672
|
+
style={{ width: 38, background: Z.gap.bg, borderRight: `1.5px dashed ${Z.gap.border}` }}>
|
|
673
|
+
<span className="text-[11px] font-mono font-bold" style={{ color: Z.gap.text }}>{gapLabel}</span>
|
|
674
|
+
</div>
|
|
675
|
+
</>
|
|
676
|
+
)}
|
|
677
|
+
{/*
|
|
678
|
+
Label / description box:固定寬度 220px,**渲染真實字串**讓 wrap 自然發生。
|
|
679
|
+
行數是 emergent(內容長度 + 容器寬度 + clamp 三者決定),不是寫死的離散值。
|
|
680
|
+
line-clamp class 演示 max-lines 截斷;若內容超過 clamp,瀏覽器自動加 ellipsis。
|
|
681
|
+
*/}
|
|
682
|
+
<div
|
|
683
|
+
className="flex flex-col shrink-0 justify-center py-1"
|
|
684
|
+
style={{
|
|
685
|
+
width: 220,
|
|
686
|
+
background: Z.label.bg,
|
|
687
|
+
borderLeft: `1.5px dashed ${Z.label.border}`,
|
|
688
|
+
borderRight: `1.5px dashed ${Z.label.border}`,
|
|
689
|
+
}}
|
|
690
|
+
>
|
|
691
|
+
<span
|
|
692
|
+
className={cn('text-[12px] font-mono font-bold leading-snug px-2 break-words', labelClampClass)}
|
|
693
|
+
style={{ color: Z.label.text }}
|
|
694
|
+
>
|
|
695
|
+
{labelText}
|
|
696
|
+
</span>
|
|
697
|
+
{hasDescription && (
|
|
698
|
+
<>
|
|
699
|
+
<div className="h-0.5" />
|
|
700
|
+
<span
|
|
701
|
+
className={cn('text-[10px] font-mono leading-snug px-2 opacity-80 break-words', descClampClass)}
|
|
702
|
+
style={{ color: Z.label.text }}
|
|
703
|
+
>
|
|
704
|
+
{descText}
|
|
705
|
+
</span>
|
|
706
|
+
</>
|
|
707
|
+
)}
|
|
708
|
+
</div>
|
|
709
|
+
{/* flex-1 spacer:斜紋背景,撐開 Label 與 suffix(或右 padding)之間的剩餘寬度 */}
|
|
710
|
+
<div
|
|
711
|
+
className="flex items-center justify-center"
|
|
712
|
+
style={{
|
|
713
|
+
flex: '1 1 0',
|
|
714
|
+
minWidth: 24,
|
|
715
|
+
background: Z.spacer.bg,
|
|
716
|
+
borderRight: `1.5px dashed ${Z.spacer.border}`,
|
|
717
|
+
}}
|
|
718
|
+
>
|
|
719
|
+
<span className="text-[10px] font-mono font-bold text-center leading-tight" style={{ color: Z.spacer.text, whiteSpace: 'pre-line' }}>
|
|
720
|
+
{'flex-1\npush →'}
|
|
721
|
+
</span>
|
|
722
|
+
</div>
|
|
723
|
+
{effectiveHasSuffix && (
|
|
724
|
+
<div className="flex items-center justify-center shrink-0"
|
|
725
|
+
style={{ width: 50, background: Z.suffix.bg, borderRight: `1.5px dashed ${Z.suffix.border}` }}>
|
|
726
|
+
<span className="text-[12px] font-mono font-bold" style={{ color: Z.suffix.text }}>suffix</span>
|
|
727
|
+
</div>
|
|
728
|
+
)}
|
|
729
|
+
{hasPx && (
|
|
730
|
+
<div className="flex items-center justify-center shrink-0"
|
|
731
|
+
style={{ width: 48, background: Z.pad.bg, borderLeft: `1.5px dashed ${Z.pad.border}` }}>
|
|
732
|
+
<span className="text-[12px] font-mono font-bold" style={{ color: Z.pad.text }}>{pxLabel}</span>
|
|
733
|
+
</div>
|
|
734
|
+
)}
|
|
735
|
+
</div>
|
|
736
|
+
{/* Bottom padding zone */}
|
|
737
|
+
<div className="flex items-center justify-center"
|
|
738
|
+
style={{ height: PY_ZONE, background: Z.pad.bg, borderTop: `1.5px dashed ${Z.pad.border}` }}>
|
|
739
|
+
<span className="text-[10px] font-mono font-bold" style={{ color: Z.pad.text }}>padding-y</span>
|
|
740
|
+
</div>
|
|
741
|
+
</div>
|
|
742
|
+
|
|
743
|
+
{/* Height annotation — 文字版,不再需要精確 px(高度由 Label box 內容決定) */}
|
|
744
|
+
<div className="ml-4 flex items-start pt-2">
|
|
745
|
+
<div className="text-[10px] font-mono text-fg-muted leading-relaxed">
|
|
746
|
+
<div className="text-fg-secondary font-bold mb-1">高度公式</div>
|
|
747
|
+
<div>= padding-y × 2</div>
|
|
748
|
+
<div>+ label content height</div>
|
|
749
|
+
{hasDescription && <div>+ 2px(label-desc gap)</div>}
|
|
750
|
+
{hasDescription && <div>+ desc content height</div>}
|
|
751
|
+
<div className="mt-2 text-fg-muted">內容多行 → 自然撐高</div>
|
|
752
|
+
<div className="text-fg-muted">padding-y 不變</div>
|
|
753
|
+
</div>
|
|
754
|
+
</div>
|
|
755
|
+
</div>
|
|
756
|
+
|
|
757
|
+
{/* 對齊規則 annotation */}
|
|
758
|
+
{effectiveHasPrefix && (
|
|
759
|
+
<div
|
|
760
|
+
className="rounded-md px-3 py-2 text-[11px] flex items-start gap-2"
|
|
761
|
+
style={{
|
|
762
|
+
background: isBlockAlign ? 'rgba(166,208,245,0.18)' : 'rgba(199,178,230,0.18)',
|
|
763
|
+
border: `1px dashed ${isBlockAlign ? Z.icon.border : Z.label.border}`,
|
|
764
|
+
}}
|
|
765
|
+
>
|
|
766
|
+
<span className="font-mono font-bold mt-0.5 shrink-0" style={{ color: isBlockAlign ? Z.icon.text : Z.label.text }}>
|
|
767
|
+
{isBlockAlign ? '◫ Block 對齊' : '— Inline 對齊'}
|
|
768
|
+
</span>
|
|
769
|
+
<span className="text-fg-secondary leading-relaxed">{alignDesc}</span>
|
|
770
|
+
</div>
|
|
771
|
+
)}
|
|
772
|
+
|
|
773
|
+
{/* Clamp 政策說明 */}
|
|
774
|
+
<div className="rounded-md px-3 py-2 text-[11px] bg-muted border border-divider flex flex-col gap-1">
|
|
775
|
+
<div className="flex items-center gap-2 flex-wrap">
|
|
776
|
+
<span className="font-bold text-fg-secondary">Clamp 政策</span>
|
|
777
|
+
<span className="text-fg-muted">由 consumer 透過 prop 決定(每個 consumer 有預設,可 per-instance override)</span>
|
|
778
|
+
</div>
|
|
779
|
+
<div className="flex flex-wrap gap-x-4 font-mono text-[10px] text-fg-secondary">
|
|
780
|
+
<span>
|
|
781
|
+
<code>labelMaxLines</code> = <strong>{effectiveLabelClamp ?? '∞ (unbounded)'}</strong>
|
|
782
|
+
{labelClampOverride !== 'preset' && <span className="text-error-text"> · override</span>}
|
|
783
|
+
{labelClampOverride === 'preset' && <span className="text-fg-muted"> · {preset.label} default</span>}
|
|
784
|
+
</span>
|
|
785
|
+
<span>
|
|
786
|
+
<code>labelMinLines</code> = <strong>{preset.labelMinLines}</strong>
|
|
787
|
+
{preset.labelMinLines === 0 && <span className="text-fg-muted"> · 不預留(內容空 → 高度 0)</span>}
|
|
788
|
+
</span>
|
|
789
|
+
</div>
|
|
790
|
+
{hasDescription && (
|
|
791
|
+
<div className="flex flex-wrap gap-x-4 font-mono text-[10px] text-fg-secondary">
|
|
792
|
+
<span>
|
|
793
|
+
<code>descMaxLines</code> = <strong>{effectiveDescClamp ?? '∞ (unbounded)'}</strong>
|
|
794
|
+
{descClampOverride !== 'preset' && <span className="text-error-text"> · override</span>}
|
|
795
|
+
{descClampOverride === 'preset' && <span className="text-fg-muted"> · {preset.label} default</span>}
|
|
796
|
+
</span>
|
|
797
|
+
<span>
|
|
798
|
+
<code>descMinLines</code> = <strong>{preset.descMinLines}</strong>
|
|
799
|
+
</span>
|
|
800
|
+
</div>
|
|
801
|
+
)}
|
|
802
|
+
<div className="text-[10px] text-fg-muted leading-relaxed">
|
|
803
|
+
行數是 <strong>內容長度 + 容器寬 + clamp</strong> 三者共同決定的 emergent 結果,**不是離散設定值**。
|
|
804
|
+
左側 live preview 和右側藍圖**同步**反映相同的 clamp—改 toggle 兩邊一起變。
|
|
805
|
+
<br />
|
|
806
|
+
※ <code>minLines</code> 概念目前在所有 consumer 都是 0,保留欄位是為了將來「避免 layout shift」的需求(例如 grid 列表需要每個 item 等高)
|
|
807
|
+
</div>
|
|
808
|
+
</div>
|
|
809
|
+
|
|
810
|
+
{/* Annotations below the blueprint */}
|
|
811
|
+
<div className="flex flex-wrap gap-x-6 gap-y-1 text-[10px] font-mono text-fg-muted">
|
|
812
|
+
{hasPx && <span><strong style={{ color: Z.pad.text }}>padding-x</strong> = {pxPx}</span>}
|
|
813
|
+
{effectiveHasPrefix && <span><strong style={{ color: Z.icon.text }}>prefix-content gap</strong> = {gapPx}</span>}
|
|
814
|
+
<span><strong style={{ color: Z.label.text }}>py</strong> = {preset.py.includes('calc') ? `calc((field-height-${size} − 一行文字高度) / 2)` : preset.py}</span>
|
|
815
|
+
{hasDescription && <span>{`label-desc gap = --item-gap-label-desc-${preset.mode}${size === 'lg' ? '-lg' : ''} (2px)`}</span>}
|
|
816
|
+
</div>
|
|
817
|
+
</div>
|
|
818
|
+
</div>
|
|
819
|
+
|
|
820
|
+
{/* Right: Inspect panel */}
|
|
821
|
+
<div className="w-[320px] shrink-0 border border-divider rounded-lg bg-surface overflow-hidden">
|
|
822
|
+
<div className="px-4 py-2.5 border-b border-divider bg-neutral-hover">
|
|
823
|
+
<div className="flex items-center justify-between">
|
|
824
|
+
<span className="text-[12px] font-semibold text-foreground">Inspect</span>
|
|
825
|
+
<span className="text-[10px] font-mono text-fg-muted">{preset.label}</span>
|
|
826
|
+
</div>
|
|
827
|
+
</div>
|
|
828
|
+
|
|
829
|
+
{/* LAYOUT */}
|
|
830
|
+
<div className="px-4 py-1">
|
|
831
|
+
<div className="py-2 border-b border-divider"><span className="text-[10px] font-semibold text-fg-muted uppercase tracking-wider">Layout</span></div>
|
|
832
|
+
<PropRow label="padding-y" dot={Z.pad.text}>
|
|
833
|
+
<TkVal token={preset.py} value={preset.pyDesc} />
|
|
834
|
+
</PropRow>
|
|
835
|
+
<PropRow label="padding-x" dot={Z.pad.text}>
|
|
836
|
+
<TkVal token={preset.px} value={preset.pxDesc} />
|
|
837
|
+
</PropRow>
|
|
838
|
+
<PropRow label="prefix-content" dot={Z.gap.text}>
|
|
839
|
+
<TkVal token={preset.gap} value={preset.gapDesc} />
|
|
840
|
+
</PropRow>
|
|
841
|
+
{hasDescription && (
|
|
842
|
+
<PropRow label="label-desc" dot={Z.gap.text}><TkVal token={`--item-gap-label-desc-${preset.mode}${size === 'lg' ? '-lg' : ''}`} value="2px" /></PropRow>
|
|
843
|
+
)}
|
|
844
|
+
{effectiveHasSuffix && (
|
|
845
|
+
<PropRow label="suffix gap" dot={Z.suffix.text}>
|
|
846
|
+
<TkVal token={preset.suffixGap} value={preset.suffixGapDesc} />
|
|
847
|
+
</PropRow>
|
|
848
|
+
)}
|
|
849
|
+
{effectiveHasPrefix && (
|
|
850
|
+
<PropRow label="icon size" dot={Z.icon.text}>{spec.iconPx}px</PropRow>
|
|
851
|
+
)}
|
|
852
|
+
</div>
|
|
853
|
+
|
|
854
|
+
{/* TYPOGRAPHY */}
|
|
855
|
+
<div className="px-4 py-1">
|
|
856
|
+
<div className="py-2 border-b border-divider"><span className="text-[10px] font-semibold text-fg-muted uppercase tracking-wider">Typography</span></div>
|
|
857
|
+
<PropRow label="Label"><TkVal token={spec.labelFont} value={spec.labelSize} /></PropRow>
|
|
858
|
+
<PropRow label="Label lh"><TkVal token={preset.mode === 'scanning' ? 'leading-compact' : 'default'} value={spec.labelLh} /></PropRow>
|
|
859
|
+
<PropRow label="Label content">
|
|
860
|
+
<TkVal token={labelLength} value={`${labelText.length} 字`} />
|
|
861
|
+
</PropRow>
|
|
862
|
+
<PropRow label="Label maxLines">
|
|
863
|
+
<TkVal
|
|
864
|
+
token={effectiveLabelClamp ? `line-clamp-${effectiveLabelClamp}` : 'unbounded'}
|
|
865
|
+
value={labelClampOverride === 'preset' ? `${preset.label} default` : 'override'}
|
|
866
|
+
/>
|
|
867
|
+
</PropRow>
|
|
868
|
+
{hasDescription && (
|
|
869
|
+
<>
|
|
870
|
+
<PropRow label="Desc"><TkVal token={spec.descFont} value={spec.descSize} /></PropRow>
|
|
871
|
+
<PropRow label="Desc content">
|
|
872
|
+
<TkVal token={descContent as string} value={`${descText.length} 字`} />
|
|
873
|
+
</PropRow>
|
|
874
|
+
<PropRow label="Desc maxLines">
|
|
875
|
+
<TkVal
|
|
876
|
+
token={effectiveDescClamp ? `line-clamp-${effectiveDescClamp}` : 'unbounded'}
|
|
877
|
+
value={descClampOverride === 'preset' ? `${preset.label} default` : 'override'}
|
|
878
|
+
/>
|
|
879
|
+
</PropRow>
|
|
880
|
+
<PropRow label="Desc color">
|
|
881
|
+
<span className="inline-flex items-center gap-2"><Swatch value="--fg-secondary" /><span>fg-secondary</span></span>
|
|
882
|
+
</PropRow>
|
|
883
|
+
</>
|
|
884
|
+
)}
|
|
885
|
+
</div>
|
|
886
|
+
|
|
887
|
+
{/* ALIGNMENT */}
|
|
888
|
+
<div className="px-4 py-1 pb-3">
|
|
889
|
+
<div className="py-2 border-b border-divider"><span className="text-[10px] font-semibold text-fg-muted uppercase tracking-wider">Alignment</span></div>
|
|
890
|
+
<PropRow label="outer"><TkVal token="flex items-start" /></PropRow>
|
|
891
|
+
<PropRow label="prefix align"><TkVal token={alignContainer} value={alignDesc} /></PropRow>
|
|
892
|
+
<PropRow label="prefix threshold"><TkVal token="24px" value="prefix > 24px triggers block align" /></PropRow>
|
|
893
|
+
{effectiveHasSuffix && (
|
|
894
|
+
<PropRow label="suffix align">
|
|
895
|
+
<TkVal token="h-[1lh]" value="永遠對齊第一行 label,跟 prefix 解耦" />
|
|
896
|
+
</PropRow>
|
|
897
|
+
)}
|
|
898
|
+
</div>
|
|
899
|
+
</div>
|
|
900
|
+
</div>
|
|
901
|
+
</div>
|
|
902
|
+
)
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
export const Inspector = {
|
|
906
|
+
name: '檢閱器',
|
|
907
|
+
render: () => (
|
|
908
|
+
<div className="flex flex-col gap-4">
|
|
909
|
+
<div className="flex flex-col gap-1">
|
|
910
|
+
<H3>Item Layout 檢閱器</H3>
|
|
911
|
+
<Desc>
|
|
912
|
+
Item Layout 是抽象對齊系統,不是固定元件。每個消費元件提供自己的間距(padding、gap),
|
|
913
|
+
但共用相同的三區域結構和對齊規則。切換 Consumer 可看到不同元件的預設值。
|
|
914
|
+
</Desc>
|
|
915
|
+
</div>
|
|
916
|
+
<InspectorInner />
|
|
917
|
+
</div>
|
|
918
|
+
),
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
/* ═══════════════════════════════════════════════════════════════════════════
|
|
922
|
+
2. 對齊容器(24px 閾值)
|
|
923
|
+
═══════════════════════════════════════════════════════════════════════════ */
|
|
924
|
+
|
|
925
|
+
export const AlignmentThreshold = {
|
|
926
|
+
name: '對齊容器(24px 閾值)',
|
|
927
|
+
render: () => (
|
|
928
|
+
<div className="flex flex-col gap-10">
|
|
929
|
+
<div className="flex flex-col gap-1">
|
|
930
|
+
<H3>對齊規則 — Prefix 與 Suffix 各自獨立</H3>
|
|
931
|
+
<Desc>
|
|
932
|
+
<strong>Prefix</strong> 對齊容器由 prefix 內容物大小決定:≤ 24px → 一行文字高度(inline);
|
|
933
|
+
> 24px(avatar + desc)→ label行高 + 2px + desc行高(block,對齊文字塊中心)。
|
|
934
|
+
<br />
|
|
935
|
+
<strong>Suffix</strong> 永遠用一行文字高度,**對齊第一行 label**,跟 prefix 解耦。
|
|
936
|
+
理由:suffix 內容(Tag、Chevron、時間、計數)是 label 的 metadata,不是整個 item 的——
|
|
937
|
+
業界 convention(Apple Mail / Gmail / iOS Settings / Material / Polaris)全部如此。
|
|
938
|
+
</Desc>
|
|
939
|
+
</div>
|
|
940
|
+
|
|
941
|
+
{/* Side-by-side comparison */}
|
|
942
|
+
<div className="flex gap-12 items-start">
|
|
943
|
+
{/* Inline: <= 24px */}
|
|
944
|
+
<div className="flex flex-col gap-4">
|
|
945
|
+
<div className="flex flex-col gap-1">
|
|
946
|
+
<span className="text-caption font-semibold text-foreground">≤ 24px — Inline 對齊</span>
|
|
947
|
+
<span className="text-[11px] text-fg-muted">icon (16/20px), checkbox (16/20px)</span>
|
|
948
|
+
</div>
|
|
949
|
+
|
|
950
|
+
{/* Blueprint diagram — LARGE */}
|
|
951
|
+
<div className="flex flex-col gap-3">
|
|
952
|
+
<div className="inline-flex items-stretch self-start rounded-lg overflow-hidden" style={{ height: 88, outline: `2px solid ${Z.dim.text}22` }}>
|
|
953
|
+
<div className="flex items-center justify-center shrink-0"
|
|
954
|
+
style={{ width: 72, height: '100%', background: Z.icon.bg, borderRight: `1.5px dashed ${Z.icon.border}` }}>
|
|
955
|
+
<div className="flex flex-col items-center gap-1">
|
|
956
|
+
<span className="text-[14px] font-mono font-bold" style={{ color: Z.icon.text }}>prefix</span>
|
|
957
|
+
<span className="text-[11px] font-mono font-semibold" style={{ color: Z.icon.text }}>一行文字高度</span>
|
|
958
|
+
</div>
|
|
959
|
+
</div>
|
|
960
|
+
<div className="flex items-center justify-center shrink-0"
|
|
961
|
+
style={{ width: 48, height: '100%', background: Z.gap.bg }}>
|
|
962
|
+
<span className="text-[13px] font-mono font-bold" style={{ color: Z.gap.text }}>gap</span>
|
|
963
|
+
</div>
|
|
964
|
+
<div className="flex flex-col items-center justify-center shrink-0"
|
|
965
|
+
style={{ width: 120, height: '100%', background: Z.label.bg }}>
|
|
966
|
+
<span className="text-[14px] font-mono font-bold" style={{ color: Z.label.text }}>Label</span>
|
|
967
|
+
<span className="text-[10px] font-mono mt-1 opacity-60" style={{ color: Z.gap.text }}>--item-gap-label-desc-*</span>
|
|
968
|
+
<span className="text-[12px] font-mono opacity-80" style={{ color: Z.label.text }}>description</span>
|
|
969
|
+
</div>
|
|
970
|
+
<div className="flex items-center justify-center shrink-0"
|
|
971
|
+
style={{ width: 72, height: '100%', background: Z.suffix.bg, borderLeft: `1.5px dashed ${Z.suffix.border}` }}>
|
|
972
|
+
<div className="flex flex-col items-center gap-1">
|
|
973
|
+
<span className="text-[14px] font-mono font-bold" style={{ color: Z.suffix.text }}>suffix</span>
|
|
974
|
+
<span className="text-[11px] font-mono font-semibold" style={{ color: Z.suffix.text }}>一行文字高度</span>
|
|
975
|
+
</div>
|
|
976
|
+
</div>
|
|
977
|
+
</div>
|
|
978
|
+
<span className="text-[11px] text-fg-muted">prefix center = label 第一行垂直中心,suffix 使用相同的 一行文字高度</span>
|
|
979
|
+
</div>
|
|
980
|
+
|
|
981
|
+
{/* Live example */}
|
|
982
|
+
<MenuFrame width={360}>
|
|
983
|
+
<MenuItem size="md" startIcon={Mail} description="每日寄送摘要信件" tag={<Tag size="md" color="blue">Pro</Tag>}>
|
|
984
|
+
電子郵件通知
|
|
985
|
+
</MenuItem>
|
|
986
|
+
<MenuItem size="md" startIcon={Bell} description="瀏覽器推送即時通知" tag={<Tag size="md" color="green">Free</Tag>}>
|
|
987
|
+
推送通知
|
|
988
|
+
</MenuItem>
|
|
989
|
+
</MenuFrame>
|
|
990
|
+
</div>
|
|
991
|
+
|
|
992
|
+
{/* Block: > 24px */}
|
|
993
|
+
<div className="flex flex-col gap-4">
|
|
994
|
+
<div className="flex flex-col gap-1">
|
|
995
|
+
<span className="text-caption font-semibold text-foreground">> 24px — Block 對齊</span>
|
|
996
|
+
<span className="text-[11px] text-fg-muted">avatar (32/40px) with description</span>
|
|
997
|
+
</div>
|
|
998
|
+
|
|
999
|
+
{/* Blueprint diagram — LARGE */}
|
|
1000
|
+
<div className="flex flex-col gap-3">
|
|
1001
|
+
<div className="inline-flex items-stretch self-start rounded-lg overflow-hidden" style={{ height: 88, outline: `2px solid ${Z.dim.text}22` }}>
|
|
1002
|
+
<div className="flex items-center justify-center shrink-0"
|
|
1003
|
+
style={{ width: 72, height: '100%', background: Z.icon.bg, borderRight: `1.5px dashed ${Z.icon.border}` }}>
|
|
1004
|
+
<div className="flex flex-col items-center gap-0.5">
|
|
1005
|
+
<span className="text-[14px] font-mono font-bold" style={{ color: Z.icon.text }}>prefix</span>
|
|
1006
|
+
<span className="text-[9px] font-mono" style={{ color: Z.icon.text }}>label行高</span>
|
|
1007
|
+
<span className="text-[9px] font-mono" style={{ color: Z.icon.text }}>+2px+desc行高</span>
|
|
1008
|
+
</div>
|
|
1009
|
+
</div>
|
|
1010
|
+
<div className="flex items-center justify-center shrink-0"
|
|
1011
|
+
style={{ width: 48, height: '100%', background: Z.gap.bg }}>
|
|
1012
|
+
<span className="text-[13px] font-mono font-bold" style={{ color: Z.gap.text }}>gap</span>
|
|
1013
|
+
</div>
|
|
1014
|
+
<div className="flex flex-col items-center justify-center shrink-0"
|
|
1015
|
+
style={{ width: 120, height: '100%', background: Z.label.bg }}>
|
|
1016
|
+
<span className="text-[14px] font-mono font-bold" style={{ color: Z.label.text }}>Label</span>
|
|
1017
|
+
<span className="text-[10px] font-mono mt-1 opacity-60" style={{ color: Z.gap.text }}>--item-gap-label-desc-*</span>
|
|
1018
|
+
<span className="text-[12px] font-mono opacity-80" style={{ color: Z.label.text }}>description</span>
|
|
1019
|
+
</div>
|
|
1020
|
+
<div className="flex items-start justify-center shrink-0 pt-3"
|
|
1021
|
+
style={{ width: 72, height: '100%', background: Z.suffix.bg, borderLeft: `1.5px dashed ${Z.suffix.border}` }}>
|
|
1022
|
+
<div className="flex flex-col items-center gap-1">
|
|
1023
|
+
<span className="text-[14px] font-mono font-bold" style={{ color: Z.suffix.text }}>suffix</span>
|
|
1024
|
+
<span className="text-[10px] font-mono font-semibold" style={{ color: Z.suffix.text }}>一行文字高度</span>
|
|
1025
|
+
<span className="text-[9px] font-mono opacity-80" style={{ color: Z.suffix.text }}>對齊第一行 label</span>
|
|
1026
|
+
</div>
|
|
1027
|
+
</div>
|
|
1028
|
+
</div>
|
|
1029
|
+
<span className="text-[11px] text-fg-muted">
|
|
1030
|
+
prefix center = label + description 文字塊中心(block);
|
|
1031
|
+
<strong>suffix 永遠對齊第一行 label,跟 prefix 解耦</strong>
|
|
1032
|
+
</span>
|
|
1033
|
+
</div>
|
|
1034
|
+
|
|
1035
|
+
{/* Live example */}
|
|
1036
|
+
<MenuFrame width={360}>
|
|
1037
|
+
<MenuItem size="md" avatar={{ alt: "Alice", color: "indigo" as const, hoverCard: personHover("Alice Chen", "Design team lead") }} description="Design team lead">
|
|
1038
|
+
Alice Chen
|
|
1039
|
+
</MenuItem>
|
|
1040
|
+
<MenuItem size="md" avatar={{ alt: "Bob", color: "yellow" as const, hoverCard: personHover("Bob Wang", "Backend engineer") }} description="Backend engineer">
|
|
1041
|
+
Bob Wang
|
|
1042
|
+
</MenuItem>
|
|
1043
|
+
</MenuFrame>
|
|
1044
|
+
</div>
|
|
1045
|
+
</div>
|
|
1046
|
+
|
|
1047
|
+
{/* Rules table */}
|
|
1048
|
+
<div className="flex flex-col gap-3">
|
|
1049
|
+
<span className="text-caption font-medium text-fg-secondary">對齊規則總覽</span>
|
|
1050
|
+
<div className="overflow-x-auto">
|
|
1051
|
+
<table className="border-collapse text-caption">
|
|
1052
|
+
<thead><tr><Th>對象</Th><Th>條件</Th><Th>對齊容器</Th><Th>對齊目標</Th></tr></thead>
|
|
1053
|
+
<tbody>
|
|
1054
|
+
<tr>
|
|
1055
|
+
<Td><strong>Prefix</strong></Td>
|
|
1056
|
+
<Td>≤ 24px(icon / checkbox / 小 avatar)</Td>
|
|
1057
|
+
<Td mono>一行文字高度</Td>
|
|
1058
|
+
<Td>第一行 label 垂直中心</Td>
|
|
1059
|
+
</tr>
|
|
1060
|
+
<tr>
|
|
1061
|
+
<Td><strong>Prefix</strong></Td>
|
|
1062
|
+
<Td>> 24px(avatar)+ 有 description</Td>
|
|
1063
|
+
<Td mono>label行高 + 2px + desc行高</Td>
|
|
1064
|
+
<Td>label + gap + desc 文字塊中心</Td>
|
|
1065
|
+
</tr>
|
|
1066
|
+
<tr>
|
|
1067
|
+
<Td><strong>Prefix</strong></Td>
|
|
1068
|
+
<Td>無 description</Td>
|
|
1069
|
+
<Td mono>一行文字高度</Td>
|
|
1070
|
+
<Td>強制 inline(prefix 上限 24px)</Td>
|
|
1071
|
+
</tr>
|
|
1072
|
+
<tr>
|
|
1073
|
+
<Td><strong>Suffix</strong></Td>
|
|
1074
|
+
<Td>**所有情況**</Td>
|
|
1075
|
+
<Td mono>一行文字高度</Td>
|
|
1076
|
+
<Td>第一行 label 垂直中心(跟 prefix 解耦)</Td>
|
|
1077
|
+
</tr>
|
|
1078
|
+
</tbody>
|
|
1079
|
+
</table>
|
|
1080
|
+
</div>
|
|
1081
|
+
<p className="text-[11px] text-fg-muted max-w-[720px]">
|
|
1082
|
+
※ Suffix 不跟 prefix 同步是有意的設計:suffix 是 label 的 metadata
|
|
1083
|
+
(Tag / Chevron / 時間 / 計數),不是整個 item 的。對齊 label 第一行讓使用者
|
|
1084
|
+
眼睛從 label 自然往右掃到 suffix,不被打斷。Apple Mail / Gmail / iOS Settings /
|
|
1085
|
+
Material / Polaris 全部如此。
|
|
1086
|
+
</p>
|
|
1087
|
+
</div>
|
|
1088
|
+
</div>
|
|
1089
|
+
),
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
/* ═══════════════════════════════════════════════════════════════════════════
|
|
1093
|
+
3. 閱讀模式比較
|
|
1094
|
+
═══════════════════════════════════════════════════════════════════════════ */
|
|
1095
|
+
|
|
1096
|
+
export const ReadingModes = {
|
|
1097
|
+
name: '閱讀模式比較',
|
|
1098
|
+
render: () => (
|
|
1099
|
+
<div className="flex flex-col gap-10">
|
|
1100
|
+
<div className="flex flex-col gap-1">
|
|
1101
|
+
<H3>掃描模式 vs 閱讀模式</H3>
|
|
1102
|
+
<Desc>
|
|
1103
|
+
同一套佈局結構,typography 策略依閱讀場景調整。掃描模式用於浮層(一掃而過),
|
|
1104
|
+
閱讀模式用於頁面/表單(仔細閱讀)。差異在行高和 description 字體。
|
|
1105
|
+
</Desc>
|
|
1106
|
+
</div>
|
|
1107
|
+
|
|
1108
|
+
{/* Side-by-side at all sizes */}
|
|
1109
|
+
<div className="flex gap-12 items-start">
|
|
1110
|
+
{/* Scanning */}
|
|
1111
|
+
<div className="flex flex-col gap-4">
|
|
1112
|
+
<div className="flex flex-col gap-1">
|
|
1113
|
+
<span className="text-caption font-semibold text-foreground">掃描模式(Scanning)</span>
|
|
1114
|
+
<span className="text-[11px] text-fg-muted">浮層 / overlay — MenuItem, ComboboxItem</span>
|
|
1115
|
+
</div>
|
|
1116
|
+
{SIZES.map((sz) => (
|
|
1117
|
+
<div key={sz} className="flex items-start gap-3">
|
|
1118
|
+
<span className="text-[12px] text-fg-muted w-6 shrink-0 pt-2 font-mono font-semibold">{sz}</span>
|
|
1119
|
+
<MenuFrame width={300}>
|
|
1120
|
+
<MenuItem size={sz} startIcon={Mail} description="每日寄送摘要信件">
|
|
1121
|
+
電子郵件通知
|
|
1122
|
+
</MenuItem>
|
|
1123
|
+
</MenuFrame>
|
|
1124
|
+
</div>
|
|
1125
|
+
))}
|
|
1126
|
+
<div className="mt-1 flex flex-col gap-1 text-[11px] text-fg-muted">
|
|
1127
|
+
<p><strong>Label:</strong> leading-compact (1.3)</p>
|
|
1128
|
+
<p><strong>Desc:</strong> 降一級字體 + fg-secondary</p>
|
|
1129
|
+
<p><strong>Gap:</strong> --item-gap-label-desc-scanning (2px,sm/md)/ -scanning-lg (lg)</p>
|
|
1130
|
+
</div>
|
|
1131
|
+
</div>
|
|
1132
|
+
|
|
1133
|
+
{/* Reading */}
|
|
1134
|
+
<div className="flex flex-col gap-4">
|
|
1135
|
+
<div className="flex flex-col gap-1">
|
|
1136
|
+
<span className="text-caption font-semibold text-foreground">閱讀模式(Reading)</span>
|
|
1137
|
+
<span className="text-[11px] text-fg-muted">頁面 / 表單 — SelectionItem (Checkbox/RadioGroup)</span>
|
|
1138
|
+
</div>
|
|
1139
|
+
{SIZES.map((sz) => (
|
|
1140
|
+
<div key={sz} className="flex items-start gap-3">
|
|
1141
|
+
<span className="text-[12px] text-fg-muted w-6 shrink-0 pt-2 font-mono font-semibold">{sz}</span>
|
|
1142
|
+
<div className="w-[300px]">
|
|
1143
|
+
<SelectionItem
|
|
1144
|
+
size={sz}
|
|
1145
|
+
control={<Checkbox size={sz} checked={true} />}
|
|
1146
|
+
label="電子郵件通知"
|
|
1147
|
+
description="每日寄送摘要信件到您的電子信箱"
|
|
1148
|
+
/>
|
|
1149
|
+
</div>
|
|
1150
|
+
</div>
|
|
1151
|
+
))}
|
|
1152
|
+
<div className="mt-1 flex flex-col gap-1 text-[11px] text-fg-muted">
|
|
1153
|
+
<p><strong>Label:</strong> default line-height (1.5)</p>
|
|
1154
|
+
<p><strong>Desc:</strong> 同字體 + fg-secondary(僅顏色區分)</p>
|
|
1155
|
+
<p><strong>Gap:</strong> --item-gap-label-desc-reading (2px,sm/md)/ -reading-lg (lg)</p>
|
|
1156
|
+
</div>
|
|
1157
|
+
</div>
|
|
1158
|
+
</div>
|
|
1159
|
+
|
|
1160
|
+
{/* Token comparison table */}
|
|
1161
|
+
<div className="flex flex-col gap-3">
|
|
1162
|
+
<span className="text-caption font-medium text-fg-secondary">Typography Token 對照表</span>
|
|
1163
|
+
<div className="overflow-x-auto">
|
|
1164
|
+
<table className="border-collapse text-caption">
|
|
1165
|
+
<thead>
|
|
1166
|
+
<tr>
|
|
1167
|
+
<Th>Size</Th>
|
|
1168
|
+
<Th>掃描 — Label</Th>
|
|
1169
|
+
<Th>掃描 — Desc</Th>
|
|
1170
|
+
<Th>閱讀 — Label</Th>
|
|
1171
|
+
<Th>閱讀 — Desc</Th>
|
|
1172
|
+
<Th>Label-Desc Gap</Th>
|
|
1173
|
+
</tr>
|
|
1174
|
+
</thead>
|
|
1175
|
+
<tbody>
|
|
1176
|
+
{SIZES.map((sz) => {
|
|
1177
|
+
const sc = SCANNING_SPECS[sz]
|
|
1178
|
+
const rd = READING_SPECS[sz]
|
|
1179
|
+
return (
|
|
1180
|
+
<tr key={sz}>
|
|
1181
|
+
<Td mono>{sz}</Td>
|
|
1182
|
+
<Td><TkVal token={sc.labelFont} value={`${sc.labelSize}, lh ${sc.labelLh}`} /></Td>
|
|
1183
|
+
<Td><TkVal token={sc.descFont} value={`${sc.descSize}, lh ${sc.descLh}`} /></Td>
|
|
1184
|
+
<Td><TkVal token={rd.labelFont} value={`${rd.labelSize}, lh ${rd.labelLh}`} /></Td>
|
|
1185
|
+
<Td><TkVal token={rd.descFont} value={`${rd.descSize}, lh ${rd.descLh}`} /></Td>
|
|
1186
|
+
<Td mono>--item-gap-label-desc-* (2px)</Td>
|
|
1187
|
+
</tr>
|
|
1188
|
+
)
|
|
1189
|
+
})}
|
|
1190
|
+
</tbody>
|
|
1191
|
+
</table>
|
|
1192
|
+
</div>
|
|
1193
|
+
</div>
|
|
1194
|
+
</div>
|
|
1195
|
+
),
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
/* ═══════════════════════════════════════════════════════════════════════════
|
|
1199
|
+
4. Icon 色彩 + 消費元件預設
|
|
1200
|
+
═══════════════════════════════════════════════════════════════════════════ */
|
|
1201
|
+
|
|
1202
|
+
export const IconColorsAndPresets = {
|
|
1203
|
+
name: '圖示色彩 + 消費元件預設',
|
|
1204
|
+
render: () => (
|
|
1205
|
+
<div className="flex flex-col gap-10">
|
|
1206
|
+
<div className="flex flex-col gap-1">
|
|
1207
|
+
<H3>Icon 色彩原則</H3>
|
|
1208
|
+
<Desc>
|
|
1209
|
+
一條統一規則:icon 代表 label 內容或類別時,與 label 同色(foreground)。
|
|
1210
|
+
icon 純粹指示方向/展開/導覽時,fg-muted。Suffix value 文字與 label 同字體大小,只降色不降級。
|
|
1211
|
+
</Desc>
|
|
1212
|
+
</div>
|
|
1213
|
+
|
|
1214
|
+
{/* Color rule table */}
|
|
1215
|
+
<div className="flex flex-col gap-3">
|
|
1216
|
+
<span className="text-caption font-medium text-fg-secondary">色彩判斷規則</span>
|
|
1217
|
+
<div className="overflow-x-auto">
|
|
1218
|
+
<table className="border-collapse text-caption">
|
|
1219
|
+
<thead><tr><Th>判斷</Th><Th>顏色</Th><Th>範例</Th></tr></thead>
|
|
1220
|
+
<tbody>
|
|
1221
|
+
<tr>
|
|
1222
|
+
<Td>代表內容/類別</Td>
|
|
1223
|
+
<Td>
|
|
1224
|
+
<span className="inline-flex items-center gap-2">
|
|
1225
|
+
<Swatch value="--foreground" />
|
|
1226
|
+
<span className="font-mono">foreground(繼承)</span>
|
|
1227
|
+
</span>
|
|
1228
|
+
</Td>
|
|
1229
|
+
<Td>Mail, Settings, Star</Td>
|
|
1230
|
+
</tr>
|
|
1231
|
+
<tr>
|
|
1232
|
+
<Td>代表危險操作</Td>
|
|
1233
|
+
<Td>
|
|
1234
|
+
<span className="inline-flex items-center gap-2">
|
|
1235
|
+
<Swatch value="--error" />
|
|
1236
|
+
<span className="font-mono">text-error(與 label 同色)</span>
|
|
1237
|
+
</span>
|
|
1238
|
+
</Td>
|
|
1239
|
+
<Td>Trash2 + 紅色 label</Td>
|
|
1240
|
+
</tr>
|
|
1241
|
+
<tr>
|
|
1242
|
+
<Td>指示方向/展開</Td>
|
|
1243
|
+
<Td>
|
|
1244
|
+
<span className="inline-flex items-center gap-2">
|
|
1245
|
+
<Swatch value="--fg-muted" />
|
|
1246
|
+
<span className="font-mono">text-fg-muted</span>
|
|
1247
|
+
</span>
|
|
1248
|
+
</Td>
|
|
1249
|
+
<Td>ChevronRight, ChevronDown, ExternalLink</Td>
|
|
1250
|
+
</tr>
|
|
1251
|
+
<tr>
|
|
1252
|
+
<Td>suffix value 文字</Td>
|
|
1253
|
+
<Td>
|
|
1254
|
+
<span className="inline-flex items-center gap-2">
|
|
1255
|
+
<Swatch value="--fg-muted" />
|
|
1256
|
+
<span className="font-mono">fg-muted, 同 label 字體大小</span>
|
|
1257
|
+
</span>
|
|
1258
|
+
</Td>
|
|
1259
|
+
<Td>"深色"、"已啟用"</Td>
|
|
1260
|
+
</tr>
|
|
1261
|
+
<tr>
|
|
1262
|
+
<Td>disabled</Td>
|
|
1263
|
+
<Td>
|
|
1264
|
+
<span className="inline-flex items-center gap-2">
|
|
1265
|
+
<Swatch value="--fg-disabled" />
|
|
1266
|
+
<span className="font-mono">text-fg-disabled</span>
|
|
1267
|
+
</span>
|
|
1268
|
+
</Td>
|
|
1269
|
+
<Td>全部統一</Td>
|
|
1270
|
+
</tr>
|
|
1271
|
+
</tbody>
|
|
1272
|
+
</table>
|
|
1273
|
+
</div>
|
|
1274
|
+
</div>
|
|
1275
|
+
|
|
1276
|
+
{/* Visual reference — live examples */}
|
|
1277
|
+
<div className="flex flex-col gap-4">
|
|
1278
|
+
<span className="text-caption font-medium text-fg-secondary">視覺參考</span>
|
|
1279
|
+
<div className="flex gap-8 items-start">
|
|
1280
|
+
{/* Prefix icons: inherit foreground */}
|
|
1281
|
+
<div className="flex flex-col gap-2">
|
|
1282
|
+
<span className="text-[11px] text-fg-muted font-medium">Prefix icon = foreground(代表內容)</span>
|
|
1283
|
+
<MenuFrame width={260}>
|
|
1284
|
+
<MenuItem size="md" startIcon={Mail}>電子郵件</MenuItem>
|
|
1285
|
+
<MenuItem size="md" startIcon={Settings}>設定</MenuItem>
|
|
1286
|
+
<MenuItem size="md" startIcon={Star}>收藏</MenuItem>
|
|
1287
|
+
</MenuFrame>
|
|
1288
|
+
</div>
|
|
1289
|
+
|
|
1290
|
+
{/* Suffix indicator: fg-muted */}
|
|
1291
|
+
<div className="flex flex-col gap-2">
|
|
1292
|
+
<span className="text-[11px] text-fg-muted font-medium">Suffix indicator = fg-muted(指示方向)</span>
|
|
1293
|
+
<MenuFrame width={280}>
|
|
1294
|
+
<MenuItem
|
|
1295
|
+
size="md"
|
|
1296
|
+
startIcon={Globe}
|
|
1297
|
+
endContent={
|
|
1298
|
+
<div className="h-[1lh] flex items-center gap-1 ml-auto">
|
|
1299
|
+
<span className="text-body text-fg-muted">English</span>
|
|
1300
|
+
<ChevronRight size={16} className="text-fg-muted" />
|
|
1301
|
+
</div>
|
|
1302
|
+
}
|
|
1303
|
+
>
|
|
1304
|
+
語言
|
|
1305
|
+
</MenuItem>
|
|
1306
|
+
<MenuItem
|
|
1307
|
+
size="md"
|
|
1308
|
+
startIcon={Lock}
|
|
1309
|
+
endContent={
|
|
1310
|
+
<div className="h-[1lh] flex items-center ml-auto">
|
|
1311
|
+
<ChevronRight size={16} className="text-fg-muted" />
|
|
1312
|
+
</div>
|
|
1313
|
+
}
|
|
1314
|
+
>
|
|
1315
|
+
隱私設定
|
|
1316
|
+
</MenuItem>
|
|
1317
|
+
</MenuFrame>
|
|
1318
|
+
</div>
|
|
1319
|
+
|
|
1320
|
+
{/* Danger: same color as label */}
|
|
1321
|
+
<div className="flex flex-col gap-2">
|
|
1322
|
+
<span className="text-[11px] text-fg-muted font-medium">危險操作 = 與 label 同色(text-error)</span>
|
|
1323
|
+
<MenuFrame width={260}>
|
|
1324
|
+
<MenuItem size="md" startIcon={Trash2} className="text-error">
|
|
1325
|
+
刪除專案
|
|
1326
|
+
</MenuItem>
|
|
1327
|
+
</MenuFrame>
|
|
1328
|
+
</div>
|
|
1329
|
+
</div>
|
|
1330
|
+
</div>
|
|
1331
|
+
|
|
1332
|
+
{/* Consumer preset comparison */}
|
|
1333
|
+
<div className="flex flex-col gap-4">
|
|
1334
|
+
<div className="flex flex-col gap-1">
|
|
1335
|
+
<span className="text-caption font-semibold text-foreground">消費元件預設比較</span>
|
|
1336
|
+
<span className="text-[11px] text-fg-muted">每個元件自訂間距,但結構和對齊規則不變</span>
|
|
1337
|
+
</div>
|
|
1338
|
+
|
|
1339
|
+
<div className="overflow-x-auto">
|
|
1340
|
+
<table className="border-collapse text-caption">
|
|
1341
|
+
<thead>
|
|
1342
|
+
<tr>
|
|
1343
|
+
<Th>屬性</Th>
|
|
1344
|
+
<Th>MenuItem</Th>
|
|
1345
|
+
<Th>SelectionItem</Th>
|
|
1346
|
+
<Th>ListItem</Th>
|
|
1347
|
+
</tr>
|
|
1348
|
+
</thead>
|
|
1349
|
+
<tbody>
|
|
1350
|
+
{[
|
|
1351
|
+
{ label: '場景', k: 'desc' as const },
|
|
1352
|
+
{ label: '閱讀模式', k: 'mode' as const },
|
|
1353
|
+
{ label: 'padding-y', k: 'py' as const },
|
|
1354
|
+
{ label: 'padding-x', k: 'px' as const },
|
|
1355
|
+
{ label: 'prefix-content gap', k: 'gap' as const },
|
|
1356
|
+
{ label: 'suffix gap', k: 'suffixGap' as const },
|
|
1357
|
+
].map(({ label, k }) => (
|
|
1358
|
+
<tr key={label}>
|
|
1359
|
+
<Td>{label}</Td>
|
|
1360
|
+
<Td mono>{CONSUMERS.MenuItem[k]}</Td>
|
|
1361
|
+
<Td mono>{CONSUMERS.SelectionItem[k]}</Td>
|
|
1362
|
+
<Td mono>{CONSUMERS.ListItem[k]}</Td>
|
|
1363
|
+
</tr>
|
|
1364
|
+
))}
|
|
1365
|
+
</tbody>
|
|
1366
|
+
</table>
|
|
1367
|
+
</div>
|
|
1368
|
+
</div>
|
|
1369
|
+
|
|
1370
|
+
{/* Live consumer examples */}
|
|
1371
|
+
<div className="flex flex-col gap-4">
|
|
1372
|
+
<span className="text-caption font-medium text-fg-secondary">消費元件即時範例(md size)</span>
|
|
1373
|
+
<div className="flex gap-8 items-start">
|
|
1374
|
+
<div className="flex flex-col gap-2">
|
|
1375
|
+
<span className="text-[11px] text-fg-muted font-medium">MenuItem</span>
|
|
1376
|
+
<MenuFrame width={280}>
|
|
1377
|
+
<MenuItem size="md" startIcon={Mail} description="每日寄送摘要信件">
|
|
1378
|
+
電子郵件通知
|
|
1379
|
+
</MenuItem>
|
|
1380
|
+
<MenuItem size="md" startIcon={Bell}>
|
|
1381
|
+
推送通知
|
|
1382
|
+
</MenuItem>
|
|
1383
|
+
</MenuFrame>
|
|
1384
|
+
</div>
|
|
1385
|
+
|
|
1386
|
+
<div className="flex flex-col gap-2">
|
|
1387
|
+
<span className="text-[11px] text-fg-muted font-medium">SelectionItem</span>
|
|
1388
|
+
<div className="w-[280px]">
|
|
1389
|
+
<SelectionItem
|
|
1390
|
+
size="md"
|
|
1391
|
+
control={<Checkbox size="md" checked={true} />}
|
|
1392
|
+
label="電子郵件通知"
|
|
1393
|
+
description="每日寄送摘要信件"
|
|
1394
|
+
/>
|
|
1395
|
+
<SelectionItem
|
|
1396
|
+
size="md"
|
|
1397
|
+
control={<Checkbox size="md" />}
|
|
1398
|
+
label="推送通知"
|
|
1399
|
+
/>
|
|
1400
|
+
</div>
|
|
1401
|
+
</div>
|
|
1402
|
+
|
|
1403
|
+
<div className="flex flex-col gap-2">
|
|
1404
|
+
<span className="text-[11px] text-fg-muted font-medium">ListItem(模擬)</span>
|
|
1405
|
+
<div className="w-[280px] rounded-lg border border-divider overflow-hidden bg-surface">
|
|
1406
|
+
<ListItemPreview
|
|
1407
|
+
size="md"
|
|
1408
|
+
startIcon={Mail}
|
|
1409
|
+
label="電子郵件通知"
|
|
1410
|
+
description="每日寄送摘要信件"
|
|
1411
|
+
suffix={<ChevronRight size={16} className="text-fg-muted" />}
|
|
1412
|
+
/>
|
|
1413
|
+
<div className="border-t border-divider" />
|
|
1414
|
+
<ListItemPreview
|
|
1415
|
+
size="md"
|
|
1416
|
+
startIcon={Bell}
|
|
1417
|
+
label="推送通知"
|
|
1418
|
+
suffix={<ChevronRight size={16} className="text-fg-muted" />}
|
|
1419
|
+
/>
|
|
1420
|
+
</div>
|
|
1421
|
+
</div>
|
|
1422
|
+
</div>
|
|
1423
|
+
</div>
|
|
1424
|
+
</div>
|
|
1425
|
+
),
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
/* ═══════════════════════════════════════════════════════════════════════════
|
|
1429
|
+
5. Icon Action Primitive 決策樹(設計準則 2026-04-22)
|
|
1430
|
+
═══════════════════════════════════════════════════════════════════════════ */
|
|
1431
|
+
|
|
1432
|
+
export const IconActionPrimitiveDecision = {
|
|
1433
|
+
name: '圖示動作通用零件決策',
|
|
1434
|
+
render: () => (
|
|
1435
|
+
<div className="flex flex-col gap-10">
|
|
1436
|
+
<div className="flex flex-col gap-1">
|
|
1437
|
+
<H3>Icon 相關動作用哪個 primitive?(3 步決策)</H3>
|
|
1438
|
+
<Desc>
|
|
1439
|
+
DS 跨元件 icon action 的設計準則。接到「要放一個 icon 可點擊」的需求,跑下方 3 步決策樹——
|
|
1440
|
+
不要直覺寫 <code className="font-mono"><button><X /></button></code>。Primitive 選錯會造成 same-row 幾何不一致、gap token 被吃掉、
|
|
1441
|
+
或 chrome corner close 無法跟 refresh / share 並排分群。
|
|
1442
|
+
</Desc>
|
|
1443
|
+
</div>
|
|
1444
|
+
|
|
1445
|
+
{/* Decision tree visual */}
|
|
1446
|
+
<div className="flex flex-col gap-3">
|
|
1447
|
+
<span className="text-caption font-semibold text-foreground">決策樹</span>
|
|
1448
|
+
<div className="overflow-x-auto">
|
|
1449
|
+
<table className="border-collapse text-caption">
|
|
1450
|
+
<thead>
|
|
1451
|
+
<tr>
|
|
1452
|
+
<Th>步驟</Th>
|
|
1453
|
+
<Th>問題</Th>
|
|
1454
|
+
<Th>結果</Th>
|
|
1455
|
+
</tr>
|
|
1456
|
+
</thead>
|
|
1457
|
+
<tbody>
|
|
1458
|
+
<tr>
|
|
1459
|
+
<Td mono>Q1</Td>
|
|
1460
|
+
<Td>Icon 點了要做事嗎?</Td>
|
|
1461
|
+
<Td>
|
|
1462
|
+
<strong>否</strong> → Decorative indicator(<code className="font-mono"><Icon aria-hidden pointer-events-none /></code>)
|
|
1463
|
+
<br /><strong>是</strong> → 繼續 Q2
|
|
1464
|
+
</Td>
|
|
1465
|
+
</tr>
|
|
1466
|
+
<tr>
|
|
1467
|
+
<Td mono>Q2</Td>
|
|
1468
|
+
<Td>位置在哪?</Td>
|
|
1469
|
+
<Td>
|
|
1470
|
+
Host 內部(chrome padding / content flow / row inline suffix)→ <strong>Inline Action</strong>
|
|
1471
|
+
<br />Row 獨立 action slot → 看 Q3
|
|
1472
|
+
<br />Action group region(toolbar / chrome corner / standalone)→ <strong>Button</strong>
|
|
1473
|
+
</Td>
|
|
1474
|
+
</tr>
|
|
1475
|
+
<tr>
|
|
1476
|
+
<Td mono>Q3</Td>
|
|
1477
|
+
<Td>Row 多大?</Td>
|
|
1478
|
+
<Td>
|
|
1479
|
+
≤ 24(compact / xs row)→ <strong>Inline Action</strong>(Button xs 24 會填滿 row,失去呼吸)
|
|
1480
|
+
<br />≥ 28(sm / md / lg row)→ <strong>Button iconOnly size="xs"(24 固定,不放大)</strong>
|
|
1481
|
+
<br /><span className="text-fg-muted">例外:FileItem compact(row 24)用 Button xs iconOnly — 2026-04-23 user 拍板 rich + compact 同 primitive 統一(field-height-xs 容器 + data-unbounded 收斂;見下表 FileItem 兩列),不套本則 ≤24 規則</span>
|
|
1482
|
+
</Td>
|
|
1483
|
+
</tr>
|
|
1484
|
+
</tbody>
|
|
1485
|
+
</table>
|
|
1486
|
+
</div>
|
|
1487
|
+
<p className="text-[11px] text-fg-muted max-w-[780px] leading-relaxed">
|
|
1488
|
+
<strong>核心原則:Row dedicated action 永遠 ≤ 24px cap</strong>,不隨 row tier 放大——超過 24 的 action
|
|
1489
|
+
會搶 content 視覺焦點,違反「資料 > 行動」的視覺階層(世界級對照:Linear / Notion / Figma 全部 ≤ 24)。
|
|
1490
|
+
</p>
|
|
1491
|
+
</div>
|
|
1492
|
+
|
|
1493
|
+
{/* Real case table */}
|
|
1494
|
+
<div className="flex flex-col gap-3">
|
|
1495
|
+
<span className="text-caption font-semibold text-foreground">實戰情境對照</span>
|
|
1496
|
+
<div className="overflow-x-auto">
|
|
1497
|
+
<table className="border-collapse text-caption">
|
|
1498
|
+
<thead>
|
|
1499
|
+
<tr>
|
|
1500
|
+
<Th>情境</Th>
|
|
1501
|
+
<Th>位置</Th>
|
|
1502
|
+
<Th>Primitive</Th>
|
|
1503
|
+
<Th>理由</Th>
|
|
1504
|
+
</tr>
|
|
1505
|
+
</thead>
|
|
1506
|
+
<tbody>
|
|
1507
|
+
<tr><Td>Input / Combobox clear X</Td><Td>Field chrome padding</Td><Td mono>Inline Action</Td><Td>Embedded in host</Td></tr>
|
|
1508
|
+
<tr><Td>Tag dismiss X</Td><Td>Pill body</Td><Td mono>Inline Action</Td><Td>Colored host,繼承顏色</Td></tr>
|
|
1509
|
+
<tr><Td>Menu / TreeView suffix action</Td><Td>Row inline flow</Td><Td mono>Inline Action</Td><Td>Inline with content</Td></tr>
|
|
1510
|
+
<tr><Td>SidebarGroup header chevron</Td><Td>Aux toggle</Td><Td mono>Inline Action</Td><Td>Inline header toggle</Td></tr>
|
|
1511
|
+
<tr><Td><strong>FileItem compact</strong>(row 24)</Td><Td>Row slot</Td><Td mono>Button xs iconOnly</Td><Td>2026-04-23 user 統一 rich + compact 同 primitive(field-height-xs 容器 + data-unbounded 收斂)</Td></tr>
|
|
1512
|
+
<tr><Td><strong>FileItem rich</strong>(row 56)</Td><Td>Row slot</Td><Td mono>Button xs iconOnly</Td><Td>≤ 24 cap,不放大</Td></tr>
|
|
1513
|
+
<tr><Td><strong>DataTable row action</strong></Td><Td>Row dedicated column</Td><Td mono>Button xs iconOnly</Td><Td>≤ 24 cap(跨 tier 固定)</Td></tr>
|
|
1514
|
+
<tr><Td><strong>Dialog / Sheet chrome corner close</strong></Td><Td>Action group region</Td><Td mono>Button sm iconOnly dismiss</Td><Td>corner 屬 action group,可與 refresh / share 並排</Td></tr>
|
|
1515
|
+
<tr><Td><strong>Alert / Toast / Coachmark close</strong></Td><Td>Action group region</Td><Td mono>Button sm iconOnly dismiss</Td><Td>同上</Td></tr>
|
|
1516
|
+
<tr><Td><strong>Popover close</strong></Td><Td>Action group region</Td><Td mono>Button sm iconOnly dismiss</Td><Td>同上</Td></tr>
|
|
1517
|
+
</tbody>
|
|
1518
|
+
</table>
|
|
1519
|
+
</div>
|
|
1520
|
+
</div>
|
|
1521
|
+
|
|
1522
|
+
{/* Dismiss X canonical */}
|
|
1523
|
+
<div className="flex flex-col gap-3">
|
|
1524
|
+
<span className="text-caption font-semibold text-foreground">Dismiss 嚴格定義 — X close only</span>
|
|
1525
|
+
<Desc>
|
|
1526
|
+
<code className="font-mono">dismiss</code> prop 僅屬 <strong>X(close)</strong>icon——
|
|
1527
|
+
「關閉 surface / 忽略訊息」的語意。Trash / Delete / Clear / Remove 都<strong>不算 dismiss</strong>,
|
|
1528
|
+
即使視覺上也是 icon-only button,callback 用 <code className="font-mono">onDelete</code> / <code className="font-mono">onRemove</code> / <code className="font-mono">onClear</code>。
|
|
1529
|
+
世界級對照:Material IconButton close / Polaris Banner.onDismiss / Apple HIG window close — 全部 icon = X。
|
|
1530
|
+
</Desc>
|
|
1531
|
+
<div className="overflow-x-auto">
|
|
1532
|
+
<table className="border-collapse text-caption">
|
|
1533
|
+
<thead>
|
|
1534
|
+
<tr>
|
|
1535
|
+
<Th>語意</Th>
|
|
1536
|
+
<Th>Icon</Th>
|
|
1537
|
+
<Th>Callback</Th>
|
|
1538
|
+
<Th>Primitive</Th>
|
|
1539
|
+
</tr>
|
|
1540
|
+
</thead>
|
|
1541
|
+
<tbody>
|
|
1542
|
+
<tr><Td>Dismiss(關閉 surface)</Td><Td mono>X</Td><Td mono>onClose / onDismiss</Td><Td>Button `dismiss` prop(chrome corner)或 Inline Action(chrome padding)</Td></tr>
|
|
1543
|
+
<tr><Td>Delete(刪除資料)</Td><Td mono>Trash2</Td><Td mono>onDelete</Td><Td>依 Q2/Q3 決策,<strong>不套 dismiss prop</strong></Td></tr>
|
|
1544
|
+
<tr><Td>Clear(清空欄位)</Td><Td mono>X</Td><Td mono>onClear</Td><Td>Inline Action(Field chrome padding)</Td></tr>
|
|
1545
|
+
<tr><Td>Remove(從集合移除)</Td><Td mono>X / Trash2</Td><Td mono>onRemove</Td><Td>依 Q2/Q3 決策</Td></tr>
|
|
1546
|
+
</tbody>
|
|
1547
|
+
</table>
|
|
1548
|
+
</div>
|
|
1549
|
+
</div>
|
|
1550
|
+
|
|
1551
|
+
{/* Live case: Alert chrome corner action group */}
|
|
1552
|
+
<div className="flex flex-col gap-3">
|
|
1553
|
+
<span className="text-caption font-semibold text-foreground">Live case — Alert chrome corner action group 佈局</span>
|
|
1554
|
+
<Desc>
|
|
1555
|
+
Chrome corner close 屬 <strong>action group region</strong>——實務上 close 左側可加 refresh / share 等
|
|
1556
|
+
輔助動作(用 Separator 分群),所以必須用 Button iconOnly(與群內其他 action 同 primitive),不可用 Inline Action。
|
|
1557
|
+
</Desc>
|
|
1558
|
+
<div className="flex items-start gap-3 p-4 rounded-md border border-border bg-surface-raised max-w-lg">
|
|
1559
|
+
<div className="flex-1 flex flex-col gap-1">
|
|
1560
|
+
<span className="text-body font-semibold text-foreground">新版本可用</span>
|
|
1561
|
+
<span className="text-caption text-fg-muted">點擊重新整理載入最新版。</span>
|
|
1562
|
+
</div>
|
|
1563
|
+
<div className="flex items-center gap-1">
|
|
1564
|
+
<Button variant="text" size="sm" iconOnly startIcon={RefreshCw} aria-label="重新整理" />
|
|
1565
|
+
<Button variant="text" size="sm" iconOnly startIcon={Share2} aria-label="分享" />
|
|
1566
|
+
<Separator orientation="vertical" className="h-5 mx-1" />
|
|
1567
|
+
<Button variant="text" size="sm" dismiss startIcon={X} aria-label="關閉" />
|
|
1568
|
+
</div>
|
|
1569
|
+
</div>
|
|
1570
|
+
<p className="text-[11px] text-fg-muted max-w-[780px] leading-relaxed">
|
|
1571
|
+
✅ refresh / share / close 都是 Button sm iconOnly,Separator 分群(action 群 vs dismiss 群)。close 套
|
|
1572
|
+
<code className="font-mono"> dismiss</code> prop 自動弱化(icon fg-muted → hover foreground)。
|
|
1573
|
+
<br />❌ 禁止把 close 改寫成 Inline Action(會造成 same-row primitive 混用,gap 視覺斷裂)。
|
|
1574
|
+
</p>
|
|
1575
|
+
</div>
|
|
1576
|
+
|
|
1577
|
+
{/* Same-row consistency */}
|
|
1578
|
+
<div className="flex flex-col gap-3">
|
|
1579
|
+
<span className="text-caption font-semibold text-foreground">Same-row consistency — 同 row 所有 icon action 必同一類</span>
|
|
1580
|
+
<Desc>
|
|
1581
|
+
同一 action row(suffix slot / chrome corner)<strong>所有 icon action 必用相同 primitive</strong>——
|
|
1582
|
+
不混 Inline Action + Button iconOnly。混用會造成 box 尺寸不一致,gap token 視覺被吃掉(參考
|
|
1583
|
+
<code className="font-mono"> .claude/rules/ui-development.md </code>「同 flex 列的互動 slot 幾何鐵律」)。
|
|
1584
|
+
</Desc>
|
|
1585
|
+
<div className="flex flex-col gap-3 max-w-xl">
|
|
1586
|
+
<div className="flex items-center gap-3 px-3 py-2 rounded-md border border-border bg-surface">
|
|
1587
|
+
<span className="flex-1 text-caption text-fg-secondary">✅ 都用 Button xs iconOnly(24 固定,gap-1 穩定)</span>
|
|
1588
|
+
<div className="flex items-center gap-1">
|
|
1589
|
+
<Button variant="text" size="xs" iconOnly startIcon={RotateCw} aria-label="重試" />
|
|
1590
|
+
<Button variant="text" size="xs" iconOnly startIcon={Download} aria-label="下載" />
|
|
1591
|
+
<Button variant="text" size="xs" iconOnly startIcon={MoreVertical} aria-label="更多" />
|
|
1592
|
+
</div>
|
|
1593
|
+
</div>
|
|
1594
|
+
<div className="flex items-center gap-3 px-3 py-2 rounded-md border border-border bg-surface">
|
|
1595
|
+
<span className="flex-1 text-caption text-fg-secondary">✅ compact row:都用 Inline Action(icon 16,hover-bg 18,size="sm",gap-2)</span>
|
|
1596
|
+
<div className="flex items-center gap-2">
|
|
1597
|
+
<ItemInlineActionButton icon={RotateCw} size="sm" aria-label="重試" />
|
|
1598
|
+
<ItemInlineActionButton icon={Download} size="sm" aria-label="下載" />
|
|
1599
|
+
<ItemInlineActionButton icon={MoreVertical} size="sm" aria-label="更多" />
|
|
1600
|
+
</div>
|
|
1601
|
+
</div>
|
|
1602
|
+
<div className="flex items-center gap-3 px-3 py-2 rounded-md border border-error bg-surface">
|
|
1603
|
+
<span className="flex-1 text-caption text-error-text">❌ 禁止混 Inline Action + Button(box 尺寸不一致)</span>
|
|
1604
|
+
<div className="flex items-center gap-2">
|
|
1605
|
+
<ItemInlineActionButton icon={RotateCw} size="sm" aria-label="重試" />
|
|
1606
|
+
<Button variant="text" size="xs" iconOnly startIcon={Download} aria-label="下載" />
|
|
1607
|
+
</div>
|
|
1608
|
+
</div>
|
|
1609
|
+
</div>
|
|
1610
|
+
</div>
|
|
1611
|
+
|
|
1612
|
+
{/* Overflow menu icon canonical */}
|
|
1613
|
+
<div className="flex flex-col gap-3">
|
|
1614
|
+
<span className="text-caption font-semibold text-foreground">Overflow menu icon — <code className="font-mono">MoreVertical</code>,禁用 <code className="font-mono">MoreHorizontal</code></span>
|
|
1615
|
+
<Desc>
|
|
1616
|
+
Overflow menu(「更多動作」下拉)一律用 <strong>MoreVertical</strong>(縱向三點)。
|
|
1617
|
+
<code className="font-mono"> MoreHorizontal</code>(橫向三點)只保留給 Breadcrumb path ellipsis 語意
|
|
1618
|
+
(「沿路徑省略中間項」),不得用於 overflow menu。世界級對照:Linear / Notion / GitHub / Figma 全部如此。
|
|
1619
|
+
</Desc>
|
|
1620
|
+
</div>
|
|
1621
|
+
</div>
|
|
1622
|
+
),
|
|
1623
|
+
}
|