@astryxdesign/core 0.1.1 → 0.1.2-canary.04e71b2
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 +105 -0
- package/README.md +131 -13
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +11 -5
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +4 -1
- package/dist/Banner/Banner.d.ts +7 -0
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +9 -2
- 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 +12 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +53 -17
- 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/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.map +1 -1
- package/dist/Chat/useTriggerMenu.js +4 -1
- 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/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +3 -3
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +49 -37
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +5 -5
- package/dist/ContextMenu/ContextMenu.d.ts +4 -5
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +93 -11
- package/dist/DateInput/DateInput.d.ts +23 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +59 -8
- 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/EmptyState/EmptyState.d.ts.map +1 -1
- package/dist/EmptyState/EmptyState.js +7 -1
- 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 +8 -0
- package/dist/HoverCard/HoverCard.d.ts +2 -2
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +18 -6
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +7 -3
- package/dist/InputGroup/InputGroup.d.ts +2 -2
- package/dist/InputGroup/InputGroup.d.ts.map +1 -1
- package/dist/InputGroup/InputGroup.js +14 -5
- 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/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 +34 -2
- package/dist/Layer/anchorName.d.ts +20 -0
- package/dist/Layer/anchorName.d.ts.map +1 -0
- package/dist/Layer/anchorName.js +36 -0
- 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 +29 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +55 -11
- 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 +17 -2
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +20 -9
- package/dist/Link/LinkProvider.d.ts +1 -0
- package/dist/Link/LinkProvider.d.ts.map +1 -1
- package/dist/Link/LinkProvider.js +1 -0
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +18 -3
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +13 -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 +25 -2
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +103 -22
- 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 +46 -28
- package/dist/Popover/usePopover.d.ts +25 -2
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +18 -6
- 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 +22 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +84 -23
- 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/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 +38 -11
- 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 +86 -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 +38 -16
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +36 -7
- package/dist/Table/TableCell.d.ts +8 -1
- package/dist/Table/TableCell.d.ts.map +1 -1
- package/dist/Table/TableCell.js +10 -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/TableRow.d.ts +6 -1
- package/dist/Table/TableRow.d.ts.map +1 -1
- package/dist/Table/TableRow.js +15 -7
- 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/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +59 -3
- package/dist/Table/plugins/stickyColumns/index.d.ts +3 -0
- package/dist/Table/plugins/stickyColumns/index.d.ts.map +1 -0
- package/dist/Table/plugins/stickyColumns/index.js +3 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts +25 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +369 -0
- package/dist/Table/tableContextMenu.d.ts +33 -0
- package/dist/Table/tableContextMenu.d.ts.map +1 -0
- package/dist/Table/tableContextMenu.js +133 -0
- package/dist/Table/types.d.ts +161 -5
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +1 -1
- package/dist/Text/text.stylex.d.ts +2 -2
- package/dist/Text/text.stylex.js +2 -2
- 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 +53 -10
- package/dist/Timestamp/Timestamp.d.ts +1 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +28 -3
- 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 +132 -3
- package/dist/ToggleButton/ToggleButton.d.ts +7 -9
- package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButton.js +34 -57
- package/dist/Tokenizer/Tokenizer.d.ts +12 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +27 -5
- 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 +57 -9
- 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 +9 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +67 -6
- package/dist/Typeahead/Typeahead.d.ts +24 -1
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +29 -5
- 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 +40 -1
- package/dist/astryx.umd.js +147 -0
- package/dist/astryx.umd.js.map +7 -0
- 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/theme/generateThemeRules.js +1 -1
- package/dist/theme/syntax/SyntaxTheme.d.ts +1 -1
- package/dist/theme/syntax/SyntaxTheme.js +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.js +2 -2
- package/dist/theme/syntax/presets.d.ts +1 -1
- package/dist/theme/syntax/presets.d.ts.map +1 -1
- package/dist/theme/syntax/presets.js +1 -1
- package/dist/theme/syntax/tokens.d.ts +1 -1
- package/dist/theme/syntax/tokens.js +1 -1
- package/dist/theme/types.d.ts +1 -1
- 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/package.json +15 -5
- package/src/Avatar/Avatar.test.tsx +37 -0
- package/src/Avatar/Avatar.tsx +10 -5
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +3 -0
- package/src/Banner/Banner.doc.mjs +8 -0
- package/src/Banner/Banner.test.tsx +16 -7
- package/src/Banner/Banner.tsx +9 -2
- package/src/Breadcrumbs/BreadcrumbItem.tsx +25 -7
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +31 -10
- package/src/Button/Button.doc.mjs +6 -0
- package/src/Button/Button.test.tsx +105 -11
- package/src/Button/Button.tsx +76 -21
- 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/ChatComposer.doc.mjs +3 -0
- package/src/Chat/ChatComposerDrawer.doc.mjs +12 -0
- 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 +3 -0
- package/src/CheckboxInput/CheckboxInput.doc.mjs +18 -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 +169 -16
- package/src/CheckboxList/CheckboxList.tsx +56 -3
- package/src/CheckboxList/CheckboxListContext.tsx +7 -0
- package/src/Citation/Citation.doc.mjs +10 -0
- package/src/Citation/Citation.test.tsx +117 -0
- package/src/Citation/Citation.tsx +9 -1
- package/src/ClickableCard/ClickableCard.doc.mjs +15 -0
- package/src/CodeBlock/CodeBlock.test.tsx +115 -0
- package/src/CodeBlock/CodeBlock.tsx +61 -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 +113 -16
- package/src/DateInput/DateInput.doc.mjs +281 -56
- package/src/DateInput/DateInput.test.tsx +188 -2
- package/src/DateInput/DateInput.tsx +89 -10
- 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/EmptyState/EmptyState.test.tsx +4 -2
- package/src/EmptyState/EmptyState.tsx +6 -2
- 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 +14 -4
- package/src/Grid/Grid.tsx +20 -0
- package/src/HoverCard/HoverCard.doc.mjs +3 -0
- package/src/HoverCard/HoverCard.test.tsx +189 -2
- package/src/HoverCard/HoverCard.tsx +20 -16
- package/src/HoverCard/useHoverCard.tsx +13 -10
- package/src/Icon/Icon.doc.mjs +8 -0
- package/src/InputGroup/InputGroup.doc.mjs +2 -2
- package/src/InputGroup/InputGroup.test.tsx +98 -60
- package/src/InputGroup/InputGroup.tsx +21 -4
- package/src/InputGroup/InputGroupContext.ts +9 -4
- package/src/InputGroup/index.ts +1 -0
- package/src/Kbd/Kbd.test.tsx +22 -4
- package/src/Kbd/Kbd.tsx +37 -12
- package/src/Layer/anchorName.test.ts +146 -0
- package/src/Layer/anchorName.ts +46 -0
- package/src/Layer/layerAnimations.stylex.ts +20 -4
- package/src/Layer/useLayer.doc.mjs +12 -2
- package/src/Layer/useLayer.tsx +100 -15
- package/src/Layout/Layout.doc.mjs +1 -1
- 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/padding.stylex.ts +52 -0
- package/src/Lightbox/Lightbox.doc.mjs +9 -2
- 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 +52 -2
- package/src/Link/Link.tsx +42 -7
- package/src/Link/LinkProvider.tsx +1 -0
- package/src/List/List.doc.mjs +7 -0
- package/src/Markdown/Markdown.doc.mjs +2 -0
- package/src/Markdown/Markdown.test.tsx +28 -26
- package/src/Markdown/Markdown.tsx +21 -6
- package/src/MetadataList/MetadataListItem.doc.mjs +4 -0
- package/src/MobileNav/MobileNav.doc.mjs +8 -8
- package/src/MobileNav/MobileNav.tsx +13 -0
- package/src/MobileNav/MobileNavReopen.test.tsx +118 -0
- package/src/MoreMenu/MoreMenu.doc.mjs +2 -17
- package/src/MoreMenu/MoreMenu.tsx +0 -9
- package/src/MultiSelector/MultiSelector.doc.mjs +25 -0
- package/src/MultiSelector/MultiSelector.test.tsx +375 -8
- package/src/MultiSelector/MultiSelector.tsx +145 -21
- 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/OverflowList/OverflowList.doc.mjs +17 -0
- package/src/Pagination/Pagination.doc.mjs +3 -3
- package/src/Pagination/Pagination.test.tsx +250 -14
- package/src/Pagination/Pagination.tsx +54 -29
- package/src/Popover/usePopover.doc.mjs +7 -3
- package/src/Popover/usePopover.tsx +49 -6
- 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 +45 -27
- 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/Resizable/Resizable.doc.mjs +1 -1
- package/src/Section/Section.doc.mjs +11 -0
- 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 +15 -0
- package/src/Selector/Selector.doc.mjs +25 -0
- package/src/Selector/Selector.test.tsx +322 -15
- package/src/Selector/Selector.tsx +126 -40
- package/src/Selector/hooks.ts +23 -0
- package/src/SideNav/SideNav.test.tsx +16 -0
- package/src/SideNav/SideNavItem.tsx +2 -4
- package/src/Skeleton/Skeleton.doc.mjs +11 -1
- package/src/Skeleton/Skeleton.test.tsx +25 -0
- package/src/Skeleton/Skeleton.tsx +11 -1
- package/src/Slider/Slider.doc.mjs +19 -0
- package/src/Slider/Slider.test.tsx +158 -18
- package/src/Slider/Slider.tsx +54 -6
- 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 +12 -0
- package/src/TabList/TabList.test.tsx +208 -0
- package/src/TabList/TabList.tsx +102 -12
- package/src/TabList/TabListContext.ts +7 -3
- package/src/TabList/TabMenu.tsx +6 -3
- package/src/Table/BaseTable.tsx +72 -41
- package/src/Table/Table.doc.mjs +14 -0
- package/src/Table/Table.test.tsx +39 -30
- package/src/Table/Table.tsx +27 -1
- package/src/Table/TableCell.tsx +25 -23
- package/src/Table/TableHeaderCell.tsx +28 -29
- package/src/Table/TableRow.tsx +37 -7
- package/src/Table/index.ts +6 -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/sortable/useTableSortable.test.tsx +91 -2
- package/src/Table/plugins/sortable/useTableSortable.tsx +53 -1
- package/src/Table/plugins/stickyColumns/index.ts +4 -0
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.test.tsx +163 -0
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +407 -0
- package/src/Table/tableContextMenu.test.tsx +157 -0
- package/src/Table/tableContextMenu.tsx +142 -0
- package/src/Table/types.ts +175 -4
- package/src/Table/useBaseTablePlugins.ts +1 -0
- package/src/Table/useTableColumnResize.doc.mjs +96 -0
- package/src/Table/useTableStickyColumns.doc.mjs +59 -0
- package/src/Text/Heading.doc.mjs +15 -2
- package/src/Text/Text.doc.mjs +7 -1
- package/src/Text/text.stylex.ts +2 -2
- 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/TimeInput/TimeInput.doc.mjs +335 -60
- package/src/TimeInput/TimeInput.test.tsx +144 -7
- package/src/TimeInput/TimeInput.tsx +74 -5
- package/src/Timestamp/Timestamp.doc.mjs +9 -0
- package/src/Timestamp/Timestamp.test.tsx +44 -18
- package/src/Timestamp/Timestamp.tsx +30 -10
- package/src/Toast/Toast.tsx +14 -0
- package/src/Toast/ToastViewport.test.tsx +204 -0
- package/src/Toast/ToastViewport.tsx +167 -21
- package/src/ToggleButton/ToggleButton.doc.mjs +9 -3
- package/src/ToggleButton/ToggleButton.test.tsx +39 -18
- package/src/ToggleButton/ToggleButton.tsx +46 -83
- package/src/Tokenizer/Tokenizer.doc.mjs +15 -0
- package/src/Tokenizer/Tokenizer.test.tsx +105 -1
- package/src/Tokenizer/Tokenizer.tsx +41 -2
- package/src/Toolbar/Toolbar.doc.mjs +65 -5
- package/src/Toolbar/Toolbar.test.tsx +109 -6
- package/src/Toolbar/Toolbar.tsx +59 -5
- package/src/Tooltip/Tooltip.test.tsx +81 -0
- package/src/Tooltip/useTooltip.tsx +57 -11
- 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 +86 -9
- package/src/Typeahead/Typeahead.doc.mjs +136 -30
- package/src/Typeahead/Typeahead.test.tsx +331 -1
- package/src/Typeahead/Typeahead.tsx +52 -1
- 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/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/useImageMode.test.ts +133 -0
- 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 +4 -0
- package/src/theme/generateThemeRules.test.ts +7 -8
- package/src/theme/generateThemeRules.ts +1 -1
- package/src/theme/syntax/SyntaxTheme.tsx +1 -1
- package/src/theme/syntax/defineSyntaxTheme.ts +20 -11
- package/src/theme/syntax/presets.ts +5 -2
- package/src/theme/syntax/tokens.ts +1 -1
- package/src/theme/types.ts +1 -1
- 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
|
@@ -21,7 +21,7 @@ export const docs = {
|
|
|
21
21
|
anatomy: [
|
|
22
22
|
{name: 'Scroll container', required: true, description: 'The horizontal overflow area that holds all items.'},
|
|
23
23
|
{name: 'Items', required: true, description: 'The children rendered in a row. Each item is animated with a scroll-driven scale effect.'},
|
|
24
|
-
{name: 'Fade edges', required:
|
|
24
|
+
{name: 'Fade edges', required: false, description: 'Gradient fades on the left and right edges that indicate more content is available. Enabled by default, disable with hasEdgeFade={false}.'},
|
|
25
25
|
{name: 'Navigation buttons', required: false, description: 'Prev/next buttons that appear on hover. Enabled by default, disable with hasButtons={false}.'},
|
|
26
26
|
],
|
|
27
27
|
},
|
|
@@ -29,7 +29,9 @@ export const docs = {
|
|
|
29
29
|
{name: 'children', type: 'ReactNode', description: 'Carousel items rendered in a horizontal scroll container.', required: true},
|
|
30
30
|
{name: 'gap', type: "0 | 0.5 | 1 | 1.5 | 2 | 3 | 4", description: 'Gap between items using the spacing token scale.', default: '1'},
|
|
31
31
|
{name: 'hasButtons', type: 'boolean', description: 'Show prev/next navigation buttons on hover (desktop only).', default: 'true'},
|
|
32
|
+
{name: 'hasEdgeFade', type: 'boolean', description: 'Show a gradient edge-fade mask when content overflows, signalling that more items exist off-screen.', default: 'true'},
|
|
32
33
|
{name: 'hasSnap', type: 'boolean', description: 'Enable scroll-snap so each child snaps to the start edge.', default: 'false'},
|
|
34
|
+
{name: 'padding', type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10', description: 'Inline padding inside the scroll container, with matching scroll-padding so snap points align to the content edge.'},
|
|
33
35
|
{name: 'aria-label', type: 'string', description: 'Accessible label for the carousel region.', default: "\'Carousel\'"},
|
|
34
36
|
{name: 'ref', type: 'React.Ref<HTMLDivElement>', description: 'Ref forwarded to the root element.'},
|
|
35
37
|
{name: 'xstyle', type: 'StyleXStyles', description: 'StyleX styles for layout customization (margins, positioning, sizing). Must be a stylex.create() value.'},
|
|
@@ -71,7 +73,9 @@ export const docsZh = {
|
|
|
71
73
|
children: '在水平滚动容器中渲染的轮播项目。',
|
|
72
74
|
gap: '使用间距令牌比例的项目间距。',
|
|
73
75
|
hasButtons: '悬停时显示上一个/下一个导航按钮(仅桌面端)。',
|
|
76
|
+
hasEdgeFade: '内容溢出时显示渐变边缘遮罩,提示屏幕外还有更多项目。',
|
|
74
77
|
hasSnap: '启用滚动吸附,使每个子元素吸附到起始边缘。',
|
|
78
|
+
padding: '滚动容器内的内联内边距,并设置匹配的 scroll-padding,使吸附点与内容边缘对齐。',
|
|
75
79
|
'aria-label': '轮播区域的无障碍标签。',
|
|
76
80
|
},
|
|
77
81
|
};
|
|
@@ -95,7 +99,9 @@ export const docsDense = {
|
|
|
95
99
|
children: 'carousel items in horizontal scroll',
|
|
96
100
|
gap: 'item spacing via spacing token scale',
|
|
97
101
|
hasButtons: 'prev/next buttons on hover (desktop)',
|
|
102
|
+
hasEdgeFade: 'gradient edge-fade mask on overflow',
|
|
98
103
|
hasSnap: 'scroll-snap; children snap to start edge',
|
|
104
|
+
padding: 'inline padding; scroll-padding keeps snap points on content edge',
|
|
99
105
|
'aria-label': 'accessible label for carousel region',
|
|
100
106
|
'data-testid': 'test selector for automated testing frameworks',
|
|
101
107
|
},
|
|
@@ -78,4 +78,24 @@ describe('Carousel', () => {
|
|
|
78
78
|
expect(screen.getByLabelText('Scroll left')).toBeInTheDocument();
|
|
79
79
|
expect(screen.getByLabelText('Scroll right')).toBeInTheDocument();
|
|
80
80
|
});
|
|
81
|
+
|
|
82
|
+
it('disables edge scroll buttons instead of removing them from the tab order', () => {
|
|
83
|
+
// In jsdom there is no measurable overflow, so both edges are at rest and
|
|
84
|
+
// the scroll buttons are in their hidden/inert state. They must stay
|
|
85
|
+
// mounted but be disabled — a disabled <button> is skipped by the tab
|
|
86
|
+
// order and hidden from the a11y tree, so keyboard users don't focus an
|
|
87
|
+
// invisible control (WCAG 2.4.7).
|
|
88
|
+
render(
|
|
89
|
+
<Carousel aria-label="Edge state">
|
|
90
|
+
<div>Item 1</div>
|
|
91
|
+
<div>Item 2</div>
|
|
92
|
+
</Carousel>,
|
|
93
|
+
);
|
|
94
|
+
const left = screen.getByLabelText('Scroll left');
|
|
95
|
+
const right = screen.getByLabelText('Scroll right');
|
|
96
|
+
expect(left).toBeInTheDocument();
|
|
97
|
+
expect(right).toBeInTheDocument();
|
|
98
|
+
expect(left).toBeDisabled();
|
|
99
|
+
expect(right).toBeDisabled();
|
|
100
|
+
});
|
|
81
101
|
});
|
|
@@ -295,9 +295,16 @@ export function Carousel({
|
|
|
295
295
|
const firstChild = el.firstElementChild as HTMLElement | null;
|
|
296
296
|
const itemWidth = firstChild ? firstChild.offsetWidth : 0;
|
|
297
297
|
const amount = el.clientWidth - itemWidth * 0.5;
|
|
298
|
+
// Respect the user's reduced-motion preference — mirrors the CSS
|
|
299
|
+
// scroll-behavior override so button-driven scrolling doesn't animate
|
|
300
|
+
// for users who opted out of motion.
|
|
301
|
+
const prefersReducedMotion =
|
|
302
|
+
typeof window !== 'undefined' &&
|
|
303
|
+
typeof window.matchMedia === 'function' &&
|
|
304
|
+
window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
298
305
|
el.scrollBy({
|
|
299
306
|
left: direction * Math.max(amount, itemWidth),
|
|
300
|
-
behavior: 'smooth',
|
|
307
|
+
behavior: prefersReducedMotion ? 'auto' : 'smooth',
|
|
301
308
|
});
|
|
302
309
|
}, []);
|
|
303
310
|
|
|
@@ -360,6 +367,11 @@ export function Carousel({
|
|
|
360
367
|
variant="ghost"
|
|
361
368
|
size="sm"
|
|
362
369
|
isIconOnly
|
|
370
|
+
// Disabled when there's nothing to scroll toward. Keeps the
|
|
371
|
+
// button mounted (stable layout/focus) but removes it from the
|
|
372
|
+
// tab order and a11y tree while it's visually hidden, so
|
|
373
|
+
// keyboard users don't land on an invisible control.
|
|
374
|
+
isDisabled={!overflowStart}
|
|
363
375
|
onClick={() => scrollBy(-1)}
|
|
364
376
|
xstyle={styles.buttonRadiusOverride}
|
|
365
377
|
/>
|
|
@@ -376,6 +388,9 @@ export function Carousel({
|
|
|
376
388
|
variant="ghost"
|
|
377
389
|
size="sm"
|
|
378
390
|
isIconOnly
|
|
391
|
+
// See "Scroll left" — disabled while visually hidden so the
|
|
392
|
+
// button stays mounted but out of the tab order / a11y tree.
|
|
393
|
+
isDisabled={!overflowEnd}
|
|
379
394
|
onClick={() => scrollBy(1)}
|
|
380
395
|
xstyle={styles.buttonRadiusOverride}
|
|
381
396
|
/>
|
|
@@ -18,14 +18,24 @@ export const docs = {
|
|
|
18
18
|
},
|
|
19
19
|
{
|
|
20
20
|
name: 'width',
|
|
21
|
-
type: '
|
|
21
|
+
type: 'SizeValue',
|
|
22
22
|
description: 'Container width (px or CSS value).',
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
name: 'height',
|
|
26
|
-
type: '
|
|
26
|
+
type: 'SizeValue',
|
|
27
27
|
description: 'Container height (px or CSS value).',
|
|
28
28
|
},
|
|
29
|
+
{
|
|
30
|
+
name: 'maxWidth',
|
|
31
|
+
type: 'SizeValue',
|
|
32
|
+
description: 'Maximum container width (px or CSS value).',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'minHeight',
|
|
36
|
+
type: 'SizeValue',
|
|
37
|
+
description: 'Minimum container height (px or CSS value).',
|
|
38
|
+
},
|
|
29
39
|
{
|
|
30
40
|
name: 'isInline',
|
|
31
41
|
type: 'boolean',
|
package/src/Center/Center.tsx
CHANGED
|
@@ -39,15 +39,21 @@ const styles = stylex.create({
|
|
|
39
39
|
|
|
40
40
|
// Dynamic styles for sizing props
|
|
41
41
|
const dynamicStyles = stylex.create({
|
|
42
|
-
sizing: (
|
|
42
|
+
sizing: (
|
|
43
|
+
width: SizeValue | null,
|
|
44
|
+
height: SizeValue | null,
|
|
45
|
+
maxWidth: SizeValue | null,
|
|
46
|
+
minHeight: SizeValue | null,
|
|
47
|
+
) => ({
|
|
43
48
|
width,
|
|
44
49
|
height,
|
|
50
|
+
maxWidth,
|
|
51
|
+
minHeight,
|
|
45
52
|
}),
|
|
46
53
|
});
|
|
47
54
|
|
|
48
55
|
export type CenterAxis = 'both' | 'horizontal' | 'vertical';
|
|
49
56
|
|
|
50
|
-
|
|
51
57
|
export interface CenterProps extends BaseProps<HTMLDivElement> {
|
|
52
58
|
/** Ref forwarded to the root element */
|
|
53
59
|
ref?: React.Ref<HTMLDivElement>;
|
|
@@ -72,6 +78,18 @@ export interface CenterProps extends BaseProps<HTMLDivElement> {
|
|
|
72
78
|
*/
|
|
73
79
|
height?: SizeValue;
|
|
74
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Maximum width of the container.
|
|
83
|
+
* Numbers are treated as pixels, strings are used as-is (e.g., '100%').
|
|
84
|
+
*/
|
|
85
|
+
maxWidth?: SizeValue;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Minimum height of the container.
|
|
89
|
+
* Numbers are treated as pixels, strings are used as-is (e.g., '100%').
|
|
90
|
+
*/
|
|
91
|
+
minHeight?: SizeValue;
|
|
92
|
+
|
|
75
93
|
/**
|
|
76
94
|
* Whether to make the container inline-flex (useful for text/icons).
|
|
77
95
|
* @default false
|
|
@@ -101,6 +119,8 @@ export function Center({
|
|
|
101
119
|
axis = 'both',
|
|
102
120
|
width,
|
|
103
121
|
height,
|
|
122
|
+
maxWidth,
|
|
123
|
+
minHeight,
|
|
104
124
|
isInline = false,
|
|
105
125
|
children,
|
|
106
126
|
xstyle,
|
|
@@ -115,7 +135,12 @@ export function Center({
|
|
|
115
135
|
isInline ? styles.inline : styles.base,
|
|
116
136
|
(axis === 'both' || axis === 'vertical') && styles.alignItemsCenter,
|
|
117
137
|
(axis === 'both' || axis === 'horizontal') && styles.justifyContentCenter,
|
|
118
|
-
dynamicStyles.sizing(
|
|
138
|
+
dynamicStyles.sizing(
|
|
139
|
+
width ?? null,
|
|
140
|
+
height ?? null,
|
|
141
|
+
maxWidth ?? null,
|
|
142
|
+
minHeight ?? null,
|
|
143
|
+
),
|
|
119
144
|
xstyle,
|
|
120
145
|
),
|
|
121
146
|
className,
|
|
@@ -7,6 +7,9 @@ export const docs = {
|
|
|
7
7
|
subComponentOf: 'Chat',
|
|
8
8
|
displayName: 'Chat Composer',
|
|
9
9
|
description: 'Layout shell for a chat composer. Arranges named slots (drawer, header, input, footer, send) with page-radius container, hover/focus shadows, and concentric inner radius for child elements.',
|
|
10
|
+
playground: {
|
|
11
|
+
wrapper: {component: 'Stack', props: {width: 480}},
|
|
12
|
+
},
|
|
10
13
|
props: [
|
|
11
14
|
{
|
|
12
15
|
name: 'onSubmit',
|
|
@@ -8,6 +8,18 @@ export const docs = {
|
|
|
8
8
|
displayName: 'Chat Composer Drawer',
|
|
9
9
|
isHiddenFromOverview: true,
|
|
10
10
|
description: "Collapsible drawer panel that sits above the chat input inside ChatComposer. Pass it to the composer's `drawer` slot to show attachments, context chips, or any supplementary content. When `count` is provided the drawer gains a collapse toggle: collapsed state shows a badge and label, expanded state shows all children.",
|
|
11
|
+
playground: {
|
|
12
|
+
wrapper: {component: 'Stack', props: {width: 480}},
|
|
13
|
+
defaults: {
|
|
14
|
+
count: 3,
|
|
15
|
+
label: 'Attachments',
|
|
16
|
+
children: [
|
|
17
|
+
{__element: 'Token', props: {label: 'design-spec.pdf'}},
|
|
18
|
+
{__element: 'Token', props: {label: 'api-schema.json'}},
|
|
19
|
+
{__element: 'Token', props: {label: 'screenshot.png'}},
|
|
20
|
+
],
|
|
21
|
+
},
|
|
22
|
+
},
|
|
11
23
|
props: [
|
|
12
24
|
{
|
|
13
25
|
name: 'children',
|
|
@@ -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(
|
|
@@ -296,6 +296,9 @@ export function useTriggerMenu(
|
|
|
296
296
|
hasLightDismiss: true,
|
|
297
297
|
hasCloseButton: false,
|
|
298
298
|
hasAutoFocus: false,
|
|
299
|
+
// The popup's own role="listbox" is the exposed semantics; focus stays in
|
|
300
|
+
// the contenteditable composer, so a modal dialog wrapper is incorrect.
|
|
301
|
+
role: 'none',
|
|
299
302
|
});
|
|
300
303
|
|
|
301
304
|
// Cleanup on unmount
|
|
@@ -63,6 +63,19 @@ 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
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: 'isReadOnly',
|
|
74
|
+
type: 'boolean',
|
|
75
|
+
description:
|
|
76
|
+
'Whether the checkbox is read-only. Displays the current state at full opacity but prevents interaction. Unlike `isDisabled`, read-only checkboxes are not visually dimmed.',
|
|
77
|
+
default: 'false',
|
|
78
|
+
},
|
|
66
79
|
{
|
|
67
80
|
name: 'isOptional',
|
|
68
81
|
type: 'boolean',
|
|
@@ -117,6 +130,7 @@ export const docs = {
|
|
|
117
130
|
{ guidance: true, description: 'Use the indeterminate state for "select all" checkboxes when only some items in a group are selected.' },
|
|
118
131
|
{ guidance: false, description: 'Use a checkbox for mutually exclusive choices; use RadioList when only one option can be selected.' },
|
|
119
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.' },
|
|
120
134
|
],
|
|
121
135
|
anatomy: [
|
|
122
136
|
{ name: 'Checkbox', required: true, description: 'The check box itself: unchecked, checked, or indeterminate.' },
|
|
@@ -139,6 +153,7 @@ export const docsZh = {
|
|
|
139
153
|
{ guidance: true, description: 'Use the indeterminate state for "select all" checkboxes when only some items in a group are selected.' },
|
|
140
154
|
{ guidance: false, description: 'Use a checkbox for mutually exclusive choices; use RadioList when only one option can be selected.' },
|
|
141
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.' },
|
|
142
157
|
],
|
|
143
158
|
},
|
|
144
159
|
props: [
|
|
@@ -156,6 +171,8 @@ export const docsZh = {
|
|
|
156
171
|
},
|
|
157
172
|
{name: 'isLoading', type: 'boolean', description: '复选框是否处于加载状态。显示旋转器并阻止交互。', default: 'false'},
|
|
158
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.'},
|
|
175
|
+
{name: 'isReadOnly', type: 'boolean', description: '复选框是否为只读。以完整不透明度显示当前状态但阻止交互。与 isDisabled 不同,只读复选框不会变暗。', default: 'false'},
|
|
159
176
|
{name: 'isOptional', type: 'boolean', description: '字段是否可选。与 isRequired 互斥。', default: 'false'},
|
|
160
177
|
{name: 'isRequired', type: 'boolean', description: '复选框是否必填。与 isOptional 互斥。', default: 'false'},
|
|
161
178
|
{name: 'size', type: "'sm' | 'md'", description: '复选框尺寸。sm 用于紧凑布局,md 为默认。', default: "'md'"},
|
|
@@ -192,6 +209,7 @@ export const docsDense = {
|
|
|
192
209
|
{ guidance: true, description: 'Use the indeterminate state for "select all" checkboxes when only some items in a group are selected.' },
|
|
193
210
|
{ guidance: false, description: 'Use a checkbox for mutually exclusive choices; use RadioList when only one option can be selected.' },
|
|
194
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.' },
|
|
195
213
|
],
|
|
196
214
|
},
|
|
197
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
|
});
|