@astryxdesign/core 0.1.2 → 0.1.3-canary.1e94ba0
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/CHANGELOG.md +165 -0
- package/README.md +12 -12
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +11 -5
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +24 -5
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +31 -12
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +0 -1
- package/dist/Calendar/Calendar.d.ts +5 -4
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +82 -43
- package/dist/Calendar/hooks/index.d.ts +0 -2
- package/dist/Calendar/hooks/index.d.ts.map +1 -1
- package/dist/Calendar/hooks/index.js +1 -2
- package/dist/Calendar/index.d.ts +3 -3
- package/dist/Calendar/index.d.ts.map +1 -1
- package/dist/Calendar/index.js +1 -1
- package/dist/Calendar/styles.d.ts +3 -9
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +3 -11
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +17 -3
- package/dist/Center/Center.d.ts +11 -1
- package/dist/Center/Center.d.ts.map +1 -1
- package/dist/Center/Center.js +9 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +0 -1
- package/dist/Chat/ChatMessageList.d.ts +14 -1
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +2 -0
- package/dist/Chat/useTriggerMenu.d.ts +8 -1
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +15 -3
- package/dist/CheckboxInput/CheckboxInput.d.ts +23 -2
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +51 -9
- package/dist/CheckboxList/CheckboxList.d.ts +13 -1
- package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxList.js +39 -9
- package/dist/CheckboxList/CheckboxListContext.d.ts +7 -0
- package/dist/CheckboxList/CheckboxListContext.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +0 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +9 -5
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +51 -37
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +5 -5
- package/dist/ContextMenu/ContextMenu.d.ts +12 -5
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +96 -11
- package/dist/DateInput/DateInput.d.ts +23 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +167 -99
- package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +42 -9
- package/dist/DateTimeInput/DateTimeInput.d.ts +35 -2
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +78 -15
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +12 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts +1 -8
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +42 -14
- package/dist/Field/Field.d.ts +19 -2
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +4 -0
- package/dist/Field/FieldLabel.d.ts +21 -2
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +41 -26
- package/dist/FileInput/FileInput.d.ts +22 -1
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +56 -10
- package/dist/Grid/Grid.d.ts +11 -1
- package/dist/Grid/Grid.d.ts.map +1 -1
- package/dist/Grid/Grid.js +32 -6
- package/dist/InputGroup/InputGroup.d.ts +4 -3
- package/dist/InputGroup/InputGroup.d.ts.map +1 -1
- package/dist/InputGroup/InputGroup.js +16 -6
- package/dist/InputGroup/InputGroupContext.d.ts +4 -0
- package/dist/InputGroup/InputGroupContext.d.ts.map +1 -1
- package/dist/InputGroup/InputGroupContext.js +2 -2
- package/dist/InputGroup/groupStyles.d.ts +1 -1
- package/dist/InputGroup/groupStyles.d.ts.map +1 -1
- package/dist/InputGroup/groupStyles.js +3 -3
- package/dist/InputGroup/index.d.ts +1 -0
- package/dist/InputGroup/index.d.ts.map +1 -1
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +33 -1
- package/dist/Layer/layerAnimations.stylex.d.ts +4 -0
- package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
- package/dist/Layer/layerAnimations.stylex.js +8 -4
- package/dist/Layer/useLayer.d.ts +10 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +64 -9
- package/dist/Layout/Layout.d.ts +4 -11
- package/dist/Layout/Layout.d.ts.map +1 -1
- package/dist/Layout/Layout.js +10 -11
- package/dist/Layout/LayoutFooter.d.ts +2 -2
- package/dist/Layout/LayoutFooter.d.ts.map +1 -1
- package/dist/Layout/LayoutHeader.d.ts +2 -2
- package/dist/Layout/LayoutHeader.d.ts.map +1 -1
- package/dist/Layout/LayoutPanel.d.ts +2 -2
- package/dist/Layout/LayoutPanel.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.d.ts +51 -0
- package/dist/Layout/padding.stylex.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.js +63 -0
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +4 -2
- package/dist/Link/Link.d.ts +16 -1
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +18 -7
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +7 -0
- package/dist/MoreMenu/MoreMenu.d.ts +1 -7
- package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
- package/dist/MoreMenu/MoreMenu.js +0 -2
- package/dist/MultiSelector/MultiSelector.d.ts +27 -2
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +141 -42
- package/dist/MultiSelector/hooks.d.ts +12 -1
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +14 -1
- package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.js +34 -3
- package/dist/NumberInput/NumberInput.d.ts +23 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +62 -12
- package/dist/Pagination/Pagination.d.ts +1 -1
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +15 -1
- package/dist/Popover/Popover.d.ts +18 -2
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +5 -2
- package/dist/Popover/usePopover.d.ts +38 -3
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +24 -9
- package/dist/PowerSearch/PowerSearch.d.ts +11 -1
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +6 -1
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +3 -5
- package/dist/RadioList/RadioList.d.ts +20 -2
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +105 -9
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +13 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts +13 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +78 -44
- package/dist/SegmentedControl/SegmentedControlContext.d.ts +7 -0
- package/dist/SegmentedControl/SegmentedControlContext.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +13 -2
- package/dist/Selector/Selector.d.ts +24 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +122 -43
- package/dist/Selector/hooks.d.ts +8 -1
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +14 -1
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +2 -0
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +1 -1
- package/dist/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/Skeleton/Skeleton.js +8 -2
- package/dist/Slider/Slider.d.ts +21 -0
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +36 -9
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +1 -1
- package/dist/Stack/Stack.d.ts +38 -23
- package/dist/Stack/Stack.d.ts.map +1 -1
- package/dist/Stack/Stack.js +25 -1
- package/dist/Stack/StackItem.d.ts +12 -23
- package/dist/Stack/StackItem.d.ts.map +1 -1
- package/dist/Stack/StackItem.js +8 -1
- package/dist/Switch/Switch.d.ts +23 -2
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +41 -11
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +6 -0
- package/dist/TabList/TabList.d.ts +16 -4
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +87 -10
- package/dist/TabList/TabListContext.d.ts +5 -0
- package/dist/TabList/TabListContext.d.ts.map +1 -1
- package/dist/TabList/TabListContext.js +5 -0
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +6 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +13 -9
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +10 -1
- package/dist/Table/TableCell.d.ts +8 -1
- package/dist/Table/TableCell.d.ts.map +1 -1
- package/dist/Table/TableCell.js +79 -10
- package/dist/Table/TableHeaderCell.d.ts +8 -1
- package/dist/Table/TableHeaderCell.d.ts.map +1 -1
- package/dist/Table/TableHeaderCell.js +16 -16
- package/dist/Table/index.d.ts +4 -1
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +3 -2
- package/dist/Table/plugins/pagination/paginateData.d.ts +2 -1
- package/dist/Table/plugins/pagination/paginateData.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/paginateData.js +8 -3
- package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +6 -1
- package/dist/Table/plugins/rowExpansion/index.d.ts +3 -0
- package/dist/Table/plugins/rowExpansion/index.d.ts.map +1 -0
- package/dist/Table/plugins/rowExpansion/index.js +3 -0
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts +90 -0
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -0
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +398 -0
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +59 -3
- package/dist/Table/tableContextMenu.d.ts +37 -0
- package/dist/Table/tableContextMenu.d.ts.map +1 -0
- package/dist/Table/tableContextMenu.js +140 -0
- package/dist/Table/types.d.ts +66 -0
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/TextArea/TextArea.d.ts +22 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +41 -9
- package/dist/TextInput/TextInput.d.ts +23 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +55 -10
- package/dist/TimeInput/TimeInput.d.ts +23 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +147 -76
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +14 -0
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +131 -3
- package/dist/Tokenizer/Tokenizer.d.ts +12 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +26 -4
- package/dist/Toolbar/Toolbar.d.ts +3 -3
- package/dist/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.js +51 -7
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +56 -9
- package/dist/TopNav/TopNavHeading.d.ts +7 -1
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +8 -0
- package/dist/TreeList/TreeList.d.ts +1 -1
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +72 -2
- package/dist/TreeList/TreeListItem.d.ts +11 -1
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +51 -12
- package/dist/TreeList/treeListItem.markers.stylex.d.ts +16 -0
- package/dist/TreeList/treeListItem.markers.stylex.d.ts.map +1 -0
- package/dist/TreeList/treeListItem.markers.stylex.js +22 -0
- package/dist/Typeahead/BaseTypeahead.d.ts +13 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +69 -6
- package/dist/Typeahead/Typeahead.d.ts +26 -3
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +65 -29
- package/dist/VisuallyHidden/VisuallyHidden.d.ts +61 -0
- package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -0
- package/dist/VisuallyHidden/VisuallyHidden.js +65 -0
- package/dist/VisuallyHidden/index.d.ts +11 -0
- package/dist/VisuallyHidden/index.d.ts.map +1 -0
- package/dist/VisuallyHidden/index.js +13 -0
- package/dist/astryx.css +22 -0
- package/dist/astryx.umd.js +54 -54
- package/dist/astryx.umd.js.map +4 -4
- package/dist/hooks/focusableSelector.d.ts +22 -0
- package/dist/hooks/focusableSelector.d.ts.map +1 -0
- package/dist/hooks/focusableSelector.js +24 -0
- package/dist/hooks/index.d.ts +12 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +7 -2
- package/dist/hooks/useAnnounce.d.ts +40 -0
- package/dist/hooks/useAnnounce.d.ts.map +1 -0
- package/dist/hooks/useAnnounce.js +142 -0
- package/dist/hooks/useClickableContainer.d.ts +16 -1
- package/dist/hooks/useClickableContainer.d.ts.map +1 -1
- package/dist/hooks/useClickableContainer.js +16 -4
- package/dist/hooks/useEntryAnimation.d.ts.map +1 -1
- package/dist/hooks/useEntryAnimation.js +4 -4
- package/dist/hooks/useFocusTrap.d.ts +18 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +87 -3
- package/dist/hooks/useGridFocus.d.ts +88 -1
- package/dist/hooks/useGridFocus.d.ts.map +1 -1
- package/dist/hooks/useGridFocus.js +261 -62
- package/dist/hooks/useKeyboardHint.d.ts +82 -0
- package/dist/hooks/useKeyboardHint.d.ts.map +1 -0
- package/dist/hooks/useKeyboardHint.js +220 -0
- package/dist/hooks/useListFocus.d.ts +78 -7
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +305 -52
- package/dist/hooks/useLongPress.d.ts +21 -0
- package/dist/hooks/useLongPress.d.ts.map +1 -0
- package/dist/hooks/useLongPress.js +89 -0
- package/dist/hooks/useTreeFocus.d.ts +157 -0
- package/dist/hooks/useTreeFocus.d.ts.map +1 -0
- package/dist/hooks/useTreeFocus.js +337 -0
- package/dist/hooks/useTypeahead.d.ts +63 -0
- package/dist/hooks/useTypeahead.d.ts.map +1 -0
- package/dist/hooks/useTypeahead.js +117 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/utils/dateTypes.d.ts +12 -0
- package/dist/utils/dateTypes.d.ts.map +1 -1
- package/dist/utils/dateTypes.js +41 -1
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -1
- package/dist/utils/inputAria.d.ts +29 -0
- package/dist/utils/inputAria.d.ts.map +1 -0
- package/dist/utils/inputAria.js +30 -0
- package/dist/utils/timeParser.d.ts.map +1 -1
- package/dist/utils/timeParser.js +5 -2
- package/docs.mjs +2 -2
- package/package.json +12 -8
- package/src/Avatar/Avatar.doc.mjs +2 -2
- package/src/Avatar/Avatar.test.tsx +37 -0
- package/src/Avatar/Avatar.tsx +10 -5
- package/src/Breadcrumbs/BreadcrumbItem.tsx +25 -7
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +31 -10
- package/src/Button/Button.tsx +42 -22
- package/src/ButtonGroup/ButtonGroup.test.tsx +9 -9
- package/src/ButtonGroup/ButtonGroup.tsx +0 -1
- package/src/Calendar/Calendar.doc.mjs +4 -4
- package/src/Calendar/Calendar.test.tsx +168 -30
- package/src/Calendar/Calendar.tsx +121 -66
- package/src/Calendar/hooks/index.ts +0 -6
- package/src/Calendar/index.ts +1 -3
- package/src/Calendar/styles.ts +4 -9
- package/src/Carousel/Carousel.doc.mjs +7 -1
- package/src/Carousel/Carousel.test.tsx +20 -0
- package/src/Carousel/Carousel.tsx +16 -1
- package/src/Center/Center.doc.mjs +12 -2
- package/src/Center/Center.tsx +28 -3
- package/src/Chat/ChatComposerInput.test.tsx +26 -7
- package/src/Chat/ChatComposerInput.tsx +0 -1
- package/src/Chat/ChatDictationButton.doc.mjs +1 -1
- package/src/Chat/ChatMessageList.doc.mjs +8 -0
- package/src/Chat/ChatMessageList.test.tsx +18 -0
- package/src/Chat/ChatMessageList.tsx +16 -0
- package/src/Chat/useTriggerMenu.tsx +22 -4
- package/src/CheckboxInput/CheckboxInput.doc.mjs +10 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +172 -27
- package/src/CheckboxInput/CheckboxInput.tsx +78 -6
- package/src/CheckboxList/CheckboxList.doc.mjs +9 -0
- package/src/CheckboxList/CheckboxList.test.tsx +192 -26
- package/src/CheckboxList/CheckboxList.tsx +56 -3
- package/src/CheckboxList/CheckboxListContext.tsx +7 -0
- package/src/CheckboxList/CheckboxListItem.tsx +0 -3
- package/src/Citation/Citation.doc.mjs +10 -0
- package/src/Citation/Citation.test.tsx +121 -0
- package/src/Citation/Citation.tsx +15 -3
- package/src/CodeBlock/CodeBlock.test.tsx +115 -0
- package/src/CodeBlock/CodeBlock.tsx +63 -33
- package/src/CommandPalette/CommandPalette.test.tsx +47 -1
- package/src/CommandPalette/CommandPalette.tsx +9 -21
- package/src/ContextMenu/ContextMenu.doc.mjs +4 -4
- package/src/ContextMenu/ContextMenu.test.tsx +155 -1
- package/src/ContextMenu/ContextMenu.tsx +129 -16
- package/src/DateInput/DateInput.doc.mjs +286 -56
- package/src/DateInput/DateInput.test.tsx +248 -2
- package/src/DateInput/DateInput.tsx +196 -100
- package/src/DateRangeInput/DateRangeInput.doc.mjs +251 -46
- package/src/DateRangeInput/DateRangeInput.test.tsx +182 -20
- package/src/DateRangeInput/DateRangeInput.tsx +63 -5
- package/src/DateTimeInput/DateTimeInput.doc.mjs +368 -67
- package/src/DateTimeInput/DateTimeInput.test.tsx +279 -11
- package/src/DateTimeInput/DateTimeInput.tsx +125 -17
- package/src/Dialog/Dialog.doc.mjs +2 -2
- package/src/Dialog/Dialog.tsx +12 -0
- package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -8
- package/src/DropdownMenu/DropdownMenu.test.tsx +56 -42
- package/src/DropdownMenu/DropdownMenu.tsx +52 -18
- package/src/Field/Field.doc.mjs +59 -18
- package/src/Field/Field.test.tsx +32 -0
- package/src/Field/Field.tsx +23 -5
- package/src/Field/FieldLabel.tsx +55 -17
- package/src/FileInput/FileInput.doc.mjs +17 -0
- package/src/FileInput/FileInput.test.tsx +283 -49
- package/src/FileInput/FileInput.tsx +76 -4
- package/src/Grid/Grid.doc.mjs +17 -4
- package/src/Grid/Grid.test.tsx +43 -30
- package/src/Grid/Grid.tsx +38 -3
- package/src/Icon/Icon.doc.mjs +3 -3
- package/src/InputGroup/InputGroup.doc.mjs +111 -23
- package/src/InputGroup/InputGroup.test.tsx +257 -60
- package/src/InputGroup/InputGroup.tsx +23 -5
- package/src/InputGroup/InputGroupContext.ts +9 -4
- package/src/InputGroup/groupStyles.ts +7 -1
- package/src/InputGroup/index.ts +1 -0
- package/src/Kbd/Kbd.test.tsx +22 -4
- package/src/Kbd/Kbd.tsx +35 -3
- package/src/Layer/layerAnimations.stylex.ts +20 -4
- package/src/Layer/useLayer.doc.mjs +5 -0
- package/src/Layer/useLayer.test.tsx +111 -0
- package/src/Layer/useLayer.tsx +90 -9
- package/src/Layout/Layout.tsx +8 -16
- package/src/Layout/LayoutFooter.doc.mjs +4 -4
- package/src/Layout/LayoutFooter.tsx +3 -3
- package/src/Layout/LayoutHeader.doc.mjs +4 -4
- package/src/Layout/LayoutHeader.tsx +3 -3
- package/src/Layout/LayoutPanel.tsx +3 -3
- package/src/Layout/__tests__/edgeCompensation.test.tsx +72 -0
- package/src/Layout/padding.stylex.ts +52 -0
- package/src/Lightbox/Lightbox.doc.mjs +9 -0
- package/src/Lightbox/Lightbox.test.tsx +53 -5
- package/src/Lightbox/Lightbox.tsx +9 -4
- package/src/Link/Link.doc.mjs +14 -0
- package/src/Link/Link.test.tsx +50 -0
- package/src/Link/Link.tsx +39 -4
- package/src/Markdown/Markdown.test.tsx +11 -0
- package/src/Markdown/Markdown.tsx +7 -0
- package/src/MetadataList/MetadataListItem.doc.mjs +4 -0
- package/src/MoreMenu/MoreMenu.doc.mjs +2 -17
- package/src/MoreMenu/MoreMenu.tsx +0 -9
- package/src/MultiSelector/MultiSelector.doc.mjs +30 -0
- package/src/MultiSelector/MultiSelector.test.tsx +375 -8
- package/src/MultiSelector/MultiSelector.tsx +194 -48
- package/src/MultiSelector/hooks.ts +27 -0
- package/src/NavMenu/NavHeadingMenu.test.tsx +77 -1
- package/src/NavMenu/NavHeadingMenu.tsx +50 -3
- package/src/NumberInput/NumberInput.doc.mjs +17 -0
- package/src/NumberInput/NumberInput.test.tsx +242 -40
- package/src/NumberInput/NumberInput.tsx +89 -11
- package/src/Pagination/Pagination.doc.mjs +3 -3
- package/src/Pagination/Pagination.test.tsx +117 -5
- package/src/Pagination/Pagination.tsx +21 -1
- package/src/Popover/Popover.doc.mjs +26 -0
- package/src/Popover/Popover.test.tsx +121 -0
- package/src/Popover/Popover.tsx +23 -2
- package/src/Popover/usePopover.doc.mjs +9 -3
- package/src/Popover/usePopover.tsx +70 -12
- package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
- package/src/PowerSearch/PowerSearch.test.tsx +97 -1
- package/src/PowerSearch/PowerSearch.tsx +16 -3
- package/src/ProgressBar/ProgressBar.test.tsx +34 -26
- package/src/ProgressBar/ProgressBar.tsx +3 -4
- package/src/RadioList/RadioList.doc.mjs +9 -0
- package/src/RadioList/RadioList.test.tsx +252 -16
- package/src/RadioList/RadioList.tsx +166 -10
- package/src/RadioList/RadioListItem.tsx +14 -2
- package/src/SegmentedControl/SegmentedControl.doc.mjs +9 -0
- package/src/SegmentedControl/SegmentedControl.test.tsx +214 -42
- package/src/SegmentedControl/SegmentedControl.tsx +102 -54
- package/src/SegmentedControl/SegmentedControlContext.ts +7 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +14 -1
- package/src/SelectableCard/SelectableCard.doc.mjs +1 -1
- package/src/Selector/Selector.doc.mjs +26 -0
- package/src/Selector/Selector.test.tsx +387 -15
- package/src/Selector/Selector.tsx +175 -67
- package/src/Selector/hooks.ts +23 -0
- package/src/SideNav/SideNav.test.tsx +48 -0
- package/src/SideNav/SideNavHeading.tsx +8 -2
- package/src/SideNav/SideNavItem.tsx +2 -4
- package/src/Skeleton/Skeleton.test.tsx +25 -0
- package/src/Skeleton/Skeleton.tsx +11 -1
- package/src/Slider/Slider.doc.mjs +15 -0
- package/src/Slider/Slider.test.tsx +155 -2
- package/src/Slider/Slider.tsx +53 -5
- package/src/Spinner/Spinner.tsx +7 -1
- package/src/Stack/Stack.doc.mjs +77 -0
- package/src/Stack/Stack.test.tsx +55 -5
- package/src/Stack/Stack.tsx +73 -24
- package/src/Stack/StackItem.test.tsx +23 -0
- package/src/Stack/StackItem.tsx +20 -23
- package/src/Switch/Switch.doc.mjs +15 -0
- package/src/Switch/Switch.test.tsx +162 -27
- package/src/Switch/Switch.tsx +61 -21
- package/src/TabList/Tab.tsx +6 -0
- package/src/TabList/TabList.doc.mjs +6 -0
- package/src/TabList/TabList.test.tsx +251 -0
- package/src/TabList/TabList.tsx +103 -12
- package/src/TabList/TabListContext.ts +7 -3
- package/src/TabList/TabMenu.tsx +6 -3
- package/src/Table/BaseTable.tsx +24 -18
- package/src/Table/Table.doc.mjs +2 -0
- package/src/Table/Table.test.tsx +10 -0
- package/src/Table/Table.tsx +8 -0
- package/src/Table/TableCell.tsx +105 -24
- package/src/Table/TableHeaderCell.tsx +28 -29
- package/src/Table/index.ts +8 -2
- package/src/Table/plugins/pagination/paginateData.ts +10 -3
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +16 -0
- package/src/Table/plugins/pagination/useTablePagination.tsx +8 -1
- package/src/Table/plugins/rowExpansion/index.ts +7 -0
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +155 -0
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +590 -0
- package/src/Table/plugins/sortable/useTableSortable.test.tsx +91 -2
- package/src/Table/plugins/sortable/useTableSortable.tsx +53 -1
- package/src/Table/tableContextMenu.test.tsx +181 -0
- package/src/Table/tableContextMenu.tsx +160 -0
- package/src/Table/types.ts +74 -0
- package/src/Table/useTableColumnResize.doc.mjs +3 -3
- package/src/Table/useTablePagination.doc.mjs +4 -1
- package/src/Table/useTableRowExpansion.doc.mjs +63 -0
- package/src/Table/useTableSortable.doc.mjs +4 -1
- package/src/Table/useTableStickyColumns.doc.mjs +2 -2
- package/src/Text/Text.doc.mjs +18 -18
- package/src/TextArea/TextArea.doc.mjs +17 -0
- package/src/TextArea/TextArea.test.tsx +167 -35
- package/src/TextArea/TextArea.tsx +62 -15
- package/src/TextInput/TextInput.doc.mjs +17 -0
- package/src/TextInput/TextInput.test.tsx +168 -34
- package/src/TextInput/TextInput.tsx +77 -9
- package/src/Thumbnail/Thumbnail.doc.mjs +4 -4
- package/src/TimeInput/TimeInput.doc.mjs +345 -60
- package/src/TimeInput/TimeInput.test.tsx +255 -7
- package/src/TimeInput/TimeInput.tsx +176 -70
- package/src/Timestamp/Timestamp.doc.mjs +19 -19
- package/src/Toast/Toast.tsx +14 -0
- package/src/Toast/ToastViewport.test.tsx +214 -0
- package/src/Toast/ToastViewport.tsx +167 -21
- package/src/Tokenizer/Tokenizer.doc.mjs +29 -14
- package/src/Tokenizer/Tokenizer.test.tsx +105 -1
- package/src/Tokenizer/Tokenizer.tsx +37 -1
- package/src/Toolbar/Toolbar.test.tsx +109 -6
- package/src/Toolbar/Toolbar.tsx +59 -5
- package/src/Tooltip/Tooltip.test.tsx +68 -0
- package/src/Tooltip/useTooltip.tsx +55 -8
- package/src/TopNav/TopNav.test.tsx +50 -0
- package/src/TopNav/TopNavHeading.tsx +17 -1
- package/src/TreeList/TreeList.test.tsx +295 -6
- package/src/TreeList/TreeList.tsx +73 -1
- package/src/TreeList/TreeListItem.tsx +51 -5
- package/src/TreeList/treeListItem.markers.stylex.ts +20 -0
- package/src/Typeahead/BaseTypeahead.tsx +93 -9
- package/src/Typeahead/Typeahead.doc.mjs +141 -30
- package/src/Typeahead/Typeahead.test.tsx +331 -1
- package/src/Typeahead/Typeahead.tsx +105 -33
- package/src/VisuallyHidden/VisuallyHidden.doc.mjs +80 -0
- package/src/VisuallyHidden/VisuallyHidden.test.tsx +76 -0
- package/src/VisuallyHidden/VisuallyHidden.tsx +113 -0
- package/src/VisuallyHidden/index.ts +15 -0
- package/src/docs-script.test.mjs +50 -0
- package/src/hooks/focusableSelector.ts +25 -0
- package/src/hooks/index.ts +28 -2
- package/src/hooks/useAnnounce.test.tsx +101 -0
- package/src/hooks/useAnnounce.ts +168 -0
- package/src/hooks/useClickableContainer.ts +16 -4
- package/src/hooks/useEntryAnimation.ts +16 -4
- package/src/hooks/useFocusTrap.test.tsx +132 -0
- package/src/hooks/useFocusTrap.ts +98 -4
- package/src/hooks/useGridFocus.doc.mjs +40 -2
- package/src/hooks/useGridFocus.test.tsx +132 -0
- package/src/hooks/useGridFocus.ts +343 -67
- package/src/hooks/useKeyboardHint.doc.mjs +101 -0
- package/src/hooks/useKeyboardHint.test.tsx +70 -0
- package/src/hooks/useKeyboardHint.tsx +332 -0
- package/src/hooks/useListFocus.doc.mjs +50 -10
- package/src/hooks/useListFocus.test.tsx +375 -0
- package/src/hooks/useListFocus.ts +395 -57
- package/src/hooks/useLongPress.test.tsx +134 -0
- package/src/hooks/useLongPress.ts +119 -0
- package/src/hooks/useTreeFocus.doc.mjs +140 -0
- package/src/hooks/useTreeFocus.test.tsx +214 -0
- package/src/hooks/useTreeFocus.ts +559 -0
- package/src/hooks/useTypeahead.test.tsx +109 -0
- package/src/hooks/useTypeahead.ts +183 -0
- package/src/index.ts +1 -0
- package/src/theme/derivedVarRegistry.test.ts +10 -5
- package/src/utils/dateTypes.test.ts +40 -0
- package/src/utils/dateTypes.ts +40 -0
- package/src/utils/index.ts +9 -0
- package/src/utils/inputAria.test.ts +39 -0
- package/src/utils/inputAria.ts +58 -0
- package/src/utils/timeParser.test.ts +10 -0
- package/src/utils/timeParser.ts +5 -2
- package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts +0 -57
- package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts.map +0 -1
- package/dist/Calendar/hooks/useCalendarRovingTabindex.js +0 -96
- package/src/Calendar/hooks/useCalendarRovingTabindex.ts +0 -118
|
@@ -45,6 +45,12 @@ export const docs = {
|
|
|
45
45
|
type: 'SpacingStep',
|
|
46
46
|
description: 'Gap between top-level message rows. Defaults to the selected density; override for LLM event streams or independent rows that need different spacing from density.',
|
|
47
47
|
},
|
|
48
|
+
{
|
|
49
|
+
name: 'isStreaming',
|
|
50
|
+
type: 'boolean',
|
|
51
|
+
description: 'Whether an assistant message is actively streaming. Marks the log aria-busy so screen readers wait and announce the completed message once instead of re-announcing partial text on every token.',
|
|
52
|
+
default: 'false',
|
|
53
|
+
},
|
|
48
54
|
],
|
|
49
55
|
};
|
|
50
56
|
|
|
@@ -59,6 +65,7 @@ export const docsZh = {
|
|
|
59
65
|
scrollToTopAction: '用户滚动到顶部时触发的异步操作。用于加载更早的消息。',
|
|
60
66
|
density: '视觉密度,通过上下文传递给子消息。',
|
|
61
67
|
gap: '顶层消息行之间的间距。默认跟随密度;当 LLM 事件流等独立行需要不同间距时可覆盖。',
|
|
68
|
+
isStreaming: '是否有助手消息正在流式输出。标记日志为 aria-busy,让屏幕阅读器等待并在完成后一次性播报,而不是每个 token 都重复播报。',
|
|
62
69
|
},
|
|
63
70
|
};
|
|
64
71
|
|
|
@@ -73,5 +80,6 @@ export const docsDense = {
|
|
|
73
80
|
scrollToTopAction: 'async action at scroll top; load older msgs',
|
|
74
81
|
density: 'visual density; flows to children via context',
|
|
75
82
|
gap: 'top-level row gap; defaults to density spacing; override for independent LLM/tool rows',
|
|
83
|
+
isStreaming: 'assistant streaming? marks log aria-busy so SR announces the completed msg once',
|
|
76
84
|
},
|
|
77
85
|
};
|
|
@@ -28,6 +28,24 @@ describe('ChatMessageList', () => {
|
|
|
28
28
|
expect(el.getAttribute('role')).toBe('log');
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
+
it('is not aria-busy by default', () => {
|
|
32
|
+
render(
|
|
33
|
+
<ChatMessageList data-testid="list">
|
|
34
|
+
<div>msg</div>
|
|
35
|
+
</ChatMessageList>,
|
|
36
|
+
);
|
|
37
|
+
expect(screen.getByTestId('list')).not.toHaveAttribute('aria-busy');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('marks the log aria-busy while streaming', () => {
|
|
41
|
+
render(
|
|
42
|
+
<ChatMessageList data-testid="list" isStreaming>
|
|
43
|
+
<div>msg</div>
|
|
44
|
+
</ChatMessageList>,
|
|
45
|
+
);
|
|
46
|
+
expect(screen.getByTestId('list')).toHaveAttribute('aria-busy', 'true');
|
|
47
|
+
});
|
|
48
|
+
|
|
31
49
|
it('renders empty state when no children', () => {
|
|
32
50
|
render(
|
|
33
51
|
<ChatMessageList emptyState={<div>No messages yet</div>}>
|
|
@@ -72,6 +72,20 @@ export interface ChatMessageListProps extends BaseProps<HTMLDivElement> {
|
|
|
72
72
|
* be grouped) and row spacing should be tuned separately from density.
|
|
73
73
|
*/
|
|
74
74
|
gap?: SpacingStep;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Whether an assistant message is actively streaming into the list.
|
|
78
|
+
*
|
|
79
|
+
* The list is a `role="log"` / `aria-live="polite"` region, so while a
|
|
80
|
+
* message streams in token-by-token, screen readers would otherwise
|
|
81
|
+
* re-announce the accumulating partial text on every mutation. Set
|
|
82
|
+
* `isStreaming` to `true` for the duration of a stream: it marks the log
|
|
83
|
+
* `aria-busy="true"` so assistive tech waits and announces the completed
|
|
84
|
+
* message once, when `isStreaming` returns to `false`.
|
|
85
|
+
*
|
|
86
|
+
* @default false
|
|
87
|
+
*/
|
|
88
|
+
isStreaming?: boolean;
|
|
75
89
|
}
|
|
76
90
|
|
|
77
91
|
// =============================================================================
|
|
@@ -190,6 +204,7 @@ export function ChatMessageList({
|
|
|
190
204
|
scrollToTopAction,
|
|
191
205
|
density = 'balanced',
|
|
192
206
|
gap,
|
|
207
|
+
isStreaming = false,
|
|
193
208
|
xstyle,
|
|
194
209
|
className,
|
|
195
210
|
style,
|
|
@@ -252,6 +267,7 @@ export function ChatMessageList({
|
|
|
252
267
|
ref={ref}
|
|
253
268
|
role="log"
|
|
254
269
|
aria-live="polite"
|
|
270
|
+
aria-busy={isStreaming || undefined}
|
|
255
271
|
tabIndex={0}
|
|
256
272
|
data-testid={testId}
|
|
257
273
|
{...mergeProps(
|
|
@@ -81,8 +81,15 @@ export interface UseTriggerMenuReturn {
|
|
|
81
81
|
renderMenu: () => ReactNode;
|
|
82
82
|
/** Reset/close the trigger menu */
|
|
83
83
|
reset: () => void;
|
|
84
|
-
/**
|
|
84
|
+
/**
|
|
85
|
+
* ARIA props to spread onto the editable element. When triggers are
|
|
86
|
+
* configured the element becomes a `combobox` (which is the only role that
|
|
87
|
+
* permits `aria-expanded`/`aria-haspopup`/`aria-controls`/
|
|
88
|
+
* `aria-activedescendant`); otherwise it stays a plain `textbox` and no
|
|
89
|
+
* combobox attributes are emitted.
|
|
90
|
+
*/
|
|
85
91
|
ariaProps: {
|
|
92
|
+
role: 'combobox' | 'textbox';
|
|
86
93
|
'aria-expanded'?: boolean;
|
|
87
94
|
'aria-controls'?: string;
|
|
88
95
|
'aria-activedescendant'?: string;
|
|
@@ -296,6 +303,9 @@ export function useTriggerMenu(
|
|
|
296
303
|
hasLightDismiss: true,
|
|
297
304
|
hasCloseButton: false,
|
|
298
305
|
hasAutoFocus: false,
|
|
306
|
+
// The popup's own role="listbox" is the exposed semantics; focus stays in
|
|
307
|
+
// the contenteditable composer, so a modal dialog wrapper is incorrect.
|
|
308
|
+
role: 'none',
|
|
299
309
|
});
|
|
300
310
|
|
|
301
311
|
// Cleanup on unmount
|
|
@@ -598,10 +608,17 @@ export function useTriggerMenu(
|
|
|
598
608
|
el?.scrollIntoView({block: 'nearest'});
|
|
599
609
|
}, [state.highlightedIndex, popover.isOpen, getItemId]);
|
|
600
610
|
|
|
601
|
-
// ARIA props for the
|
|
602
|
-
|
|
603
|
-
|
|
611
|
+
// ARIA props for the editable element. Combobox attributes
|
|
612
|
+
// (aria-expanded/haspopup/controls/activedescendant) are only valid on
|
|
613
|
+
// role="combobox", so we only switch to that role — and only emit those
|
|
614
|
+
// attributes — when triggers are actually configured. With no triggers the
|
|
615
|
+
// element stays a plain role="textbox".
|
|
616
|
+
const hasTriggers = (triggers?.length ?? 0) > 0;
|
|
617
|
+
const ariaProps: UseTriggerMenuReturn['ariaProps'] = !hasTriggers
|
|
618
|
+
? {role: 'textbox'}
|
|
619
|
+
: state.isActive && popover.isOpen
|
|
604
620
|
? {
|
|
621
|
+
role: 'combobox',
|
|
605
622
|
'aria-expanded': true as const,
|
|
606
623
|
'aria-controls': listboxId,
|
|
607
624
|
'aria-activedescendant':
|
|
@@ -611,6 +628,7 @@ export function useTriggerMenu(
|
|
|
611
628
|
'aria-haspopup': 'listbox' as const,
|
|
612
629
|
}
|
|
613
630
|
: {
|
|
631
|
+
role: 'combobox',
|
|
614
632
|
'aria-expanded': false as const,
|
|
615
633
|
'aria-haspopup': 'listbox' as const,
|
|
616
634
|
};
|
|
@@ -63,6 +63,12 @@ export const docs = {
|
|
|
63
63
|
description: 'Whether the checkbox is disabled.',
|
|
64
64
|
default: 'false',
|
|
65
65
|
},
|
|
66
|
+
{
|
|
67
|
+
name: 'disabledMessage',
|
|
68
|
+
type: 'string',
|
|
69
|
+
description:
|
|
70
|
+
'Explains why the checkbox is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the checkbox focusable via aria-disabled (toggling stays blocked). Use this instead of wrapping a disabled CheckboxInput in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.',
|
|
71
|
+
},
|
|
66
72
|
{
|
|
67
73
|
name: 'isReadOnly',
|
|
68
74
|
type: 'boolean',
|
|
@@ -124,6 +130,7 @@ export const docs = {
|
|
|
124
130
|
{ guidance: true, description: 'Use the indeterminate state for "select all" checkboxes when only some items in a group are selected.' },
|
|
125
131
|
{ guidance: false, description: 'Use a checkbox for mutually exclusive choices; use RadioList when only one option can be selected.' },
|
|
126
132
|
{ guidance: false, description: 'Use a checkbox for actions that take effect immediately; use a toggle switch or button instead.' },
|
|
133
|
+
{ guidance: false, description: 'Wrap a disabled checkbox in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.' },
|
|
127
134
|
],
|
|
128
135
|
anatomy: [
|
|
129
136
|
{ name: 'Checkbox', required: true, description: 'The check box itself: unchecked, checked, or indeterminate.' },
|
|
@@ -146,6 +153,7 @@ export const docsZh = {
|
|
|
146
153
|
{ guidance: true, description: 'Use the indeterminate state for "select all" checkboxes when only some items in a group are selected.' },
|
|
147
154
|
{ guidance: false, description: 'Use a checkbox for mutually exclusive choices; use RadioList when only one option can be selected.' },
|
|
148
155
|
{ guidance: false, description: 'Use a checkbox for actions that take effect immediately; use a toggle switch or button instead.' },
|
|
156
|
+
{ guidance: false, description: 'Wrap a disabled checkbox in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.' },
|
|
149
157
|
],
|
|
150
158
|
},
|
|
151
159
|
props: [
|
|
@@ -163,6 +171,7 @@ export const docsZh = {
|
|
|
163
171
|
},
|
|
164
172
|
{name: 'isLoading', type: 'boolean', description: '复选框是否处于加载状态。显示旋转器并阻止交互。', default: 'false'},
|
|
165
173
|
{name: 'isDisabled', type: 'boolean', description: '复选框是否禁用。', default: 'false'},
|
|
174
|
+
{name: 'disabledMessage', type: 'string', description: 'Explains why the checkbox is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the checkbox focusable via aria-disabled (toggling stays blocked). Use this instead of wrapping a disabled CheckboxInput in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.'},
|
|
166
175
|
{name: 'isReadOnly', type: 'boolean', description: '复选框是否为只读。以完整不透明度显示当前状态但阻止交互。与 isDisabled 不同,只读复选框不会变暗。', default: 'false'},
|
|
167
176
|
{name: 'isOptional', type: 'boolean', description: '字段是否可选。与 isRequired 互斥。', default: 'false'},
|
|
168
177
|
{name: 'isRequired', type: 'boolean', description: '复选框是否必填。与 isOptional 互斥。', default: 'false'},
|
|
@@ -200,6 +209,7 @@ export const docsDense = {
|
|
|
200
209
|
{ guidance: true, description: 'Use the indeterminate state for "select all" checkboxes when only some items in a group are selected.' },
|
|
201
210
|
{ guidance: false, description: 'Use a checkbox for mutually exclusive choices; use RadioList when only one option can be selected.' },
|
|
202
211
|
{ guidance: false, description: 'Use a checkbox for actions that take effect immediately; use a toggle switch or button instead.' },
|
|
212
|
+
{ guidance: false, description: 'Wrap a disabled checkbox in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.' },
|
|
203
213
|
],
|
|
204
214
|
},
|
|
205
215
|
propDescriptions: {
|
|
@@ -9,41 +9,56 @@
|
|
|
9
9
|
* SYNC: When CheckboxInput.tsx changes, update tests to match new behavior
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {describe, it, expect, vi} from 'vitest';
|
|
13
|
-
import {render, screen} from '@testing-library/react';
|
|
12
|
+
import {describe, it, expect, vi, beforeEach} from 'vitest';
|
|
13
|
+
import {render, screen, fireEvent, waitFor} from '@testing-library/react';
|
|
14
14
|
import userEvent from '@testing-library/user-event';
|
|
15
15
|
import {CheckboxInput} from './CheckboxInput';
|
|
16
16
|
|
|
17
|
+
// Mock showPopover/hidePopover (not implemented in jsdom) so the tooltip layer
|
|
18
|
+
// reflects its open state via a `popover-open` attribute the tests can assert.
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
HTMLElement.prototype.showPopover = vi.fn(function (this: HTMLElement) {
|
|
21
|
+
this.setAttribute('popover-open', '');
|
|
22
|
+
const event = new Event('toggle', {bubbles: false});
|
|
23
|
+
Object.defineProperty(event, 'newState', {value: 'open'});
|
|
24
|
+
this.dispatchEvent(event);
|
|
25
|
+
});
|
|
26
|
+
HTMLElement.prototype.hidePopover = vi.fn(function (this: HTMLElement) {
|
|
27
|
+
this.removeAttribute('popover-open');
|
|
28
|
+
const event = new Event('toggle', {bubbles: false});
|
|
29
|
+
Object.defineProperty(event, 'newState', {value: 'closed'});
|
|
30
|
+
this.dispatchEvent(event);
|
|
31
|
+
});
|
|
32
|
+
const originalMatches = HTMLElement.prototype.matches;
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34
|
+
(HTMLElement.prototype as any).matches = function (
|
|
35
|
+
selector: string,
|
|
36
|
+
): boolean {
|
|
37
|
+
if (selector === ':popover-open') {
|
|
38
|
+
return this.hasAttribute('popover-open');
|
|
39
|
+
}
|
|
40
|
+
return originalMatches.call(this, selector);
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
|
|
17
44
|
describe('CheckboxInput', () => {
|
|
18
45
|
it('renders with label', () => {
|
|
19
46
|
render(
|
|
20
|
-
<CheckboxInput
|
|
21
|
-
label="Accept terms"
|
|
22
|
-
value={false}
|
|
23
|
-
onChange={() => {}}
|
|
24
|
-
/>,
|
|
47
|
+
<CheckboxInput label="Accept terms" value={false} onChange={() => {}} />,
|
|
25
48
|
);
|
|
26
49
|
expect(screen.getByLabelText('Accept terms')).toBeInTheDocument();
|
|
27
50
|
});
|
|
28
51
|
|
|
29
52
|
it('renders as unchecked by default', () => {
|
|
30
53
|
render(
|
|
31
|
-
<CheckboxInput
|
|
32
|
-
label="Accept terms"
|
|
33
|
-
value={false}
|
|
34
|
-
onChange={() => {}}
|
|
35
|
-
/>,
|
|
54
|
+
<CheckboxInput label="Accept terms" value={false} onChange={() => {}} />,
|
|
36
55
|
);
|
|
37
56
|
expect(screen.getByRole('checkbox')).not.toBeChecked();
|
|
38
57
|
});
|
|
39
58
|
|
|
40
59
|
it('renders as checked when value prop is true', () => {
|
|
41
60
|
render(
|
|
42
|
-
<CheckboxInput
|
|
43
|
-
label="Accept terms"
|
|
44
|
-
value={true}
|
|
45
|
-
onChange={() => {}}
|
|
46
|
-
/>,
|
|
61
|
+
<CheckboxInput label="Accept terms" value={true} onChange={() => {}} />,
|
|
47
62
|
);
|
|
48
63
|
expect(screen.getByRole('checkbox')).toBeChecked();
|
|
49
64
|
});
|
|
@@ -182,11 +197,7 @@ describe('CheckboxInput', () => {
|
|
|
182
197
|
|
|
183
198
|
it('shows label visually by default', () => {
|
|
184
199
|
render(
|
|
185
|
-
<CheckboxInput
|
|
186
|
-
label="Accept terms"
|
|
187
|
-
value={false}
|
|
188
|
-
onChange={() => {}}
|
|
189
|
-
/>,
|
|
200
|
+
<CheckboxInput label="Accept terms" value={false} onChange={() => {}} />,
|
|
190
201
|
);
|
|
191
202
|
const label = screen.getByText('Accept terms');
|
|
192
203
|
expect(label).toBeVisible();
|
|
@@ -204,7 +215,7 @@ describe('CheckboxInput', () => {
|
|
|
204
215
|
expect(screen.getByRole('checkbox')).toHaveAttribute('aria-busy', 'true');
|
|
205
216
|
});
|
|
206
217
|
|
|
207
|
-
it('
|
|
218
|
+
it('exposes indeterminate state via the native indeterminate property', () => {
|
|
208
219
|
render(
|
|
209
220
|
<CheckboxInput
|
|
210
221
|
label="Select all"
|
|
@@ -212,10 +223,15 @@ describe('CheckboxInput', () => {
|
|
|
212
223
|
onChange={() => {}}
|
|
213
224
|
/>,
|
|
214
225
|
);
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
)
|
|
226
|
+
const checkbox = screen.getByRole('checkbox');
|
|
227
|
+
// Native checkboxes expose mixed state through the DOM indeterminate
|
|
228
|
+
// property, which browsers map to aria-checked="mixed". A redundant
|
|
229
|
+
// aria-checked attribute is intentionally NOT set (forms-16).
|
|
230
|
+
expect(checkbox).toBeInstanceOf(HTMLInputElement);
|
|
231
|
+
if (checkbox instanceof HTMLInputElement) {
|
|
232
|
+
expect(checkbox.indeterminate).toBe(true);
|
|
233
|
+
}
|
|
234
|
+
expect(checkbox).not.toHaveAttribute('aria-checked');
|
|
219
235
|
});
|
|
220
236
|
|
|
221
237
|
it('renders semantic labelIcon names as icons', () => {
|
|
@@ -247,4 +263,133 @@ describe('CheckboxInput', () => {
|
|
|
247
263
|
'true',
|
|
248
264
|
);
|
|
249
265
|
});
|
|
266
|
+
|
|
267
|
+
describe('disabledMessage', () => {
|
|
268
|
+
const h = {hidden: true} as const;
|
|
269
|
+
|
|
270
|
+
function getRow(): HTMLElement {
|
|
271
|
+
return screen.getByRole('checkbox', h).closest('div')!.parentElement!;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
it('shows the reason tooltip on hover when disabled with a reason', async () => {
|
|
275
|
+
render(
|
|
276
|
+
<CheckboxInput
|
|
277
|
+
label="Accept terms"
|
|
278
|
+
value={false}
|
|
279
|
+
onChange={() => {}}
|
|
280
|
+
isDisabled
|
|
281
|
+
disabledMessage="Terms are managed by your administrator"
|
|
282
|
+
/>,
|
|
283
|
+
);
|
|
284
|
+
const tooltip = screen.getByRole('tooltip', h);
|
|
285
|
+
expect(tooltip).toHaveTextContent(
|
|
286
|
+
'Terms are managed by your administrator',
|
|
287
|
+
);
|
|
288
|
+
fireEvent.mouseEnter(getRow());
|
|
289
|
+
await waitFor(() => expect(tooltip).toHaveAttribute('popover-open'));
|
|
290
|
+
fireEvent.mouseLeave(getRow());
|
|
291
|
+
await waitFor(() => expect(tooltip).not.toHaveAttribute('popover-open'));
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
it('shows the reason tooltip on keyboard focus', async () => {
|
|
295
|
+
const user = userEvent.setup();
|
|
296
|
+
render(
|
|
297
|
+
<CheckboxInput
|
|
298
|
+
label="Accept terms"
|
|
299
|
+
value={false}
|
|
300
|
+
onChange={() => {}}
|
|
301
|
+
isDisabled
|
|
302
|
+
disabledMessage="Terms are managed by your administrator"
|
|
303
|
+
/>,
|
|
304
|
+
);
|
|
305
|
+
const tooltip = screen.getByRole('tooltip', h);
|
|
306
|
+
await user.tab();
|
|
307
|
+
expect(screen.getByRole('checkbox', h)).toHaveFocus();
|
|
308
|
+
await waitFor(() => expect(tooltip).toHaveAttribute('popover-open'));
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
it('does not render a tooltip when not disabled', () => {
|
|
312
|
+
render(
|
|
313
|
+
<CheckboxInput
|
|
314
|
+
label="Accept terms"
|
|
315
|
+
value={false}
|
|
316
|
+
onChange={() => {}}
|
|
317
|
+
disabledMessage="Terms are managed by your administrator"
|
|
318
|
+
/>,
|
|
319
|
+
);
|
|
320
|
+
expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it('does not render a tooltip when disabled without a reason', () => {
|
|
324
|
+
render(
|
|
325
|
+
<CheckboxInput
|
|
326
|
+
label="Accept terms"
|
|
327
|
+
value={false}
|
|
328
|
+
onChange={() => {}}
|
|
329
|
+
isDisabled
|
|
330
|
+
/>,
|
|
331
|
+
);
|
|
332
|
+
expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
it('keeps the checkbox focusable via aria-disabled when a reason is provided', () => {
|
|
336
|
+
render(
|
|
337
|
+
<CheckboxInput
|
|
338
|
+
label="Accept terms"
|
|
339
|
+
value={false}
|
|
340
|
+
onChange={() => {}}
|
|
341
|
+
isDisabled
|
|
342
|
+
disabledMessage="Terms are managed by your administrator"
|
|
343
|
+
/>,
|
|
344
|
+
);
|
|
345
|
+
const checkbox = screen.getByRole('checkbox', h);
|
|
346
|
+
expect(checkbox).not.toBeDisabled();
|
|
347
|
+
expect(checkbox).toHaveAttribute('aria-disabled', 'true');
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
it('links the reason tooltip via aria-describedby', () => {
|
|
351
|
+
render(
|
|
352
|
+
<CheckboxInput
|
|
353
|
+
label="Accept terms"
|
|
354
|
+
value={false}
|
|
355
|
+
onChange={() => {}}
|
|
356
|
+
isDisabled
|
|
357
|
+
disabledMessage="Terms are managed by your administrator"
|
|
358
|
+
/>,
|
|
359
|
+
);
|
|
360
|
+
const checkbox = screen.getByRole('checkbox', h);
|
|
361
|
+
const tooltip = screen.getByRole('tooltip', h);
|
|
362
|
+
expect(checkbox.getAttribute('aria-describedby')).toContain(tooltip.id);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('blocks toggling while focusable-disabled', async () => {
|
|
366
|
+
const user = userEvent.setup();
|
|
367
|
+
const onChange = vi.fn();
|
|
368
|
+
render(
|
|
369
|
+
<CheckboxInput
|
|
370
|
+
label="Accept terms"
|
|
371
|
+
value={false}
|
|
372
|
+
onChange={onChange}
|
|
373
|
+
isDisabled
|
|
374
|
+
disabledMessage="Terms are managed by your administrator"
|
|
375
|
+
/>,
|
|
376
|
+
);
|
|
377
|
+
const checkbox = screen.getByRole('checkbox', h);
|
|
378
|
+
await user.click(checkbox);
|
|
379
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
380
|
+
expect(checkbox).not.toBeChecked();
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
it('remains natively disabled when disabled without a reason', () => {
|
|
384
|
+
render(
|
|
385
|
+
<CheckboxInput
|
|
386
|
+
label="Accept terms"
|
|
387
|
+
value={false}
|
|
388
|
+
onChange={() => {}}
|
|
389
|
+
isDisabled
|
|
390
|
+
/>,
|
|
391
|
+
);
|
|
392
|
+
expect(screen.getByRole('checkbox')).toBeDisabled();
|
|
393
|
+
});
|
|
394
|
+
});
|
|
250
395
|
});
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file CheckboxInput.tsx
|
|
7
|
-
* @input Uses React, useId, ChangeEvent, FieldLabel, FieldStatus, IconType, InputStatus
|
|
7
|
+
* @input Uses React, useId, ChangeEvent, FieldLabel, FieldStatus, IconType, InputStatus, useTooltip
|
|
8
8
|
* @output Exports CheckboxInput component, CheckboxInputProps
|
|
9
9
|
* @position Core implementation; consumed by index.ts, tested by CheckboxInput.test.tsx
|
|
10
10
|
*
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
import {
|
|
20
20
|
useId,
|
|
21
21
|
useCallback,
|
|
22
|
+
use,
|
|
22
23
|
useOptimistic,
|
|
23
24
|
useTransition,
|
|
24
25
|
type ChangeEvent,
|
|
@@ -44,9 +45,11 @@ import {FieldStatus} from '../FieldStatus/FieldStatus';
|
|
|
44
45
|
import type {IconType} from '../Icon';
|
|
45
46
|
import type {InputStatus} from '../Field/types';
|
|
46
47
|
import {Spinner} from '../Spinner';
|
|
48
|
+
import {useTooltip} from '../Tooltip';
|
|
47
49
|
import {mergeProps, mergeRefs} from '../utils';
|
|
48
50
|
import {checkboxScope} from './checkbox.markers.stylex';
|
|
49
51
|
import {themeProps} from '../utils/themeProps';
|
|
52
|
+
import {CheckboxListContext} from '../CheckboxList/CheckboxListContext';
|
|
50
53
|
|
|
51
54
|
const styles = stylex.create({
|
|
52
55
|
container: {
|
|
@@ -269,6 +272,27 @@ export interface CheckboxInputProps extends Omit<BaseProps, 'onChange'> {
|
|
|
269
272
|
* @default false
|
|
270
273
|
*/
|
|
271
274
|
isDisabled?: boolean;
|
|
275
|
+
/**
|
|
276
|
+
* Explains why the checkbox is disabled. When set together with
|
|
277
|
+
* `isDisabled`, the checkbox shows a tooltip with this text on hover and
|
|
278
|
+
* keyboard focus, and the control stays focusable (via `aria-disabled`) so
|
|
279
|
+
* the reason is discoverable by keyboard and assistive technology.
|
|
280
|
+
* Activation stays blocked.
|
|
281
|
+
*
|
|
282
|
+
* Use this instead of wrapping a disabled checkbox in `Tooltip` — disabled
|
|
283
|
+
* controls don't emit the pointer events an external tooltip needs.
|
|
284
|
+
*
|
|
285
|
+
* @example
|
|
286
|
+
* ```
|
|
287
|
+
* <CheckboxInput
|
|
288
|
+
* label="Accept terms"
|
|
289
|
+
* value={accepted}
|
|
290
|
+
* isDisabled
|
|
291
|
+
* disabledMessage="Terms are managed by your administrator"
|
|
292
|
+
* />
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
295
|
+
disabledMessage?: string;
|
|
272
296
|
/**
|
|
273
297
|
* Whether the checkbox is read-only.
|
|
274
298
|
* Displays the current state at full opacity but prevents interaction.
|
|
@@ -350,6 +374,7 @@ export function CheckboxInput({
|
|
|
350
374
|
isLoading = false,
|
|
351
375
|
value,
|
|
352
376
|
isDisabled = false,
|
|
377
|
+
disabledMessage,
|
|
353
378
|
isReadOnly = false,
|
|
354
379
|
isOptional = false,
|
|
355
380
|
isRequired = false,
|
|
@@ -372,11 +397,37 @@ export function CheckboxInput({
|
|
|
372
397
|
const [optimisticValue, setOptimisticValue] = useOptimistic(value);
|
|
373
398
|
const isBusy = isLoading || optimisticValue !== value;
|
|
374
399
|
|
|
400
|
+
// Disabled-reason tooltip. Disabled controls swallow pointer events, so the
|
|
401
|
+
// tooltip listeners attach to the checkbox row (which already exists) and the
|
|
402
|
+
// native checkbox stays perceivable via aria-disabled instead of the disabled
|
|
403
|
+
// attribute. Value mutation is blocked by the isDisabled guard in onChange.
|
|
404
|
+
const showsDisabledMessage = isDisabled && !!disabledMessage;
|
|
405
|
+
// Keep the native checkbox focusable via aria-disabled either when it renders
|
|
406
|
+
// its own reason tooltip, or when it sits in a CheckboxList whose whole-group
|
|
407
|
+
// `disabledMessage` (shown on the group container) needs each checkbox to
|
|
408
|
+
// stay keyboard-perceivable. The group signals this through context rather
|
|
409
|
+
// than a public prop.
|
|
410
|
+
const checkboxListContext = use(CheckboxListContext);
|
|
411
|
+
const isFocusableDisabled =
|
|
412
|
+
isDisabled &&
|
|
413
|
+
(showsDisabledMessage ||
|
|
414
|
+
(checkboxListContext?.hasDisabledMessage ?? false));
|
|
415
|
+
const disabledMessageTooltip = useTooltip({
|
|
416
|
+
placement: 'above',
|
|
417
|
+
// The container row is not naturally focusable; focusin bubbles up from the
|
|
418
|
+
// native checkbox, so always attach focus listeners.
|
|
419
|
+
focusTrigger: 'always',
|
|
420
|
+
isEnabled: showsDisabledMessage,
|
|
421
|
+
});
|
|
422
|
+
|
|
375
423
|
const isIndeterminate = optimisticValue === 'indeterminate';
|
|
376
424
|
const isChecked = optimisticValue === true;
|
|
377
425
|
const isCheckedOrIndeterminate = isChecked || isIndeterminate;
|
|
378
426
|
|
|
379
|
-
// Sync the native indeterminate DOM property (can't be set via JSX
|
|
427
|
+
// Sync the native indeterminate DOM property (can't be set via JSX
|
|
428
|
+
// attribute). On a native checkbox this is the authoritative way to expose
|
|
429
|
+
// the mixed state — a separate aria-checked="mixed" would be redundant and
|
|
430
|
+
// can desync from / override the native state (forms-16), so it is omitted.
|
|
380
431
|
const indeterminateRef = useCallback(
|
|
381
432
|
(el: HTMLInputElement | null) => {
|
|
382
433
|
if (el) {
|
|
@@ -395,6 +446,9 @@ export function CheckboxInput({
|
|
|
395
446
|
if (status?.message) {
|
|
396
447
|
describedByParts.push(statusMessageID);
|
|
397
448
|
}
|
|
449
|
+
if (showsDisabledMessage) {
|
|
450
|
+
describedByParts.push(disabledMessageTooltip.describedBy);
|
|
451
|
+
}
|
|
398
452
|
const ariaDescribedBy =
|
|
399
453
|
describedByParts.length > 0 ? describedByParts.join(' ') : undefined;
|
|
400
454
|
|
|
@@ -407,6 +461,15 @@ export function CheckboxInput({
|
|
|
407
461
|
style,
|
|
408
462
|
)}>
|
|
409
463
|
<div
|
|
464
|
+
ref={el => {
|
|
465
|
+
// Interaction (hover/focus) listeners for the disabled-message
|
|
466
|
+
// tooltip attach to the whole row for a larger trigger target;
|
|
467
|
+
// positioning anchors on the checkbox itself (below) so the tooltip
|
|
468
|
+
// appears next to the control, not the far edge of the row.
|
|
469
|
+
// Handlers are gated internally by isEnabled, so attaching
|
|
470
|
+
// unconditionally is safe.
|
|
471
|
+
disabledMessageTooltip.interactionRef(el);
|
|
472
|
+
}}
|
|
410
473
|
{...stylex.props(
|
|
411
474
|
styles.container,
|
|
412
475
|
isLabelHidden && styles.containerLabelHidden,
|
|
@@ -414,15 +477,23 @@ export function CheckboxInput({
|
|
|
414
477
|
)}>
|
|
415
478
|
<div {...stylex.props(styles.checkboxWrapper, wrapperSizeStyles[size])}>
|
|
416
479
|
<input
|
|
417
|
-
ref={mergeRefs(
|
|
480
|
+
ref={mergeRefs(
|
|
481
|
+
ref,
|
|
482
|
+
indeterminateRef,
|
|
483
|
+
disabledMessageTooltip.positionRef,
|
|
484
|
+
)}
|
|
418
485
|
id={id}
|
|
419
486
|
type="checkbox"
|
|
420
487
|
checked={isChecked}
|
|
421
|
-
|
|
488
|
+
// With a disabledMessage the checkbox keeps focusability via
|
|
489
|
+
// aria-disabled so the reason is focus-discoverable; toggling is
|
|
490
|
+
// still blocked by the isDisabled guard in onChange below.
|
|
491
|
+
disabled={isDisabled && !isFocusableDisabled}
|
|
492
|
+
aria-disabled={isFocusableDisabled ? 'true' : undefined}
|
|
422
493
|
readOnly={isReadOnly}
|
|
423
494
|
required={isRequired}
|
|
424
495
|
onChange={e => {
|
|
425
|
-
if (isBusy || isReadOnly) {
|
|
496
|
+
if (isDisabled || isBusy || isReadOnly) {
|
|
426
497
|
return;
|
|
427
498
|
}
|
|
428
499
|
const checked = e.target.checked;
|
|
@@ -436,7 +507,6 @@ export function CheckboxInput({
|
|
|
436
507
|
}}
|
|
437
508
|
onFocus={onFocus}
|
|
438
509
|
onBlur={onBlur}
|
|
439
|
-
aria-checked={isIndeterminate ? 'mixed' : undefined}
|
|
440
510
|
aria-readonly={isReadOnly || undefined}
|
|
441
511
|
aria-describedby={ariaDescribedBy}
|
|
442
512
|
aria-invalid={status?.type === 'error' ? true : undefined}
|
|
@@ -525,6 +595,8 @@ export function CheckboxInput({
|
|
|
525
595
|
variant="detached"
|
|
526
596
|
/>
|
|
527
597
|
)}
|
|
598
|
+
{showsDisabledMessage &&
|
|
599
|
+
disabledMessageTooltip.renderTooltip(disabledMessage)}
|
|
528
600
|
</div>
|
|
529
601
|
);
|
|
530
602
|
}
|
|
@@ -77,6 +77,12 @@ export const docs = {
|
|
|
77
77
|
description: 'Whether all checkbox items are disabled.',
|
|
78
78
|
default: 'false',
|
|
79
79
|
},
|
|
80
|
+
{
|
|
81
|
+
name: 'disabledMessage',
|
|
82
|
+
type: 'string',
|
|
83
|
+
description:
|
|
84
|
+
'Explains why the group is disabled. Applies to the whole-group disabled state (isDisabled), not per item. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the checkboxes focusable via aria-disabled (toggling stays blocked). Use this instead of wrapping a disabled CheckboxList in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.',
|
|
85
|
+
},
|
|
80
86
|
{
|
|
81
87
|
name: 'status',
|
|
82
88
|
type: 'InputStatus',
|
|
@@ -99,6 +105,7 @@ export const docs = {
|
|
|
99
105
|
{ guidance: true, description: 'Write a group label that says what the choices represent: "Export formats" tells users more than "Options".' },
|
|
100
106
|
{ guidance: false, description: 'Show a CheckboxList when the user can only pick one thing; that is what RadioList is for.' },
|
|
101
107
|
{ guidance: false, description: 'Put buttons or links inside the trailing slot (endContent); the whole row is already tappable, so a nested button creates two competing click targets.' },
|
|
108
|
+
{ guidance: false, description: 'Wrap a disabled CheckboxList in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.' },
|
|
102
109
|
],
|
|
103
110
|
},
|
|
104
111
|
};
|
|
@@ -113,6 +120,7 @@ export const docsZh = {
|
|
|
113
120
|
{ guidance: true, description: 'Write a group label that says what the choices represent: "Export formats" tells users more than "Options".' },
|
|
114
121
|
{ guidance: false, description: 'Show a CheckboxList when the user can only pick one thing; that is what RadioList is for.' },
|
|
115
122
|
{ guidance: false, description: 'Put buttons or links inside the trailing slot (endContent); the whole row is already tappable, so a nested button creates two competing click targets.' },
|
|
123
|
+
{ guidance: false, description: 'Wrap a disabled CheckboxList in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.' },
|
|
116
124
|
],
|
|
117
125
|
},
|
|
118
126
|
};
|
|
@@ -129,6 +137,7 @@ export const docsDense = {
|
|
|
129
137
|
{ guidance: true, description: 'Write a group label that says what the choices represent: "Export formats" tells users more than "Options".' },
|
|
130
138
|
{ guidance: false, description: 'Show a CheckboxList when the user can only pick one thing; that is what RadioList is for.' },
|
|
131
139
|
{ guidance: false, description: 'Put buttons or links inside the trailing slot (endContent); the whole row is already tappable, so a nested button creates two competing click targets.' },
|
|
140
|
+
{ guidance: false, description: 'Wrap a disabled CheckboxList in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.' },
|
|
132
141
|
],
|
|
133
142
|
},
|
|
134
143
|
};
|