@astryxdesign/core 0.1.2 → 0.1.3
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
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @file InputGroup.test.tsx
|
|
5
|
-
* @input Uses vitest, @testing-library/react, InputGroup
|
|
5
|
+
* @input Uses vitest, @testing-library/react, InputGroup, TextInput, NumberInput, DateInput components
|
|
6
6
|
* @output Unit tests for InputGroup
|
|
7
7
|
* @position Testing; validates InputGroup component implementation
|
|
8
8
|
*
|
|
@@ -14,38 +14,275 @@ import {render, screen} from '@testing-library/react';
|
|
|
14
14
|
import {InputGroup} from './InputGroup';
|
|
15
15
|
import {InputGroupText} from './InputGroupText';
|
|
16
16
|
import {TextInput} from '../TextInput';
|
|
17
|
+
import {NumberInput} from '../NumberInput';
|
|
18
|
+
import {DateInput} from '../DateInput';
|
|
19
|
+
import {Typeahead} from '../Typeahead';
|
|
20
|
+
import type {SearchableItem, SearchSource} from '../Typeahead';
|
|
21
|
+
import {Selector} from '../Selector';
|
|
22
|
+
import {MultiSelector} from '../MultiSelector';
|
|
23
|
+
|
|
24
|
+
const fruits: SearchableItem[] = [
|
|
25
|
+
{id: '1', label: 'Apple'},
|
|
26
|
+
{id: '2', label: 'Banana'},
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const fruitSource: SearchSource = {
|
|
30
|
+
search: (query: string) =>
|
|
31
|
+
fruits.filter(f => f.label.toLowerCase().includes(query.toLowerCase())),
|
|
32
|
+
bootstrap: () => fruits,
|
|
33
|
+
};
|
|
17
34
|
|
|
18
35
|
describe('InputGroup', () => {
|
|
19
|
-
it('
|
|
36
|
+
it('names the group via the label element (forms-14)', () => {
|
|
20
37
|
render(
|
|
21
38
|
<InputGroup label="Price">
|
|
22
39
|
<InputGroupText>$</InputGroupText>
|
|
23
|
-
<TextInput
|
|
24
|
-
|
|
40
|
+
<TextInput label="Amount" isLabelHidden value="" onChange={() => {}} />
|
|
41
|
+
</InputGroup>,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
// The group is named by the field label via aria-labelledby (not a
|
|
45
|
+
// duplicated aria-label). The label is rendered as a <span> (not a literal
|
|
46
|
+
// <label>, which can't name a group) and carries no orphaned htmlFor.
|
|
47
|
+
const group = screen.getByRole('group', {name: 'Price'});
|
|
48
|
+
expect(group).toBeInTheDocument();
|
|
49
|
+
expect(group).not.toHaveAttribute('aria-label');
|
|
50
|
+
const label = screen.getByText('Price');
|
|
51
|
+
expect(label.tagName).toBe('SPAN');
|
|
52
|
+
expect(label.closest('label')).toBeNull();
|
|
53
|
+
expect(label).not.toHaveAttribute('for');
|
|
54
|
+
expect(group.getAttribute('aria-labelledby')).toBe(label.id);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('associates group description and status through aria-describedby', () => {
|
|
58
|
+
render(
|
|
59
|
+
<InputGroup
|
|
60
|
+
label="Price"
|
|
61
|
+
description="Enter the amount in USD"
|
|
62
|
+
status={{type: 'error', message: 'Price is required'}}>
|
|
63
|
+
<InputGroupText>$</InputGroupText>
|
|
64
|
+
<TextInput label="Amount" isLabelHidden value="" onChange={() => {}} />
|
|
65
|
+
</InputGroup>,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const group = screen.getByRole('group', {name: 'Price'});
|
|
69
|
+
const describedBy = group.getAttribute('aria-describedby');
|
|
70
|
+
expect(describedBy).toBeTruthy();
|
|
71
|
+
expect(describedBy!.split(' ')).toHaveLength(2);
|
|
72
|
+
expect(describedBy).toContain(
|
|
73
|
+
screen.getByText('Enter the amount in USD').id,
|
|
74
|
+
);
|
|
75
|
+
expect(describedBy).toContain(screen.getByText('Price is required').id);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('labels grouped TextInput from the group and inner input labels', () => {
|
|
79
|
+
render(
|
|
80
|
+
<InputGroup
|
|
81
|
+
label="Price"
|
|
82
|
+
description="Enter the amount in USD"
|
|
83
|
+
status={{type: 'error', message: 'Price is required'}}>
|
|
84
|
+
<InputGroupText>$</InputGroupText>
|
|
85
|
+
<TextInput label="Amount" isLabelHidden value="" onChange={() => {}} />
|
|
86
|
+
</InputGroup>,
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const group = screen.getByRole('group', {name: 'Price'});
|
|
90
|
+
const groupLabelID = group.getAttribute('aria-labelledby');
|
|
91
|
+
const describedBy = group.getAttribute('aria-describedby');
|
|
92
|
+
const input = screen.getByRole('textbox', {name: 'Price Amount'});
|
|
93
|
+
const labelledByIDs =
|
|
94
|
+
input.getAttribute('aria-labelledby')?.split(' ') ?? [];
|
|
95
|
+
|
|
96
|
+
expect(labelledByIDs).toHaveLength(2);
|
|
97
|
+
expect(labelledByIDs[0]).toBe(groupLabelID);
|
|
98
|
+
expect(document.getElementById(labelledByIDs[1])).toHaveTextContent(
|
|
99
|
+
'Amount',
|
|
100
|
+
);
|
|
101
|
+
expect(input).not.toHaveAttribute('aria-label');
|
|
102
|
+
expect(input).toHaveAttribute('aria-describedby', describedBy);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('labels grouped Typeahead from the group and inner input labels', () => {
|
|
106
|
+
const {container} = render(
|
|
107
|
+
<InputGroup label="Favorite fruit" description="Pick one fruit">
|
|
108
|
+
<InputGroupText>Fruit</InputGroupText>
|
|
109
|
+
<Typeahead
|
|
110
|
+
label="Selection"
|
|
25
111
|
isLabelHidden
|
|
26
|
-
|
|
112
|
+
searchSource={fruitSource}
|
|
113
|
+
value={null}
|
|
27
114
|
onChange={() => {}}
|
|
28
115
|
/>
|
|
29
116
|
</InputGroup>,
|
|
30
117
|
);
|
|
31
118
|
|
|
32
|
-
const group = screen.getByRole('group');
|
|
33
|
-
|
|
34
|
-
|
|
119
|
+
const group = screen.getByRole('group', {name: 'Favorite fruit'});
|
|
120
|
+
const groupLabelID = group.getAttribute('aria-labelledby');
|
|
121
|
+
const input = screen.getByRole('combobox', {
|
|
122
|
+
name: 'Favorite fruit Selection',
|
|
123
|
+
});
|
|
124
|
+
const labelledByIDs =
|
|
125
|
+
input.getAttribute('aria-labelledby')?.split(' ') ?? [];
|
|
126
|
+
|
|
127
|
+
expect(labelledByIDs).toHaveLength(2);
|
|
128
|
+
expect(labelledByIDs[0]).toBe(groupLabelID);
|
|
129
|
+
expect(document.getElementById(labelledByIDs[1])).toHaveTextContent(
|
|
130
|
+
'Selection',
|
|
131
|
+
);
|
|
132
|
+
expect(input).not.toHaveAttribute('aria-label');
|
|
133
|
+
expect(input).toHaveAttribute(
|
|
134
|
+
'aria-describedby',
|
|
135
|
+
group.getAttribute('aria-describedby'),
|
|
136
|
+
);
|
|
137
|
+
expect(container.querySelectorAll('.astryx-field')).toHaveLength(1);
|
|
35
138
|
});
|
|
36
139
|
|
|
37
|
-
it('
|
|
140
|
+
it('labels grouped NumberInput from the group and inner input labels', () => {
|
|
38
141
|
render(
|
|
39
|
-
<InputGroup label="
|
|
40
|
-
<
|
|
142
|
+
<InputGroup label="Budget" description="Whole dollars only">
|
|
143
|
+
<InputGroupText>$</InputGroupText>
|
|
144
|
+
<NumberInput
|
|
41
145
|
label="Amount"
|
|
42
146
|
isLabelHidden
|
|
43
|
-
value=
|
|
147
|
+
value={null}
|
|
44
148
|
onChange={() => {}}
|
|
45
149
|
/>
|
|
46
150
|
</InputGroup>,
|
|
47
151
|
);
|
|
48
152
|
|
|
153
|
+
const group = screen.getByRole('group', {name: 'Budget'});
|
|
154
|
+
const groupLabelID = group.getAttribute('aria-labelledby');
|
|
155
|
+
const input = screen.getByRole('spinbutton', {name: 'Budget Amount'});
|
|
156
|
+
const labelledByIDs =
|
|
157
|
+
input.getAttribute('aria-labelledby')?.split(' ') ?? [];
|
|
158
|
+
|
|
159
|
+
expect(labelledByIDs).toHaveLength(2);
|
|
160
|
+
expect(labelledByIDs[0]).toBe(groupLabelID);
|
|
161
|
+
expect(document.getElementById(labelledByIDs[1])).toHaveTextContent(
|
|
162
|
+
'Amount',
|
|
163
|
+
);
|
|
164
|
+
expect(input).not.toHaveAttribute('aria-label');
|
|
165
|
+
expect(input).toHaveAttribute(
|
|
166
|
+
'aria-describedby',
|
|
167
|
+
group.getAttribute('aria-describedby'),
|
|
168
|
+
);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('labels grouped DateInput from the group and inner input labels', () => {
|
|
172
|
+
render(
|
|
173
|
+
<InputGroup label="Deadline" description="Use business days">
|
|
174
|
+
<InputGroupText>Due</InputGroupText>
|
|
175
|
+
<DateInput label="Date" isLabelHidden onChange={() => {}} />
|
|
176
|
+
</InputGroup>,
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
const group = screen.getByRole('group', {name: 'Deadline'});
|
|
180
|
+
const groupLabelID = group.getAttribute('aria-labelledby');
|
|
181
|
+
const input = screen.getByRole('combobox', {name: 'Deadline Date'});
|
|
182
|
+
const labelledByIDs =
|
|
183
|
+
input.getAttribute('aria-labelledby')?.split(' ') ?? [];
|
|
184
|
+
|
|
185
|
+
expect(labelledByIDs).toHaveLength(2);
|
|
186
|
+
expect(labelledByIDs[0]).toBe(groupLabelID);
|
|
187
|
+
expect(document.getElementById(labelledByIDs[1])).toHaveTextContent('Date');
|
|
188
|
+
expect(input).toHaveAttribute('aria-haspopup', 'dialog');
|
|
189
|
+
expect(input).toHaveAttribute(
|
|
190
|
+
'aria-describedby',
|
|
191
|
+
group.getAttribute('aria-describedby'),
|
|
192
|
+
);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('labels grouped Selector from the group and selector labels', () => {
|
|
196
|
+
render(
|
|
197
|
+
<InputGroup label="Destination" description="Where alerts are sent">
|
|
198
|
+
<InputGroupText>#</InputGroupText>
|
|
199
|
+
<Selector
|
|
200
|
+
label="Channel"
|
|
201
|
+
isLabelHidden
|
|
202
|
+
options={['General', 'Support']}
|
|
203
|
+
placeholder="Choose channel"
|
|
204
|
+
/>
|
|
205
|
+
</InputGroup>,
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
const group = screen.getByRole('group', {name: 'Destination'});
|
|
209
|
+
const groupLabelID = group.getAttribute('aria-labelledby');
|
|
210
|
+
const trigger = screen.getByRole('combobox', {
|
|
211
|
+
name: 'Destination Channel',
|
|
212
|
+
});
|
|
213
|
+
const labelledByIDs =
|
|
214
|
+
trigger.getAttribute('aria-labelledby')?.split(' ') ?? [];
|
|
215
|
+
|
|
216
|
+
expect(labelledByIDs).toHaveLength(2);
|
|
217
|
+
expect(labelledByIDs[0]).toBe(groupLabelID);
|
|
218
|
+
expect(document.getElementById(labelledByIDs[1])).toHaveTextContent(
|
|
219
|
+
'Channel',
|
|
220
|
+
);
|
|
221
|
+
expect(trigger).not.toHaveAttribute('aria-label');
|
|
222
|
+
expect(trigger).toHaveAttribute(
|
|
223
|
+
'aria-describedby',
|
|
224
|
+
group.getAttribute('aria-describedby'),
|
|
225
|
+
);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('labels grouped MultiSelector from the group and selector labels', () => {
|
|
229
|
+
render(
|
|
230
|
+
<InputGroup label="Destinations" description="Where alerts are sent">
|
|
231
|
+
<InputGroupText>#</InputGroupText>
|
|
232
|
+
<MultiSelector
|
|
233
|
+
label="Channels"
|
|
234
|
+
isLabelHidden
|
|
235
|
+
options={['General', 'Support']}
|
|
236
|
+
value={[]}
|
|
237
|
+
onChange={() => {}}
|
|
238
|
+
placeholder="Choose channels"
|
|
239
|
+
/>
|
|
240
|
+
</InputGroup>,
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
const group = screen.getByRole('group', {name: 'Destinations'});
|
|
244
|
+
const groupLabelID = group.getAttribute('aria-labelledby');
|
|
245
|
+
const trigger = screen.getByRole('combobox', {
|
|
246
|
+
name: 'Destinations Channels',
|
|
247
|
+
});
|
|
248
|
+
const labelledByIDs =
|
|
249
|
+
trigger.getAttribute('aria-labelledby')?.split(' ') ?? [];
|
|
250
|
+
|
|
251
|
+
expect(labelledByIDs).toHaveLength(2);
|
|
252
|
+
expect(labelledByIDs[0]).toBe(groupLabelID);
|
|
253
|
+
expect(document.getElementById(labelledByIDs[1])).toHaveTextContent(
|
|
254
|
+
'Channels',
|
|
255
|
+
);
|
|
256
|
+
expect(trigger).not.toHaveAttribute('aria-label');
|
|
257
|
+
expect(trigger).toHaveAttribute(
|
|
258
|
+
'aria-describedby',
|
|
259
|
+
group.getAttribute('aria-describedby'),
|
|
260
|
+
);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('keeps grouped DateInput calendar button and popover semantics', () => {
|
|
264
|
+
render(
|
|
265
|
+
<InputGroup label="Deadline">
|
|
266
|
+
<InputGroupText>Due</InputGroupText>
|
|
267
|
+
<DateInput label="Date" isLabelHidden onChange={() => {}} />
|
|
268
|
+
</InputGroup>,
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
expect(
|
|
272
|
+
screen.getByRole('button', {name: 'Open calendar'}),
|
|
273
|
+
).toBeInTheDocument();
|
|
274
|
+
expect(
|
|
275
|
+
screen.getByRole('combobox', {name: 'Deadline Date'}),
|
|
276
|
+
).toHaveAttribute('aria-expanded', 'false');
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('renders the visible label', () => {
|
|
280
|
+
render(
|
|
281
|
+
<InputGroup label="Price">
|
|
282
|
+
<TextInput label="Amount" isLabelHidden value="" onChange={() => {}} />
|
|
283
|
+
</InputGroup>,
|
|
284
|
+
);
|
|
285
|
+
|
|
49
286
|
expect(screen.getByText('Price')).toBeInTheDocument();
|
|
50
287
|
});
|
|
51
288
|
|
|
@@ -53,12 +290,7 @@ describe('InputGroup', () => {
|
|
|
53
290
|
render(
|
|
54
291
|
<InputGroup label="Price">
|
|
55
292
|
<InputGroupText>$</InputGroupText>
|
|
56
|
-
<TextInput
|
|
57
|
-
label="Amount"
|
|
58
|
-
isLabelHidden
|
|
59
|
-
value=""
|
|
60
|
-
onChange={() => {}}
|
|
61
|
-
/>
|
|
293
|
+
<TextInput label="Amount" isLabelHidden value="" onChange={() => {}} />
|
|
62
294
|
</InputGroup>,
|
|
63
295
|
);
|
|
64
296
|
|
|
@@ -68,12 +300,7 @@ describe('InputGroup', () => {
|
|
|
68
300
|
it('renders the input', () => {
|
|
69
301
|
render(
|
|
70
302
|
<InputGroup label="Price">
|
|
71
|
-
<TextInput
|
|
72
|
-
label="Amount"
|
|
73
|
-
isLabelHidden
|
|
74
|
-
value=""
|
|
75
|
-
onChange={() => {}}
|
|
76
|
-
/>
|
|
303
|
+
<TextInput label="Amount" isLabelHidden value="" onChange={() => {}} />
|
|
77
304
|
</InputGroup>,
|
|
78
305
|
);
|
|
79
306
|
|
|
@@ -97,12 +324,7 @@ describe('InputGroup', () => {
|
|
|
97
324
|
it('applies data-testid', () => {
|
|
98
325
|
render(
|
|
99
326
|
<InputGroup label="Price" data-testid="price-group">
|
|
100
|
-
<TextInput
|
|
101
|
-
label="Amount"
|
|
102
|
-
isLabelHidden
|
|
103
|
-
value=""
|
|
104
|
-
onChange={() => {}}
|
|
105
|
-
/>
|
|
327
|
+
<TextInput label="Amount" isLabelHidden value="" onChange={() => {}} />
|
|
106
328
|
</InputGroup>,
|
|
107
329
|
);
|
|
108
330
|
|
|
@@ -112,12 +334,7 @@ describe('InputGroup', () => {
|
|
|
112
334
|
it('renders description text', () => {
|
|
113
335
|
render(
|
|
114
336
|
<InputGroup label="Price" description="Enter the price in USD">
|
|
115
|
-
<TextInput
|
|
116
|
-
label="Amount"
|
|
117
|
-
isLabelHidden
|
|
118
|
-
value=""
|
|
119
|
-
onChange={() => {}}
|
|
120
|
-
/>
|
|
337
|
+
<TextInput label="Amount" isLabelHidden value="" onChange={() => {}} />
|
|
121
338
|
</InputGroup>,
|
|
122
339
|
);
|
|
123
340
|
|
|
@@ -129,12 +346,7 @@ describe('InputGroup', () => {
|
|
|
129
346
|
<InputGroup
|
|
130
347
|
label="Price"
|
|
131
348
|
status={{type: 'error', message: 'Price is required'}}>
|
|
132
|
-
<TextInput
|
|
133
|
-
label="Amount"
|
|
134
|
-
isLabelHidden
|
|
135
|
-
value=""
|
|
136
|
-
onChange={() => {}}
|
|
137
|
-
/>
|
|
349
|
+
<TextInput label="Amount" isLabelHidden value="" onChange={() => {}} />
|
|
138
350
|
</InputGroup>,
|
|
139
351
|
);
|
|
140
352
|
|
|
@@ -144,12 +356,7 @@ describe('InputGroup', () => {
|
|
|
144
356
|
it('renders with hidden label', () => {
|
|
145
357
|
render(
|
|
146
358
|
<InputGroup label="Price" isLabelHidden>
|
|
147
|
-
<TextInput
|
|
148
|
-
label="Amount"
|
|
149
|
-
isLabelHidden
|
|
150
|
-
value=""
|
|
151
|
-
onChange={() => {}}
|
|
152
|
-
/>
|
|
359
|
+
<TextInput label="Amount" isLabelHidden value="" onChange={() => {}} />
|
|
153
360
|
</InputGroup>,
|
|
154
361
|
);
|
|
155
362
|
|
|
@@ -160,24 +367,14 @@ describe('InputGroup', () => {
|
|
|
160
367
|
it('renders with different sizes', () => {
|
|
161
368
|
const {rerender} = render(
|
|
162
369
|
<InputGroup label="Price" size="sm">
|
|
163
|
-
<TextInput
|
|
164
|
-
label="Amount"
|
|
165
|
-
isLabelHidden
|
|
166
|
-
value=""
|
|
167
|
-
onChange={() => {}}
|
|
168
|
-
/>
|
|
370
|
+
<TextInput label="Amount" isLabelHidden value="" onChange={() => {}} />
|
|
169
371
|
</InputGroup>,
|
|
170
372
|
);
|
|
171
373
|
expect(screen.getByRole('textbox')).toBeInTheDocument();
|
|
172
374
|
|
|
173
375
|
rerender(
|
|
174
376
|
<InputGroup label="Price" size="lg">
|
|
175
|
-
<TextInput
|
|
176
|
-
label="Amount"
|
|
177
|
-
isLabelHidden
|
|
178
|
-
value=""
|
|
179
|
-
onChange={() => {}}
|
|
180
|
-
/>
|
|
377
|
+
<TextInput label="Amount" isLabelHidden value="" onChange={() => {}} />
|
|
181
378
|
</InputGroup>,
|
|
182
379
|
);
|
|
183
380
|
expect(screen.getByRole('textbox')).toBeInTheDocument();
|
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file InputGroup.tsx
|
|
7
|
-
* @input Uses React, StyleX, theme tokens, InputGroupContext
|
|
8
|
-
* @output Exports InputGroup component
|
|
7
|
+
* @input Uses React, StyleX, theme tokens, InputGroupContext, Field
|
|
8
|
+
* @output Exports InputGroup component with group label/description ARIA wiring
|
|
9
9
|
* @position Groups input with prefix/suffix addons; consumed by index.ts
|
|
10
10
|
*
|
|
11
|
-
* Children (TextInput, NumberInput
|
|
11
|
+
* Children (TextInput, NumberInput, TimeInput, DateInput, Typeahead,
|
|
12
|
+
* Selector, MultiSelector) consume the InputGroup context
|
|
12
13
|
* to remove their own border/radius so the group container provides
|
|
13
14
|
* the unified border treatment.
|
|
14
15
|
*
|
|
@@ -156,9 +157,22 @@ export function InputGroup({
|
|
|
156
157
|
}: InputGroupProps) {
|
|
157
158
|
const size = useSize(sizeProp, 'md');
|
|
158
159
|
const inputId = useId();
|
|
160
|
+
const labelID = useId();
|
|
161
|
+
const descriptionID = useId();
|
|
159
162
|
const statusMessageId = useId();
|
|
160
163
|
|
|
161
|
-
const
|
|
164
|
+
const describedByIDs =
|
|
165
|
+
[
|
|
166
|
+
description ? descriptionID : null,
|
|
167
|
+
status?.message ? statusMessageId : null,
|
|
168
|
+
]
|
|
169
|
+
.filter(Boolean)
|
|
170
|
+
.join(' ') || undefined;
|
|
171
|
+
|
|
172
|
+
const contextValue = useMemo(
|
|
173
|
+
() => ({isInGroup: true as const, labelID, describedByIDs}),
|
|
174
|
+
[labelID, describedByIDs],
|
|
175
|
+
);
|
|
162
176
|
|
|
163
177
|
return (
|
|
164
178
|
<InputGroupContext value={contextValue}>
|
|
@@ -168,6 +182,9 @@ export function InputGroup({
|
|
|
168
182
|
isLabelHidden={isLabelHidden}
|
|
169
183
|
description={description}
|
|
170
184
|
inputID={inputId}
|
|
185
|
+
labelID={labelID}
|
|
186
|
+
descriptionID={description ? descriptionID : undefined}
|
|
187
|
+
isGroupLabel
|
|
171
188
|
isOptional={isOptional}
|
|
172
189
|
isRequired={isRequired}
|
|
173
190
|
isDisabled={isDisabled}
|
|
@@ -185,7 +202,8 @@ export function InputGroup({
|
|
|
185
202
|
<div
|
|
186
203
|
ref={ref}
|
|
187
204
|
role="group"
|
|
188
|
-
aria-
|
|
205
|
+
aria-labelledby={labelID}
|
|
206
|
+
aria-describedby={describedByIDs}
|
|
189
207
|
data-testid={testId}
|
|
190
208
|
{...rest}
|
|
191
209
|
{...mergeProps(
|
|
@@ -4,19 +4,24 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file InputGroupContext.ts
|
|
7
|
-
* @input
|
|
7
|
+
* @input React createContext/use
|
|
8
8
|
* @output Exports InputGroup context and useInputGroup hook
|
|
9
|
-
* @position Shared context; consumed by input components for group-aware styling
|
|
9
|
+
* @position Shared context; consumed by input components for group-aware styling and ARIA associations
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import {createContext, use} from 'react';
|
|
13
13
|
|
|
14
14
|
export interface InputGroupContextValue {
|
|
15
15
|
isInGroup: true;
|
|
16
|
+
/** ID of the group label element, for aria-labelledby composition. */
|
|
17
|
+
labelID: string;
|
|
18
|
+
/** IDs of helper/status text owned by the group, for aria-describedby composition. */
|
|
19
|
+
describedByIDs?: string;
|
|
16
20
|
}
|
|
17
21
|
|
|
18
|
-
export const InputGroupContext =
|
|
19
|
-
|
|
22
|
+
export const InputGroupContext = createContext<InputGroupContextValue | null>(
|
|
23
|
+
null,
|
|
24
|
+
);
|
|
20
25
|
InputGroupContext.displayName = 'InputGroupContext';
|
|
21
26
|
|
|
22
27
|
/**
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @file groupStyles.ts
|
|
5
5
|
* @input Uses StyleX, theme tokens
|
|
6
6
|
* @output Exports shared group-aware styles for input components
|
|
7
|
-
* @position Shared styles consumed by
|
|
7
|
+
* @position Shared styles consumed by InputGroup-compatible controls
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import * as stylex from '@stylexjs/stylex';
|
|
@@ -30,10 +30,16 @@ export const groupStyles = stylex.create({
|
|
|
30
30
|
borderStartEndRadius: {
|
|
31
31
|
default: 0,
|
|
32
32
|
':last-child': radiusVars['--radius-element'],
|
|
33
|
+
':has(+ [popover]:last-child)': radiusVars['--radius-element'],
|
|
34
|
+
':has(+ [popover] + [popover]:last-child)':
|
|
35
|
+
radiusVars['--radius-element'],
|
|
33
36
|
},
|
|
34
37
|
borderEndEndRadius: {
|
|
35
38
|
default: 0,
|
|
36
39
|
':last-child': radiusVars['--radius-element'],
|
|
40
|
+
':has(+ [popover]:last-child)': radiusVars['--radius-element'],
|
|
41
|
+
':has(+ [popover] + [popover]:last-child)':
|
|
42
|
+
radiusVars['--radius-element'],
|
|
37
43
|
},
|
|
38
44
|
':focus-within': {
|
|
39
45
|
zIndex: 1,
|
package/src/InputGroup/index.ts
CHANGED
package/src/Kbd/Kbd.test.tsx
CHANGED
|
@@ -72,10 +72,28 @@ describe('Kbd', () => {
|
|
|
72
72
|
expect(screen.getByText('Esc')).toBeInTheDocument();
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
-
it('
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
it('exposes a spoken accessible name and hides the glyphs (obs-1)', () => {
|
|
76
|
+
render(<Kbd keys="mod+shift+k" />);
|
|
77
|
+
// The wrapper carries a screen-reader name built from spoken key labels
|
|
78
|
+
// (jsdom is non-Mac, so mod → "Control").
|
|
79
|
+
const img = screen.getByRole('img');
|
|
80
|
+
expect(img).toHaveAttribute('aria-label', 'Control + Shift + K');
|
|
81
|
+
// The visual glyph elements are hidden from assistive tech.
|
|
82
|
+
const glyphs = img.querySelectorAll('kbd');
|
|
83
|
+
glyphs.forEach(g => expect(g).toHaveAttribute('aria-hidden', 'true'));
|
|
84
|
+
expect(img).not.toHaveAttribute('aria-hidden');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('uses "Command" in the accessible name for mod on Mac', () => {
|
|
88
|
+
Object.defineProperty(navigator, 'platform', {
|
|
89
|
+
value: 'MacIntel',
|
|
90
|
+
configurable: true,
|
|
91
|
+
});
|
|
92
|
+
render(<Kbd keys="mod+k" />);
|
|
93
|
+
expect(screen.getByRole('img')).toHaveAttribute(
|
|
94
|
+
'aria-label',
|
|
95
|
+
'Command + K',
|
|
96
|
+
);
|
|
79
97
|
});
|
|
80
98
|
|
|
81
99
|
it('uppercases unknown keys', () => {
|
package/src/Kbd/Kbd.tsx
CHANGED
|
@@ -87,6 +87,33 @@ function getKeyDisplay(key: string, isMac: boolean): string {
|
|
|
87
87
|
return KEY_DISPLAY[key] ?? key.toUpperCase();
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Spoken-word labels for screen readers. The visual `KEY_DISPLAY` uses glyphs
|
|
92
|
+
* (⌘, ⇧, ↵, …) that assistive tech cannot announce meaningfully, so the
|
|
93
|
+
* accessible name for the shortcut is built from these words instead.
|
|
94
|
+
*/
|
|
95
|
+
const KEY_LABEL: Record<string, string> = {
|
|
96
|
+
ctrl: 'Control',
|
|
97
|
+
alt: 'Alt',
|
|
98
|
+
shift: 'Shift',
|
|
99
|
+
enter: 'Enter',
|
|
100
|
+
backspace: 'Backspace',
|
|
101
|
+
escape: 'Escape',
|
|
102
|
+
tab: 'Tab',
|
|
103
|
+
up: 'Up arrow',
|
|
104
|
+
down: 'Down arrow',
|
|
105
|
+
left: 'Left arrow',
|
|
106
|
+
right: 'Right arrow',
|
|
107
|
+
plus: 'Plus',
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
function getKeyLabel(key: string, isMac: boolean): string {
|
|
111
|
+
if (key === 'mod') {
|
|
112
|
+
return isMac ? 'Command' : 'Control';
|
|
113
|
+
}
|
|
114
|
+
return KEY_LABEL[key] ?? key.toUpperCase();
|
|
115
|
+
}
|
|
116
|
+
|
|
90
117
|
function subscribeToPlatformChanges(): () => void {
|
|
91
118
|
return () => {};
|
|
92
119
|
}
|
|
@@ -155,19 +182,24 @@ export function Kbd({keys, ref, xstyle, className, style, ...rest}: KbdProps) {
|
|
|
155
182
|
|
|
156
183
|
const parts = keys.split('+').map(key => key.trim().toLowerCase());
|
|
157
184
|
|
|
185
|
+
// Screen-reader name: the joined spoken labels (e.g. "Command + K"), since
|
|
186
|
+
// the visual glyphs below are announced meaninglessly by assistive tech.
|
|
187
|
+
const accessibleName = parts.map(key => getKeyLabel(key, isMac)).join(' + ');
|
|
188
|
+
|
|
158
189
|
return (
|
|
159
190
|
<span
|
|
160
191
|
ref={ref}
|
|
192
|
+
role="img"
|
|
193
|
+
aria-label={accessibleName}
|
|
161
194
|
{...rest}
|
|
162
195
|
{...mergeProps(
|
|
163
196
|
themeProps('kbd'),
|
|
164
197
|
stylex.props(styles.wrapper, xstyle),
|
|
165
198
|
className,
|
|
166
199
|
style,
|
|
167
|
-
)}
|
|
168
|
-
aria-hidden="true">
|
|
200
|
+
)}>
|
|
169
201
|
{parts.map(key => (
|
|
170
|
-
<kbd key={key} {...stylex.props(styles.kbd)}>
|
|
202
|
+
<kbd key={key} aria-hidden="true" {...stylex.props(styles.kbd)}>
|
|
171
203
|
{getKeyDisplay(key, isMac)}
|
|
172
204
|
</kbd>
|
|
173
205
|
))}
|
|
@@ -72,22 +72,38 @@ const animationBase = {
|
|
|
72
72
|
*
|
|
73
73
|
* Keyed by LayerPlacement ('above' | 'below' | 'start' | 'end')
|
|
74
74
|
* for easy lookup: `layerAnimations[placement]`.
|
|
75
|
+
*
|
|
76
|
+
* Each entry disables its keyframe animation under
|
|
77
|
+
* `prefers-reduced-motion: reduce` so the layer appears instantly instead of
|
|
78
|
+
* translating/scaling in (infra-6).
|
|
75
79
|
*/
|
|
76
80
|
export const layerAnimations = stylex.create({
|
|
77
81
|
below: {
|
|
78
|
-
animationName:
|
|
82
|
+
animationName: {
|
|
83
|
+
default: enterBelow,
|
|
84
|
+
'@media (prefers-reduced-motion: reduce)': 'none',
|
|
85
|
+
},
|
|
79
86
|
...animationBase,
|
|
80
87
|
},
|
|
81
88
|
above: {
|
|
82
|
-
animationName:
|
|
89
|
+
animationName: {
|
|
90
|
+
default: enterAbove,
|
|
91
|
+
'@media (prefers-reduced-motion: reduce)': 'none',
|
|
92
|
+
},
|
|
83
93
|
...animationBase,
|
|
84
94
|
},
|
|
85
95
|
end: {
|
|
86
|
-
animationName:
|
|
96
|
+
animationName: {
|
|
97
|
+
default: enterEnd,
|
|
98
|
+
'@media (prefers-reduced-motion: reduce)': 'none',
|
|
99
|
+
},
|
|
87
100
|
...animationBase,
|
|
88
101
|
},
|
|
89
102
|
start: {
|
|
90
|
-
animationName:
|
|
103
|
+
animationName: {
|
|
104
|
+
default: enterStart,
|
|
105
|
+
'@media (prefers-reduced-motion: reduce)': 'none',
|
|
106
|
+
},
|
|
91
107
|
...animationBase,
|
|
92
108
|
},
|
|
93
109
|
});
|
|
@@ -144,6 +144,11 @@ export const docsDense = {
|
|
|
144
144
|
guidance: true,
|
|
145
145
|
description: 'Build on Popover/HoverCard/Tooltip for common overlay patterns.',
|
|
146
146
|
},
|
|
147
|
+
{
|
|
148
|
+
guidance: true,
|
|
149
|
+
description:
|
|
150
|
+
'Rely on the Popover API top layer to escape clipping/stacking: render inline (no portal) to inherit the trigger theme cascade and natural focus order. Use `as: "span"` when the layer must be valid in inline contexts like a paragraph.',
|
|
151
|
+
},
|
|
147
152
|
{
|
|
148
153
|
guidance: false,
|
|
149
154
|
description:
|