@astryxdesign/core 0.1.2 → 0.1.3-canary.6d57c8d
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 +2 -4
- 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 +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 +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 +11 -8
- 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 +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/index.d.ts +2 -1
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +2 -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/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 +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 +18 -0
- package/dist/astryx.umd.js +55 -55
- 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.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 +3 -16
- 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 +113 -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/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 +21 -17
- 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 +25 -23
- package/src/Table/TableHeaderCell.tsx +28 -29
- package/src/Table/index.ts +3 -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/tableContextMenu.test.tsx +157 -0
- package/src/Table/tableContextMenu.tsx +142 -0
- package/src/Table/types.ts +74 -0
- package/src/Table/useTableColumnResize.doc.mjs +3 -3
- 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 +340 -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
package/src/Switch/Switch.tsx
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file Switch.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 Switch component, SwitchProps, SwitchLabelPosition, SwitchLabelSpacing
|
|
9
9
|
* @position Core implementation; consumed by index.ts, tested by Switch.test.tsx
|
|
10
10
|
*
|
|
@@ -39,11 +39,13 @@ import {FieldStatus} from '../FieldStatus/FieldStatus';
|
|
|
39
39
|
import type {IconType} from '../Icon';
|
|
40
40
|
import type {InputStatus} from '../Field/types';
|
|
41
41
|
import {Spinner} from '../Spinner';
|
|
42
|
-
import {
|
|
42
|
+
import {useTooltip} from '../Tooltip';
|
|
43
|
+
import {mergeProps, mergeRefs} from '../utils';
|
|
43
44
|
import {switchScope} from './switch.markers.stylex';
|
|
44
45
|
import type {BaseProps} from '../BaseProps';
|
|
45
46
|
import type {SizeValue} from '../utils/types';
|
|
46
47
|
import {themeProps} from '../utils/themeProps';
|
|
48
|
+
import {VisuallyHidden} from '../VisuallyHidden';
|
|
47
49
|
|
|
48
50
|
// Fixed dimensions: 40px width, 24px height, 16px thumb (off), 20px thumb (on)
|
|
49
51
|
const SWITCH_WIDTH = 40;
|
|
@@ -179,17 +181,6 @@ const styles = stylex.create({
|
|
|
179
181
|
fontSize: typeScaleVars['--text-supporting-size'],
|
|
180
182
|
color: colorVars['--color-text-secondary'],
|
|
181
183
|
},
|
|
182
|
-
srOnly: {
|
|
183
|
-
position: 'absolute',
|
|
184
|
-
width: 1,
|
|
185
|
-
height: 1,
|
|
186
|
-
padding: 0,
|
|
187
|
-
margin: -1,
|
|
188
|
-
overflow: 'hidden',
|
|
189
|
-
clip: 'rect(0, 0, 0, 0)',
|
|
190
|
-
whiteSpace: 'nowrap',
|
|
191
|
-
borderWidth: 0,
|
|
192
|
-
},
|
|
193
184
|
});
|
|
194
185
|
|
|
195
186
|
export type SwitchLabelPosition = 'start' | 'end';
|
|
@@ -237,6 +228,27 @@ export interface SwitchProps extends Omit<BaseProps, 'onChange'> {
|
|
|
237
228
|
* @default false
|
|
238
229
|
*/
|
|
239
230
|
isDisabled?: boolean;
|
|
231
|
+
/**
|
|
232
|
+
* Explains why the switch is disabled. When set together with `isDisabled`,
|
|
233
|
+
* the switch shows a tooltip with this text on hover and keyboard focus, and
|
|
234
|
+
* the control stays focusable (via `aria-disabled`) so the reason is
|
|
235
|
+
* discoverable by keyboard and assistive technology. Activation stays
|
|
236
|
+
* blocked.
|
|
237
|
+
*
|
|
238
|
+
* Use this instead of wrapping a disabled switch in `Tooltip` — disabled
|
|
239
|
+
* controls don't emit the pointer events an external tooltip needs.
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* ```
|
|
243
|
+
* <Switch
|
|
244
|
+
* label="Enable notifications"
|
|
245
|
+
* value={enabled}
|
|
246
|
+
* isDisabled
|
|
247
|
+
* disabledMessage="Notifications are turned off org-wide"
|
|
248
|
+
* />
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
251
|
+
disabledMessage?: string;
|
|
240
252
|
/**
|
|
241
253
|
* Whether the field is optional. Mutually exclusive with isRequired.
|
|
242
254
|
* @default false
|
|
@@ -322,6 +334,7 @@ export function Switch({
|
|
|
322
334
|
isLoading = false,
|
|
323
335
|
value,
|
|
324
336
|
isDisabled = false,
|
|
337
|
+
disabledMessage,
|
|
325
338
|
isOptional = false,
|
|
326
339
|
isRequired = false,
|
|
327
340
|
onFocus,
|
|
@@ -347,6 +360,19 @@ export function Switch({
|
|
|
347
360
|
|
|
348
361
|
const isOn = optimisticValue === true;
|
|
349
362
|
|
|
363
|
+
// Disabled-reason tooltip. Disabled controls swallow pointer events, so the
|
|
364
|
+
// tooltip listeners attach to the switch row (which already exists) and the
|
|
365
|
+
// native checkbox stays perceivable via aria-disabled instead of the disabled
|
|
366
|
+
// attribute. Toggling is blocked by the isDisabled guard in onChange.
|
|
367
|
+
const showsDisabledMessage = isDisabled && !!disabledMessage;
|
|
368
|
+
const disabledMessageTooltip = useTooltip({
|
|
369
|
+
placement: 'above',
|
|
370
|
+
// The container row is not naturally focusable; focusin bubbles up from the
|
|
371
|
+
// native input, so always attach focus listeners.
|
|
372
|
+
focusTrigger: 'always',
|
|
373
|
+
isEnabled: showsDisabledMessage,
|
|
374
|
+
});
|
|
375
|
+
|
|
350
376
|
// Build aria-describedby from description and status message
|
|
351
377
|
// Only include descriptionID when the element actually renders
|
|
352
378
|
const describedByParts: string[] = [];
|
|
@@ -356,21 +382,28 @@ export function Switch({
|
|
|
356
382
|
if (status?.message) {
|
|
357
383
|
describedByParts.push(statusMessageID);
|
|
358
384
|
}
|
|
385
|
+
if (showsDisabledMessage) {
|
|
386
|
+
describedByParts.push(disabledMessageTooltip.describedBy);
|
|
387
|
+
}
|
|
359
388
|
const ariaDescribedBy =
|
|
360
389
|
describedByParts.length > 0 ? describedByParts.join(' ') : undefined;
|
|
361
390
|
|
|
362
391
|
const switchElement = (
|
|
363
392
|
<div {...stylex.props(styles.switchWrapper)}>
|
|
364
393
|
<input
|
|
365
|
-
ref={ref}
|
|
394
|
+
ref={mergeRefs(ref, disabledMessageTooltip.positionRef)}
|
|
366
395
|
id={id}
|
|
367
396
|
type="checkbox"
|
|
368
397
|
role="switch"
|
|
369
398
|
checked={isOn}
|
|
370
|
-
disabled
|
|
399
|
+
// With a disabledMessage the switch keeps focusability via aria-disabled
|
|
400
|
+
// so the reason is focus-discoverable; toggling is still blocked by the
|
|
401
|
+
// isDisabled guard in onChange below.
|
|
402
|
+
disabled={isDisabled && !showsDisabledMessage}
|
|
403
|
+
aria-disabled={showsDisabledMessage ? 'true' : undefined}
|
|
371
404
|
required={isRequired}
|
|
372
405
|
onChange={e => {
|
|
373
|
-
if (isBusy) {
|
|
406
|
+
if (isDisabled || isBusy) {
|
|
374
407
|
return;
|
|
375
408
|
}
|
|
376
409
|
const checked = e.target.checked;
|
|
@@ -416,11 +449,7 @@ export function Switch({
|
|
|
416
449
|
{isBusy && <Spinner size="sm" />}
|
|
417
450
|
</div>
|
|
418
451
|
</div>
|
|
419
|
-
{isBusy &&
|
|
420
|
-
<span {...stylex.props(styles.srOnly)} role="status">
|
|
421
|
-
Loading
|
|
422
|
-
</span>
|
|
423
|
-
)}
|
|
452
|
+
{isBusy && <VisuallyHidden role="status">Loading</VisuallyHidden>}
|
|
424
453
|
</div>
|
|
425
454
|
);
|
|
426
455
|
|
|
@@ -453,6 +482,15 @@ export function Switch({
|
|
|
453
482
|
style,
|
|
454
483
|
)}>
|
|
455
484
|
<div
|
|
485
|
+
ref={el => {
|
|
486
|
+
// Interaction (hover/focus) listeners for the disabled-message
|
|
487
|
+
// tooltip attach to the whole row for a larger trigger target;
|
|
488
|
+
// positioning anchors on the switch itself (above) so the tooltip
|
|
489
|
+
// appears next to the control, not the far edge of the row.
|
|
490
|
+
// Handlers are gated internally by isEnabled, so attaching
|
|
491
|
+
// unconditionally is safe.
|
|
492
|
+
disabledMessageTooltip.interactionRef(el);
|
|
493
|
+
}}
|
|
456
494
|
{...stylex.props(
|
|
457
495
|
styles.container,
|
|
458
496
|
labelSpacing === 'spread' && styles.containerSpread,
|
|
@@ -481,6 +519,8 @@ export function Switch({
|
|
|
481
519
|
/>
|
|
482
520
|
</div>
|
|
483
521
|
)}
|
|
522
|
+
{showsDisabledMessage &&
|
|
523
|
+
disabledMessageTooltip.renderTooltip(disabledMessage)}
|
|
484
524
|
</div>
|
|
485
525
|
);
|
|
486
526
|
}
|
package/src/TabList/Tab.tsx
CHANGED
|
@@ -259,7 +259,13 @@ export function Tab({
|
|
|
259
259
|
...restProps,
|
|
260
260
|
...(isLabelHidden ? {'aria-label': label} : {}),
|
|
261
261
|
[EDGE_COMP_ATTR]: '',
|
|
262
|
+
'data-tab-value': value,
|
|
262
263
|
'aria-current': isSelected ? ('page' as const) : undefined,
|
|
264
|
+
// Roving tabindex: the tab strip is a single Tab stop. The selected tab is
|
|
265
|
+
// the tabbable one; the rest are reachable via arrow keys (handled by
|
|
266
|
+
// TabList's onKeyDown). When no tab is selected, TabList's repair effect
|
|
267
|
+
// makes the first stop tabbable.
|
|
268
|
+
tabIndex: isSelected ? 0 : -1,
|
|
263
269
|
...mergeProps(
|
|
264
270
|
themeProps('tab', {
|
|
265
271
|
selected: isSelected ? 'selected' : null,
|
|
@@ -55,6 +55,12 @@ export const docs = {
|
|
|
55
55
|
description: 'Whether to show a bottom border divider under the tab list.',
|
|
56
56
|
default: 'false',
|
|
57
57
|
},
|
|
58
|
+
{
|
|
59
|
+
name: 'orientation',
|
|
60
|
+
type: "'horizontal' | 'vertical'",
|
|
61
|
+
description: "Orientation of the tab strip, controlling which arrow keys move focus between tabs and the reported aria-orientation. 'horizontal': ArrowLeft/ArrowRight. 'vertical': ArrowUp/ArrowDown. Both axes' arrows are accepted regardless.",
|
|
62
|
+
default: "'horizontal'",
|
|
63
|
+
},
|
|
58
64
|
{
|
|
59
65
|
name: 'children',
|
|
60
66
|
type: 'ReactNode',
|
|
@@ -75,6 +75,49 @@ describe('TabList', () => {
|
|
|
75
75
|
expect(screen.getByRole('button', {name: 'Settings'})).toBeInTheDocument();
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
+
it('does not set aria-orientation on the nav (invalid for role navigation)', () => {
|
|
79
|
+
// Regression: aria-orientation is not an allowed attribute on the
|
|
80
|
+
// navigation role and produces an axe aria-allowed-attr violation. The
|
|
81
|
+
// `orientation` prop must drive keyboard/hint behavior without emitting
|
|
82
|
+
// this attribute, regardless of the value passed.
|
|
83
|
+
const {rerender} = render(
|
|
84
|
+
<TabList value="home" onChange={() => {}}>
|
|
85
|
+
<Tab value="home" label="Home" />
|
|
86
|
+
<Tab value="settings" label="Settings" />
|
|
87
|
+
</TabList>,
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
expect(screen.getByRole('navigation')).not.toHaveAttribute(
|
|
91
|
+
'aria-orientation',
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
rerender(
|
|
95
|
+
<TabList value="home" onChange={() => {}} orientation="vertical">
|
|
96
|
+
<Tab value="home" label="Home" />
|
|
97
|
+
<Tab value="settings" label="Settings" />
|
|
98
|
+
</TabList>,
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
expect(screen.getByRole('navigation')).not.toHaveAttribute(
|
|
102
|
+
'aria-orientation',
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('ignores a consumer-supplied aria-orientation on the nav', () => {
|
|
107
|
+
// A caller passing aria-orientation should not reintroduce the invalid
|
|
108
|
+
// attribute onto the nav.
|
|
109
|
+
render(
|
|
110
|
+
<TabList value="home" onChange={() => {}} aria-orientation="vertical">
|
|
111
|
+
<Tab value="home" label="Home" />
|
|
112
|
+
<Tab value="settings" label="Settings" />
|
|
113
|
+
</TabList>,
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
expect(screen.getByRole('navigation')).not.toHaveAttribute(
|
|
117
|
+
'aria-orientation',
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
|
|
78
121
|
it('marks selected tab with aria-current', () => {
|
|
79
122
|
render(
|
|
80
123
|
<TabList value="home" onChange={() => {}}>
|
|
@@ -280,6 +323,214 @@ describe('TabList', () => {
|
|
|
280
323
|
});
|
|
281
324
|
});
|
|
282
325
|
|
|
326
|
+
describe('TabList keyboard navigation (roving tabindex)', () => {
|
|
327
|
+
it('exposes the tab strip as a single Tab stop (only selected tab is tabbable)', () => {
|
|
328
|
+
render(
|
|
329
|
+
<TabList value="settings" onChange={() => {}}>
|
|
330
|
+
<Tab value="home" label="Home" />
|
|
331
|
+
<Tab value="settings" label="Settings" />
|
|
332
|
+
<Tab value="profile" label="Profile" />
|
|
333
|
+
</TabList>,
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
expect(screen.getByRole('button', {name: 'Home'})).toHaveAttribute(
|
|
337
|
+
'tabindex',
|
|
338
|
+
'-1',
|
|
339
|
+
);
|
|
340
|
+
expect(screen.getByRole('button', {name: 'Settings'})).toHaveAttribute(
|
|
341
|
+
'tabindex',
|
|
342
|
+
'0',
|
|
343
|
+
);
|
|
344
|
+
expect(screen.getByRole('button', {name: 'Profile'})).toHaveAttribute(
|
|
345
|
+
'tabindex',
|
|
346
|
+
'-1',
|
|
347
|
+
);
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
it('makes the first tab tabbable when the selected value matches no tab', () => {
|
|
351
|
+
render(
|
|
352
|
+
<TabList value="__none__" onChange={() => {}}>
|
|
353
|
+
<Tab value="home" label="Home" />
|
|
354
|
+
<Tab value="settings" label="Settings" />
|
|
355
|
+
</TabList>,
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
expect(screen.getByRole('button', {name: 'Home'})).toHaveAttribute(
|
|
359
|
+
'tabindex',
|
|
360
|
+
'0',
|
|
361
|
+
);
|
|
362
|
+
expect(screen.getByRole('button', {name: 'Settings'})).toHaveAttribute(
|
|
363
|
+
'tabindex',
|
|
364
|
+
'-1',
|
|
365
|
+
);
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
it('moves focus with ArrowRight and ArrowLeft', async () => {
|
|
369
|
+
const user = userEvent.setup();
|
|
370
|
+
render(
|
|
371
|
+
<TabList value="home" onChange={() => {}}>
|
|
372
|
+
<Tab value="home" label="Home" />
|
|
373
|
+
<Tab value="settings" label="Settings" />
|
|
374
|
+
<Tab value="profile" label="Profile" />
|
|
375
|
+
</TabList>,
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
const home = screen.getByRole('button', {name: 'Home'});
|
|
379
|
+
const settings = screen.getByRole('button', {name: 'Settings'});
|
|
380
|
+
const profile = screen.getByRole('button', {name: 'Profile'});
|
|
381
|
+
|
|
382
|
+
home.focus();
|
|
383
|
+
expect(home).toHaveFocus();
|
|
384
|
+
|
|
385
|
+
await user.keyboard('{ArrowRight}');
|
|
386
|
+
expect(settings).toHaveFocus();
|
|
387
|
+
|
|
388
|
+
await user.keyboard('{ArrowRight}');
|
|
389
|
+
expect(profile).toHaveFocus();
|
|
390
|
+
|
|
391
|
+
await user.keyboard('{ArrowLeft}');
|
|
392
|
+
expect(settings).toHaveFocus();
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
it('supports ArrowDown and ArrowUp as forward/backward as well', async () => {
|
|
396
|
+
const user = userEvent.setup();
|
|
397
|
+
render(
|
|
398
|
+
<TabList value="home" onChange={() => {}}>
|
|
399
|
+
<Tab value="home" label="Home" />
|
|
400
|
+
<Tab value="settings" label="Settings" />
|
|
401
|
+
</TabList>,
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
const home = screen.getByRole('button', {name: 'Home'});
|
|
405
|
+
const settings = screen.getByRole('button', {name: 'Settings'});
|
|
406
|
+
|
|
407
|
+
home.focus();
|
|
408
|
+
await user.keyboard('{ArrowDown}');
|
|
409
|
+
expect(settings).toHaveFocus();
|
|
410
|
+
|
|
411
|
+
await user.keyboard('{ArrowUp}');
|
|
412
|
+
expect(home).toHaveFocus();
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it('jumps to first and last tab with Home and End', async () => {
|
|
416
|
+
const user = userEvent.setup();
|
|
417
|
+
render(
|
|
418
|
+
<TabList value="settings" onChange={() => {}}>
|
|
419
|
+
<Tab value="home" label="Home" />
|
|
420
|
+
<Tab value="settings" label="Settings" />
|
|
421
|
+
<Tab value="profile" label="Profile" />
|
|
422
|
+
</TabList>,
|
|
423
|
+
);
|
|
424
|
+
|
|
425
|
+
const home = screen.getByRole('button', {name: 'Home'});
|
|
426
|
+
const settings = screen.getByRole('button', {name: 'Settings'});
|
|
427
|
+
const profile = screen.getByRole('button', {name: 'Profile'});
|
|
428
|
+
|
|
429
|
+
settings.focus();
|
|
430
|
+
|
|
431
|
+
await user.keyboard('{End}');
|
|
432
|
+
expect(profile).toHaveFocus();
|
|
433
|
+
|
|
434
|
+
await user.keyboard('{Home}');
|
|
435
|
+
expect(home).toHaveFocus();
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
it('wraps around at the ends', async () => {
|
|
439
|
+
const user = userEvent.setup();
|
|
440
|
+
render(
|
|
441
|
+
<TabList value="home" onChange={() => {}}>
|
|
442
|
+
<Tab value="home" label="Home" />
|
|
443
|
+
<Tab value="settings" label="Settings" />
|
|
444
|
+
<Tab value="profile" label="Profile" />
|
|
445
|
+
</TabList>,
|
|
446
|
+
);
|
|
447
|
+
|
|
448
|
+
const home = screen.getByRole('button', {name: 'Home'});
|
|
449
|
+
const profile = screen.getByRole('button', {name: 'Profile'});
|
|
450
|
+
|
|
451
|
+
home.focus();
|
|
452
|
+
await user.keyboard('{ArrowLeft}');
|
|
453
|
+
expect(profile).toHaveFocus();
|
|
454
|
+
|
|
455
|
+
await user.keyboard('{ArrowRight}');
|
|
456
|
+
expect(home).toHaveFocus();
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
it('skips disabled tabs during arrow navigation', async () => {
|
|
460
|
+
const user = userEvent.setup();
|
|
461
|
+
render(
|
|
462
|
+
<TabList value="home" onChange={() => {}}>
|
|
463
|
+
<Tab value="home" label="Home" />
|
|
464
|
+
<Tab value="settings" label="Settings" aria-disabled="true" />
|
|
465
|
+
<Tab value="profile" label="Profile" />
|
|
466
|
+
</TabList>,
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
const home = screen.getByRole('button', {name: 'Home'});
|
|
470
|
+
const profile = screen.getByRole('button', {name: 'Profile'});
|
|
471
|
+
|
|
472
|
+
home.focus();
|
|
473
|
+
await user.keyboard('{ArrowRight}');
|
|
474
|
+
expect(profile).toHaveFocus();
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
it('does not intercept unrelated keys', async () => {
|
|
478
|
+
const user = userEvent.setup();
|
|
479
|
+
render(
|
|
480
|
+
<TabList value="home" onChange={() => {}}>
|
|
481
|
+
<Tab value="home" label="Home" />
|
|
482
|
+
<Tab value="settings" label="Settings" />
|
|
483
|
+
</TabList>,
|
|
484
|
+
);
|
|
485
|
+
|
|
486
|
+
const home = screen.getByRole('button', {name: 'Home'});
|
|
487
|
+
home.focus();
|
|
488
|
+
await user.keyboard('a');
|
|
489
|
+
expect(home).toHaveFocus();
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
it('composes consumer onKeyDown with internal arrow navigation', async () => {
|
|
493
|
+
const user = userEvent.setup();
|
|
494
|
+
const onKeyDown = vi.fn();
|
|
495
|
+
|
|
496
|
+
render(
|
|
497
|
+
<TabList value="home" onChange={() => {}} onKeyDown={onKeyDown}>
|
|
498
|
+
<Tab value="home" label="Home" />
|
|
499
|
+
<Tab value="settings" label="Settings" />
|
|
500
|
+
</TabList>,
|
|
501
|
+
);
|
|
502
|
+
|
|
503
|
+
const home = screen.getByRole('button', {name: 'Home'});
|
|
504
|
+
const settings = screen.getByRole('button', {name: 'Settings'});
|
|
505
|
+
|
|
506
|
+
home.focus();
|
|
507
|
+
await user.keyboard('{ArrowRight}');
|
|
508
|
+
|
|
509
|
+
expect(onKeyDown).toHaveBeenCalled();
|
|
510
|
+
expect(settings).toHaveFocus();
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
it('respects preventDefault from consumer onKeyDown', async () => {
|
|
514
|
+
const user = userEvent.setup();
|
|
515
|
+
|
|
516
|
+
render(
|
|
517
|
+
<TabList
|
|
518
|
+
value="home"
|
|
519
|
+
onChange={() => {}}
|
|
520
|
+
onKeyDown={e => e.preventDefault()}>
|
|
521
|
+
<Tab value="home" label="Home" />
|
|
522
|
+
<Tab value="settings" label="Settings" />
|
|
523
|
+
</TabList>,
|
|
524
|
+
);
|
|
525
|
+
|
|
526
|
+
const home = screen.getByRole('button', {name: 'Home'});
|
|
527
|
+
home.focus();
|
|
528
|
+
await user.keyboard('{ArrowRight}');
|
|
529
|
+
|
|
530
|
+
expect(home).toHaveFocus();
|
|
531
|
+
});
|
|
532
|
+
});
|
|
533
|
+
|
|
283
534
|
describe('Tab polymorphic link', () => {
|
|
284
535
|
it('renders custom component when href and as are provided', () => {
|
|
285
536
|
render(
|
package/src/TabList/TabList.tsx
CHANGED
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file TabList.tsx
|
|
7
|
-
* @input Uses React, StyleX, TabListContext
|
|
7
|
+
* @input Uses React, StyleX, TabListContext, useListFocus, useKeyboardHint
|
|
8
8
|
* @output Exports TabList component and TabListProps type
|
|
9
|
-
* @position Nav wrapper; provides TabListContext to Tab and TabMenu children
|
|
9
|
+
* @position Nav wrapper; provides TabListContext to Tab and TabMenu children.
|
|
10
|
+
* Owns roving-tabindex keyboard navigation (Arrow/Home/End) across the tab
|
|
11
|
+
* strip via the shared useListFocus hook so it is a single Tab stop.
|
|
10
12
|
*
|
|
11
13
|
* SYNC: When modified, update:
|
|
12
14
|
* - /packages/core/src/TabList/TabList.doc.mjs
|
|
@@ -15,21 +17,27 @@
|
|
|
15
17
|
* - /packages/cli/templates/blocks/components/TabList/ (showcase blocks)
|
|
16
18
|
*/
|
|
17
19
|
|
|
18
|
-
import React, {useMemo, type ReactNode} from 'react';
|
|
20
|
+
import React, {useCallback, useMemo, type ReactNode} from 'react';
|
|
19
21
|
import * as stylex from '@stylexjs/stylex';
|
|
20
22
|
import {borderVars, colorVars, spacingVars} from '../theme/tokens.stylex';
|
|
21
23
|
import type {BaseProps} from '../BaseProps';
|
|
22
24
|
import {TabListContext} from './TabListContext';
|
|
23
|
-
import type {TabListSize} from './TabListContext';
|
|
25
|
+
import type {TabListOrientation, TabListSize} from './TabListContext';
|
|
24
26
|
import {useSize} from '../SizeContext/SizeContext';
|
|
25
|
-
import {mergeProps} from '../utils';
|
|
27
|
+
import {mergeProps, mergeRefs} from '../utils';
|
|
28
|
+
import {useListFocus} from '../hooks/useListFocus';
|
|
29
|
+
import {useKeyboardHint} from '../hooks/useKeyboardHint';
|
|
26
30
|
import {EDGE_COMP_ATTR} from '../Layout/edgeCompensation.stylex';
|
|
27
31
|
import {themeProps} from '../utils/themeProps';
|
|
28
32
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Selector matching the focusable stops in the tab strip: every Tab
|
|
35
|
+
* (`[data-tab-value]`) and every TabMenu trigger (`[data-tab-menu]`),
|
|
36
|
+
* in DOM order. Disabled stops are filtered out by the handler.
|
|
37
|
+
*/
|
|
38
|
+
const TAB_STOP_SELECTOR = '[data-tab-value],[data-tab-menu]';
|
|
39
|
+
|
|
40
|
+
export interface TabListProps extends Omit<BaseProps<HTMLElement>, 'onChange'> {
|
|
33
41
|
ref?: React.Ref<HTMLElement>;
|
|
34
42
|
/**
|
|
35
43
|
* The currently selected tab value.
|
|
@@ -57,6 +65,15 @@ export interface TabListProps extends Omit<
|
|
|
57
65
|
* @default false
|
|
58
66
|
*/
|
|
59
67
|
hasDivider?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Orientation of the tab strip, controlling which arrow keys move
|
|
70
|
+
* focus between tabs.
|
|
71
|
+
* - `'horizontal'` (default): ArrowLeft / ArrowRight (ArrowUp / ArrowDown
|
|
72
|
+
* also work per the WAI-ARIA APG).
|
|
73
|
+
* - `'vertical'`: ArrowUp / ArrowDown (ArrowLeft / ArrowRight also work).
|
|
74
|
+
* @default 'horizontal'
|
|
75
|
+
*/
|
|
76
|
+
orientation?: TabListOrientation;
|
|
60
77
|
/**
|
|
61
78
|
* Tab and TabMenu children.
|
|
62
79
|
*/
|
|
@@ -104,26 +121,99 @@ export function TabList({
|
|
|
104
121
|
size: sizeProp,
|
|
105
122
|
layout = 'hug',
|
|
106
123
|
hasDivider = false,
|
|
124
|
+
orientation = 'horizontal',
|
|
107
125
|
xstyle,
|
|
108
126
|
className,
|
|
109
127
|
style,
|
|
110
128
|
children,
|
|
129
|
+
onKeyDown: onKeyDownProp,
|
|
130
|
+
onFocus: onFocusProp,
|
|
131
|
+
onBlur: onBlurProp,
|
|
132
|
+
'aria-label': ariaLabel = 'Tabs',
|
|
133
|
+
'aria-orientation': _ariaOrientation,
|
|
134
|
+
[EDGE_COMP_ATTR]: _edgeCompAttr,
|
|
111
135
|
...restProps
|
|
112
136
|
}: TabListProps) {
|
|
113
137
|
const size = useSize(sizeProp, 'md');
|
|
114
138
|
|
|
139
|
+
// Roving-tabindex keyboard navigation across the tab strip via the shared
|
|
140
|
+
// hook. `orientation: 'both'` accepts both arrow axes per the WAI-ARIA APG
|
|
141
|
+
// allowance for tab strips (ArrowRight/ArrowDown advance, ArrowLeft/ArrowUp
|
|
142
|
+
// retreat) regardless of the component's `orientation` prop, which only
|
|
143
|
+
// drives the keyboard hint badge (see useKeyboardHint below). We do not set
|
|
144
|
+
// `aria-orientation` on the `<nav>`: that attribute is invalid on the
|
|
145
|
+
// navigation role and triggers an axe `aria-allowed-attr` violation.
|
|
146
|
+
//
|
|
147
|
+
// `hasRovingTabIndex` makes the hook own the single tab stop: it stamps
|
|
148
|
+
// tabindex 0/-1, repairs the stop on mount and as stops mount/unmount or
|
|
149
|
+
// toggle disabled, and — via `handleFocus` on the nav — keeps the stop in
|
|
150
|
+
// sync after clicks or programmatic focus. Individual Tabs still render
|
|
151
|
+
// `tabIndex={isSelected ? 0 : -1}` (see Tab.tsx) as the initial source of
|
|
152
|
+
// truth; the hook's repair preserves an existing tab stop and only promotes
|
|
153
|
+
// the first enabled stop when none is tabbable.
|
|
154
|
+
const {listRef, handleKeyDown, handleFocus} = useListFocus<HTMLElement>({
|
|
155
|
+
itemSelector: TAB_STOP_SELECTOR,
|
|
156
|
+
orientation: 'both',
|
|
157
|
+
hasRovingTabIndex: true,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const {
|
|
161
|
+
hintElement,
|
|
162
|
+
onKeyDown: onHintKeyDown,
|
|
163
|
+
onFocus: onHintFocus,
|
|
164
|
+
onBlur: onHintBlur,
|
|
165
|
+
} = useKeyboardHint({orientation});
|
|
166
|
+
|
|
115
167
|
const contextValue = useMemo(
|
|
116
168
|
() => ({value, onChange, size, layout}),
|
|
117
169
|
[value, onChange, size, layout],
|
|
118
170
|
);
|
|
119
171
|
|
|
172
|
+
const handleRootKeyDown = useCallback(
|
|
173
|
+
(e: React.KeyboardEvent<HTMLElement>) => {
|
|
174
|
+
onKeyDownProp?.(e);
|
|
175
|
+
if (e.defaultPrevented) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
onHintKeyDown(e);
|
|
179
|
+
handleKeyDown(e);
|
|
180
|
+
},
|
|
181
|
+
[onKeyDownProp, onHintKeyDown, handleKeyDown],
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
const handleRootFocus = useCallback(
|
|
185
|
+
(e: React.FocusEvent<HTMLElement>) => {
|
|
186
|
+
onFocusProp?.(e);
|
|
187
|
+
if (e.defaultPrevented) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
onHintFocus(e);
|
|
191
|
+
handleFocus(e);
|
|
192
|
+
},
|
|
193
|
+
[onFocusProp, onHintFocus, handleFocus],
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
const handleRootBlur = useCallback(
|
|
197
|
+
(e: React.FocusEvent<HTMLElement>) => {
|
|
198
|
+
onBlurProp?.(e);
|
|
199
|
+
if (e.defaultPrevented) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
onHintBlur(e);
|
|
203
|
+
},
|
|
204
|
+
[onBlurProp, onHintBlur],
|
|
205
|
+
);
|
|
206
|
+
|
|
120
207
|
return (
|
|
121
208
|
<TabListContext value={contextValue}>
|
|
122
209
|
<nav
|
|
123
|
-
ref={ref}
|
|
124
|
-
aria-label="Tabs"
|
|
125
|
-
{...{[EDGE_COMP_ATTR]: ''}}
|
|
210
|
+
ref={mergeRefs(ref, listRef)}
|
|
126
211
|
{...restProps}
|
|
212
|
+
aria-label={ariaLabel}
|
|
213
|
+
onKeyDown={handleRootKeyDown}
|
|
214
|
+
onFocus={handleRootFocus}
|
|
215
|
+
onBlur={handleRootBlur}
|
|
216
|
+
{...{[EDGE_COMP_ATTR]: ''}}
|
|
127
217
|
{...mergeProps(
|
|
128
218
|
themeProps('tab-list', {size}),
|
|
129
219
|
stylex.props(
|
|
@@ -136,6 +226,7 @@ export function TabList({
|
|
|
136
226
|
style,
|
|
137
227
|
)}>
|
|
138
228
|
{children}
|
|
229
|
+
{hintElement}
|
|
139
230
|
</nav>
|
|
140
231
|
</TabListContext>
|
|
141
232
|
);
|
|
@@ -26,6 +26,12 @@ export type TabListSize = 'sm' | 'md' | 'lg';
|
|
|
26
26
|
*/
|
|
27
27
|
export type TabListLayout = 'hug' | 'fill';
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Orientation of the tab strip. Controls which arrow keys move focus
|
|
31
|
+
* between tabs and the reported `aria-orientation`.
|
|
32
|
+
*/
|
|
33
|
+
export type TabListOrientation = 'horizontal' | 'vertical';
|
|
34
|
+
|
|
29
35
|
/**
|
|
30
36
|
* Context for communicating value/onChange/size/layout from TabList to children.
|
|
31
37
|
*/
|
|
@@ -36,9 +42,7 @@ export interface TabListContextValue {
|
|
|
36
42
|
layout: TabListLayout;
|
|
37
43
|
}
|
|
38
44
|
|
|
39
|
-
export const TabListContext = createContext<TabListContextValue | null>(
|
|
40
|
-
null,
|
|
41
|
-
);
|
|
45
|
+
export const TabListContext = createContext<TabListContextValue | null>(null);
|
|
42
46
|
TabListContext.displayName = 'TabListContext';
|
|
43
47
|
|
|
44
48
|
/**
|
package/src/TabList/TabMenu.tsx
CHANGED
|
@@ -267,6 +267,9 @@ export function TabMenu({
|
|
|
267
267
|
hasLightDismiss: true,
|
|
268
268
|
hasCloseButton: false,
|
|
269
269
|
hasAutoFocus: false,
|
|
270
|
+
// The popup's own role="menu" is the exposed semantics; a modal dialog
|
|
271
|
+
// wrapper would announce an unnamed dialog around the menu.
|
|
272
|
+
role: 'none',
|
|
270
273
|
});
|
|
271
274
|
|
|
272
275
|
const {listRef, handleKeyDown: handleListKeyDown} =
|
|
@@ -306,6 +309,8 @@ export function TabMenu({
|
|
|
306
309
|
aria-haspopup="menu"
|
|
307
310
|
aria-expanded={popover.isOpen}
|
|
308
311
|
aria-controls={menuId}
|
|
312
|
+
data-tab-menu=""
|
|
313
|
+
tabIndex={hasSelectedOption ? 0 : -1}
|
|
309
314
|
onClick={handleToggle}
|
|
310
315
|
{...mergeProps(
|
|
311
316
|
themeProps('tab-menu'),
|
|
@@ -390,9 +395,7 @@ export function TabMenu({
|
|
|
390
395
|
})}
|
|
391
396
|
{option.label}
|
|
392
397
|
</span>
|
|
393
|
-
{isSelected &&
|
|
394
|
-
<Icon icon="check" size="sm" color="accent" />
|
|
395
|
-
)}
|
|
398
|
+
{isSelected && <Icon icon="check" size="sm" color="accent" />}
|
|
396
399
|
</div>
|
|
397
400
|
);
|
|
398
401
|
})}
|