@astryxdesign/core 0.1.8 → 0.1.9-canary.02ef052
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 +100 -0
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +6 -2
- package/dist/AppShell/AppShellMobileContext.d.ts +8 -0
- package/dist/AppShell/AppShellMobileContext.d.ts.map +1 -1
- package/dist/Avatar/Avatar.d.ts +58 -3
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +240 -53
- package/dist/Avatar/AvatarStatusDot.d.ts +35 -5
- package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
- package/dist/Avatar/AvatarStatusDot.js +144 -19
- package/dist/AvatarGroup/AvatarGroup.d.ts +7 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +58 -6
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +1 -0
- package/dist/Banner/Banner.d.ts +9 -1
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +33 -4
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +31 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +215 -6
- package/dist/Breadcrumbs/index.d.ts +6 -0
- package/dist/Breadcrumbs/index.d.ts.map +1 -1
- package/dist/Breadcrumbs/index.js +10 -1
- package/dist/Button/Button.d.ts +8 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +33 -4
- package/dist/ButtonGroup/ButtonGroup.d.ts +9 -1
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +30 -1
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +80 -11
- package/dist/Calendar/dayCellUtils.d.ts +4 -4
- package/dist/Calendar/dayCellUtils.js +3 -3
- package/dist/Calendar/styles.d.ts +30 -31
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +30 -31
- package/dist/Card/Card.d.ts +8 -2
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +28 -2
- package/dist/Carousel/Carousel.d.ts +4 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +46 -16
- package/dist/Chat/ChatComposer.d.ts +8 -0
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +46 -7
- package/dist/Chat/ChatComposerDrawer.d.ts +2 -0
- package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
- package/dist/Chat/ChatComposerDrawer.js +11 -1
- package/dist/Chat/ChatComposerInput.d.ts +20 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +36 -4
- package/dist/Chat/ChatContext.d.ts +33 -0
- package/dist/Chat/ChatContext.d.ts.map +1 -1
- package/dist/Chat/ChatContext.js +16 -2
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +4 -2
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +4 -4
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +4 -4
- package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.js +7 -1
- package/dist/Chat/ChatToolCalls.d.ts +5 -1
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +27 -11
- package/dist/Chat/index.d.ts +2 -1
- package/dist/Chat/index.d.ts.map +1 -1
- package/dist/Chat/index.js +1 -1
- package/dist/Chat/useChatStreamScroll.d.ts +2 -1
- package/dist/Chat/useChatStreamScroll.d.ts.map +1 -1
- package/dist/Chat/useChatStreamScroll.js +22 -8
- package/dist/Chat/useSpeechRecognition.d.ts +0 -1
- package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
- package/dist/Chat/useSpeechRecognition.js +1 -1
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +2 -2
- package/dist/CheckboxInput/CheckboxInput.js +5 -5
- package/dist/CheckboxList/CheckboxListItem.d.ts +20 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +11 -1
- package/dist/Citation/Citation.d.ts +22 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +20 -6
- package/dist/ClickableCard/ClickableCard.d.ts +9 -2
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +5 -2
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +22 -9
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +3 -1
- package/dist/CommandPalette/CommandPalette.d.ts +2 -2
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +45 -4
- package/dist/CommandPalette/CommandPaletteGroup.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteGroup.js +9 -2
- package/dist/CommandPalette/CommandPaletteInput.d.ts +7 -1
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +6 -1
- package/dist/CommandPalette/CommandPaletteItem.js +1 -1
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +14 -5
- package/dist/ContextMenu/index.d.ts +1 -0
- package/dist/ContextMenu/index.d.ts.map +1 -1
- package/dist/ContextMenu/index.js +3 -1
- package/dist/DateInput/DateInput.d.ts +56 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +59 -21
- package/dist/DateInput/index.d.ts +1 -1
- package/dist/DateInput/index.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts +10 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +23 -20
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +33 -19
- package/dist/Dialog/Dialog.d.ts +3 -0
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +57 -6
- package/dist/Dialog/DialogContext.d.ts +7 -0
- package/dist/Dialog/DialogContext.d.ts.map +1 -1
- package/dist/Dialog/DialogContext.js +2 -2
- package/dist/Dialog/DialogHeader.d.ts +5 -2
- package/dist/Dialog/DialogHeader.d.ts.map +1 -1
- package/dist/Dialog/DialogHeader.js +6 -1
- package/dist/Divider/Divider.js +1 -1
- package/dist/DropdownMenu/DropdownMenu.d.ts +6 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +22 -5
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +1 -2
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +5 -3
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +5 -2
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +1 -2
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +1 -2
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +4 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +104 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +427 -0
- package/dist/DropdownMenu/index.d.ts +10 -0
- package/dist/DropdownMenu/index.d.ts.map +1 -1
- package/dist/DropdownMenu/index.js +13 -0
- package/dist/DropdownMenu/menuItemHover.d.ts +23 -0
- package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -0
- package/dist/DropdownMenu/menuItemHover.js +33 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts +8 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -1
- package/dist/DropdownMenu/menuItemRoles.js +10 -1
- package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
- package/dist/DropdownMenu/renderDropdownItems.js +21 -6
- package/dist/Field/Field.d.ts +3 -1
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +6 -4
- package/dist/Field/FieldLabel.d.ts +1 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +43 -16
- package/dist/Field/inputStyles.stylex.d.ts +1 -0
- package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
- package/dist/Field/inputStyles.stylex.js +1 -0
- package/dist/FieldStatus/FieldStatus.d.ts +18 -0
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +60 -6
- package/dist/FileInput/FileInput.d.ts +10 -2
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +54 -35
- package/dist/HoverCard/HoverCard.d.ts +9 -1
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +2 -0
- package/dist/HoverCard/useHoverCard.d.ts +8 -0
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +17 -6
- package/dist/Icon/Icon.d.ts +22 -3
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +19 -3
- package/dist/Item/Item.d.ts +6 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +22 -1
- package/dist/Layer/useLayer.d.ts +6 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +2 -0
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +19 -13
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +7 -0
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +6 -1
- package/dist/MobileNav/MobileNavToggle.d.ts.map +1 -1
- package/dist/MobileNav/MobileNavToggle.js +4 -0
- package/dist/MultiSelector/MultiSelector.d.ts +9 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +104 -50
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +16 -0
- package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
- package/dist/NumberInput/NumberInput.d.ts +10 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +22 -17
- package/dist/Outline/Outline.d.ts +0 -1
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +0 -1
- package/dist/OverflowList/OverflowList.d.ts +20 -3
- package/dist/OverflowList/OverflowList.d.ts.map +1 -1
- package/dist/OverflowList/OverflowList.js +29 -4
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +11 -3
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +3 -2
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +3 -9
- package/dist/PowerSearch/PowerSearch.d.ts +9 -2
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +2 -0
- package/dist/PowerSearch/PowerSearchEditPopover.js +1 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
- package/dist/RadioList/RadioList.d.ts +2 -2
- package/dist/RadioList/RadioListItem.js +4 -4
- package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +2 -1
- package/dist/SelectableCard/SelectableCard.d.ts +9 -2
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +16 -13
- package/dist/Selector/Selector.d.ts +8 -0
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +65 -19
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +16 -0
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +5 -5
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +13 -10
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +21 -8
- package/dist/SideNav/SideNavItem.d.ts +1 -1
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +12 -10
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +106 -36
- package/dist/Stack/stack.stylex.d.ts +9 -9
- package/dist/Switch/Switch.d.ts +8 -1
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +160 -91
- package/dist/TabList/Tab.js +2 -2
- package/dist/TabList/TabMenu.js +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +33 -6
- package/dist/Table/TableCell.js +3 -3
- package/dist/Table/TableHeaderCell.js +3 -3
- package/dist/Table/index.d.ts +2 -0
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +1 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +15 -11
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +36 -26
- package/dist/Table/plugins/rowStatus/index.d.ts +3 -0
- package/dist/Table/plugins/rowStatus/index.d.ts.map +1 -0
- package/dist/Table/plugins/rowStatus/index.js +3 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts +60 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.js +145 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts +13 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +7 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.d.ts +16 -0
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.js +105 -12
- package/dist/Table/plugins/tree/useTableTreeState.d.ts +6 -0
- package/dist/Table/plugins/tree/useTableTreeState.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeState.js +22 -1
- package/dist/Table/types.d.ts +32 -0
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +5 -3
- package/dist/TextArea/TextArea.d.ts +10 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +18 -19
- package/dist/TextInput/TextInput.d.ts +10 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +20 -17
- package/dist/Thumbnail/Thumbnail.d.ts +26 -5
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +97 -54
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts +9 -0
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts.map +1 -0
- package/dist/Thumbnail/thumbnail.markers.stylex.js +14 -0
- package/dist/TimeInput/TimeInput.d.ts +10 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +32 -21
- package/dist/Timestamp/Timestamp.d.ts +3 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +8 -6
- package/dist/Toast/useToast.d.ts.map +1 -1
- package/dist/Toast/useToast.js +2 -5
- package/dist/ToggleButton/ToggleButtonGroup.d.ts +0 -1
- package/dist/ToggleButton/ToggleButtonGroup.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButtonGroup.js +1 -1
- package/dist/Token/Token.d.ts +30 -3
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +17 -2
- package/dist/Token/index.d.ts +1 -1
- package/dist/Token/index.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.d.ts +10 -3
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +20 -6
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +17 -1
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +18 -8
- package/dist/TopNav/TopNavMegaMenu.js +10 -4
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts +9 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.js +8 -1
- package/dist/TopNav/TopNavMenu.d.ts +2 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +68 -6
- package/dist/TreeList/TreeList.d.ts +12 -3
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +3 -0
- package/dist/TreeList/TreeListBranches.d.ts +5 -0
- package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
- package/dist/TreeList/TreeListBranches.js +18 -10
- package/dist/TreeList/TreeListItem.d.ts +8 -2
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +59 -21
- package/dist/TreeList/TreeListTypes.d.ts +25 -1
- package/dist/TreeList/TreeListTypes.d.ts.map +1 -1
- package/dist/TreeList/index.d.ts +2 -2
- package/dist/TreeList/index.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +20 -11
- package/dist/Typeahead/Typeahead.d.ts +9 -2
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +3 -1
- package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
- package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
- package/dist/Typeahead/TypeaheadItem.js +20 -10
- package/dist/astryx.css +61 -39
- package/dist/astryx.umd.js +53 -53
- package/dist/astryx.umd.js.map +4 -4
- package/dist/authoring/doc.d.ts.map +1 -1
- package/dist/docs-types.d.ts +8 -0
- package/dist/docs-types.d.ts.map +1 -1
- package/dist/hooks/computeOverflow.d.ts +47 -0
- package/dist/hooks/computeOverflow.d.ts.map +1 -0
- package/dist/hooks/computeOverflow.js +213 -0
- package/dist/hooks/index.d.ts +3 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +3 -1
- package/dist/hooks/isRtlElement.d.ts +18 -0
- package/dist/hooks/isRtlElement.d.ts.map +1 -0
- package/dist/hooks/isRtlElement.js +27 -0
- package/dist/hooks/useDevWarning.d.ts +18 -0
- package/dist/hooks/useDevWarning.d.ts.map +1 -0
- package/dist/hooks/useDevWarning.js +49 -0
- package/dist/hooks/useGridFocus.d.ts +6 -1
- package/dist/hooks/useGridFocus.d.ts.map +1 -1
- package/dist/hooks/useGridFocus.js +12 -9
- package/dist/hooks/useInputStatusIcon.d.ts +38 -0
- package/dist/hooks/useInputStatusIcon.d.ts.map +1 -0
- package/dist/hooks/useInputStatusIcon.js +158 -0
- package/dist/hooks/useListFocus.d.ts +39 -1
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +54 -9
- package/dist/hooks/useOverflow.d.ts +19 -0
- package/dist/hooks/useOverflow.d.ts.map +1 -1
- package/dist/hooks/useOverflow.js +36 -25
- package/dist/i18n/InternationalizationContext.d.ts +1 -0
- package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
- package/dist/i18n/InternationalizationContext.js +3 -0
- package/dist/i18n/InternationalizationProvider.d.ts +8 -1
- package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
- package/dist/i18n/InternationalizationProvider.js +5 -1
- package/dist/i18n/getLocaleDirection.d.ts +18 -0
- package/dist/i18n/getLocaleDirection.d.ts.map +1 -0
- package/dist/i18n/getLocaleDirection.js +29 -0
- package/dist/i18n/index.d.ts +6 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +7 -1
- package/dist/i18n/resolve.d.ts.map +1 -1
- package/dist/i18n/resolve.js +7 -18
- package/dist/i18n/useDirection.d.ts +2 -0
- package/dist/i18n/useDirection.d.ts.map +1 -0
- package/dist/i18n/useDirection.js +27 -0
- package/dist/theme/Theme.d.ts.map +1 -1
- package/dist/theme/Theme.js +2 -7
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +13 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +51 -0
- package/dist/theme/hct.d.ts +0 -1
- package/dist/theme/hct.d.ts.map +1 -1
- package/dist/theme/hct.js +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.js +2 -1
- package/dist/utils/devWarning.d.ts +42 -0
- package/dist/utils/devWarning.d.ts.map +1 -0
- package/dist/utils/devWarning.js +88 -0
- package/dist/utils/index.d.ts +4 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -2
- package/dist/utils/plainDate.d.ts +30 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +65 -3
- package/dist/utils/rtlStyles.d.ts +24 -0
- package/dist/utils/rtlStyles.d.ts.map +1 -0
- package/dist/utils/rtlStyles.js +27 -0
- package/dist/utils/types.d.ts +13 -0
- package/dist/utils/types.d.ts.map +1 -1
- package/locales/en.json +104 -0
- package/locales/fr-FR.json +14 -0
- package/locales/pseudo.json +78 -0
- package/package.json +6 -1
- package/src/AppShell/AppShell.tsx +6 -0
- package/src/AppShell/AppShellMobileContext.tsx +8 -0
- package/src/AppShell/useAppShellMobile.doc.mjs +8 -0
- package/src/Avatar/Avatar.doc.mjs +64 -5
- package/src/Avatar/Avatar.test.tsx +374 -1
- package/src/Avatar/Avatar.tsx +367 -69
- package/src/Avatar/AvatarStatusDot.doc.mjs +23 -12
- package/src/Avatar/AvatarStatusDot.test.tsx +284 -0
- package/src/Avatar/AvatarStatusDot.tsx +180 -21
- package/src/AvatarGroup/AvatarGroup.doc.mjs +2 -0
- package/src/AvatarGroup/AvatarGroup.test.tsx +141 -1
- package/src/AvatarGroup/AvatarGroup.tsx +58 -3
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +1 -0
- package/src/Banner/Banner.doc.mjs +9 -0
- package/src/Banner/Banner.test.tsx +30 -0
- package/src/Banner/Banner.tsx +53 -9
- package/src/Breadcrumbs/BreadcrumbItem.doc.mjs +26 -0
- package/src/Breadcrumbs/BreadcrumbItem.tsx +333 -14
- package/src/Breadcrumbs/Breadcrumbs.doc.mjs +2 -0
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +335 -2
- package/src/Breadcrumbs/index.ts +31 -0
- package/src/Button/Button.doc.mjs +9 -4
- package/src/Button/Button.test.tsx +49 -0
- package/src/Button/Button.tsx +27 -3
- package/src/ButtonGroup/ButtonGroup.doc.mjs +3 -0
- package/src/ButtonGroup/ButtonGroup.test.tsx +37 -0
- package/src/ButtonGroup/ButtonGroup.tsx +32 -0
- package/src/Calendar/Calendar.doc.mjs +12 -1
- package/src/Calendar/Calendar.test.tsx +362 -19
- package/src/Calendar/Calendar.tsx +111 -32
- package/src/Calendar/dayCellUtils.test.ts +23 -18
- package/src/Calendar/dayCellUtils.ts +3 -3
- package/src/Calendar/styles.ts +33 -39
- package/src/Card/Card.doc.mjs +9 -0
- package/src/Card/Card.test.tsx +21 -3
- package/src/Card/Card.tsx +35 -2
- package/src/Carousel/Carousel.doc.mjs +1 -0
- package/src/Carousel/Carousel.test.tsx +53 -0
- package/src/Carousel/Carousel.tsx +59 -10
- package/src/Chat/ChatComposer.doc.mjs +12 -3
- package/src/Chat/ChatComposer.test.tsx +115 -0
- package/src/Chat/ChatComposer.tsx +73 -9
- package/src/Chat/ChatComposerDrawer.test.tsx +61 -0
- package/src/Chat/ChatComposerDrawer.tsx +11 -1
- package/src/Chat/ChatComposerInput.doc.mjs +7 -0
- package/src/Chat/ChatComposerInput.test.tsx +103 -0
- package/src/Chat/ChatComposerInput.tsx +51 -5
- package/src/Chat/ChatContext.tsx +37 -10
- package/src/Chat/ChatDictationButton.tsx +11 -2
- package/src/Chat/ChatLayout.tsx +7 -5
- package/src/Chat/ChatLayoutScrollButton.tsx +7 -2
- package/src/Chat/ChatMessageMetadata.tsx +1 -2
- package/src/Chat/ChatSendButton.tsx +11 -1
- package/src/Chat/ChatToolCalls.test.tsx +64 -0
- package/src/Chat/ChatToolCalls.tsx +33 -5
- package/src/Chat/index.ts +5 -1
- package/src/Chat/useChatStreamScroll.test.tsx +49 -0
- package/src/Chat/useChatStreamScroll.ts +27 -10
- package/src/Chat/useSpeechRecognition.ts +1 -1
- package/src/Chat/useTriggerMenu.tsx +4 -2
- package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +32 -1
- package/src/CheckboxInput/CheckboxInput.tsx +5 -5
- package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
- package/src/CheckboxList/CheckboxList.test.tsx +81 -3
- package/src/CheckboxList/CheckboxListItem.doc.mjs +33 -5
- package/src/CheckboxList/CheckboxListItem.tsx +41 -5
- package/src/Citation/Citation.doc.mjs +4 -3
- package/src/Citation/Citation.test.tsx +97 -0
- package/src/Citation/Citation.tsx +43 -11
- package/src/ClickableCard/ClickableCard.doc.mjs +2 -0
- package/src/ClickableCard/ClickableCard.test.tsx +34 -0
- package/src/ClickableCard/ClickableCard.tsx +13 -3
- package/src/CodeBlock/CodeBlock.test.tsx +56 -0
- package/src/CodeBlock/CodeBlock.tsx +45 -10
- package/src/Collapsible/Collapsible.doc.mjs +1 -0
- package/src/Collapsible/Collapsible.test.tsx +7 -0
- package/src/Collapsible/Collapsible.tsx +16 -6
- package/src/CommandPalette/CommandPalette.doc.mjs +1 -0
- package/src/CommandPalette/CommandPalette.test.tsx +95 -1
- package/src/CommandPalette/CommandPalette.tsx +44 -3
- package/src/CommandPalette/CommandPaletteGroup.test.tsx +71 -0
- package/src/CommandPalette/CommandPaletteGroup.tsx +12 -1
- package/src/CommandPalette/CommandPaletteInput.doc.mjs +26 -9
- package/src/CommandPalette/CommandPaletteInput.test.tsx +34 -0
- package/src/CommandPalette/CommandPaletteInput.tsx +11 -0
- package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
- package/src/ContextMenu/ContextMenu.test.tsx +235 -0
- package/src/ContextMenu/ContextMenu.tsx +13 -11
- package/src/ContextMenu/index.ts +5 -0
- package/src/DateInput/DateInput.doc.mjs +41 -0
- package/src/DateInput/DateInput.test.tsx +338 -0
- package/src/DateInput/DateInput.tsx +119 -32
- package/src/DateInput/index.ts +1 -0
- package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
- package/src/DateRangeInput/DateRangeInput.test.tsx +140 -0
- package/src/DateRangeInput/DateRangeInput.tsx +42 -30
- package/src/DateTimeInput/DateTimeInput.doc.mjs +22 -1
- package/src/DateTimeInput/DateTimeInput.test.tsx +147 -0
- package/src/DateTimeInput/DateTimeInput.tsx +58 -41
- package/src/Dialog/Dialog.doc.mjs +2 -2
- package/src/Dialog/Dialog.test.tsx +77 -4
- package/src/Dialog/Dialog.tsx +89 -5
- package/src/Dialog/DialogContext.ts +9 -2
- package/src/Dialog/DialogHeader.doc.mjs +2 -2
- package/src/Dialog/DialogHeader.tsx +9 -2
- package/src/Divider/Divider.tsx +2 -2
- package/src/DropdownMenu/DropdownMenu.test.tsx +229 -0
- package/src/DropdownMenu/DropdownMenu.tsx +31 -12
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +9 -4
- package/src/DropdownMenu/DropdownMenuItem.tsx +9 -3
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +1 -2
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +8 -2
- package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +88 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +635 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +553 -0
- package/src/DropdownMenu/index.ts +16 -0
- package/src/DropdownMenu/menuItemHover.ts +39 -0
- package/src/DropdownMenu/menuItemRoles.ts +9 -0
- package/src/DropdownMenu/renderDropdownItems.tsx +29 -15
- package/src/Field/Field.test.tsx +57 -12
- package/src/Field/Field.tsx +20 -14
- package/src/Field/FieldLabel.tsx +9 -1
- package/src/Field/inputStyles.stylex.ts +2 -0
- package/src/FieldStatus/FieldStatus.doc.mjs +17 -5
- package/src/FieldStatus/FieldStatus.test.tsx +150 -40
- package/src/FieldStatus/FieldStatus.tsx +69 -5
- package/src/FileInput/FileInput.doc.mjs +23 -2
- package/src/FileInput/FileInput.test.tsx +135 -12
- package/src/FileInput/FileInput.tsx +65 -51
- package/src/HoverCard/HoverCard.doc.mjs +13 -0
- package/src/HoverCard/HoverCard.test.tsx +21 -2
- package/src/HoverCard/HoverCard.tsx +11 -0
- package/src/HoverCard/useHoverCard.doc.mjs +2 -0
- package/src/HoverCard/useHoverCard.tsx +39 -5
- package/src/Icon/Icon.doc.mjs +16 -2
- package/src/Icon/Icon.test.tsx +89 -0
- package/src/Icon/Icon.tsx +58 -5
- package/src/IconButton/IconButton.doc.mjs +8 -0
- package/src/IconButton/IconButton.test.tsx +15 -18
- package/src/Item/Item.test.tsx +40 -18
- package/src/Item/Item.tsx +38 -2
- package/src/Layer/useLayer.tsx +8 -0
- package/src/Lightbox/Lightbox.tsx +15 -7
- package/src/List/List.test.tsx +9 -8
- package/src/Markdown/Markdown.test.tsx +21 -0
- package/src/Markdown/Markdown.tsx +4 -0
- package/src/MobileNav/MobileNav.tsx +12 -1
- package/src/MobileNav/MobileNavToggle.test.tsx +116 -0
- package/src/MobileNav/MobileNavToggle.tsx +9 -1
- package/src/MultiSelector/MultiSelector.doc.mjs +24 -2
- package/src/MultiSelector/MultiSelector.test.tsx +498 -3
- package/src/MultiSelector/MultiSelector.tsx +149 -65
- package/src/MultiSelector/hooks.ts +17 -0
- package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
- package/src/NumberInput/NumberInput.doc.mjs +21 -0
- package/src/NumberInput/NumberInput.test.tsx +82 -7
- package/src/NumberInput/NumberInput.tsx +36 -28
- package/src/Outline/Outline.tsx +0 -1
- package/src/OverflowList/OverflowList.doc.mjs +39 -6
- package/src/OverflowList/OverflowList.test.tsx +111 -0
- package/src/OverflowList/OverflowList.tsx +48 -8
- package/src/Pagination/Pagination.tsx +11 -3
- package/src/Popover/Popover.tsx +7 -4
- package/src/Popover/usePopover.tsx +9 -13
- package/src/PowerSearch/PowerSearch.doc.mjs +29 -0
- package/src/PowerSearch/PowerSearch.test.tsx +43 -0
- package/src/PowerSearch/PowerSearch.tsx +10 -1
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +67 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +1 -1
- package/src/PowerSearch/usePowerSearchSource.ts +1 -2
- package/src/RadioList/RadioList.doc.mjs +6 -0
- package/src/RadioList/RadioList.tsx +2 -2
- package/src/RadioList/RadioListItem.tsx +4 -4
- package/src/SegmentedControl/SegmentedControlItem.tsx +2 -0
- package/src/SelectableCard/SelectableCard.doc.mjs +2 -0
- package/src/SelectableCard/SelectableCard.test.tsx +46 -4
- package/src/SelectableCard/SelectableCard.tsx +29 -16
- package/src/Selector/Selector.doc.mjs +15 -0
- package/src/Selector/Selector.test.tsx +417 -0
- package/src/Selector/Selector.tsx +86 -21
- package/src/Selector/hooks.ts +17 -0
- package/src/SideNav/SideNav.test.tsx +119 -3
- package/src/SideNav/SideNav.tsx +1 -8
- package/src/SideNav/SideNavCollapseButton.tsx +15 -8
- package/src/SideNav/SideNavHeading.tsx +24 -8
- package/src/SideNav/SideNavItem.tsx +10 -4
- package/src/Slider/Slider.doc.mjs +6 -0
- package/src/Slider/Slider.test.tsx +314 -13
- package/src/Slider/Slider.tsx +117 -28
- package/src/Switch/Switch.doc.mjs +142 -42
- package/src/Switch/Switch.test.tsx +54 -1
- package/src/Switch/Switch.tsx +90 -33
- package/src/TabList/Tab.tsx +2 -2
- package/src/TabList/TabMenu.tsx +2 -2
- package/src/Table/BaseTable.tsx +37 -7
- package/src/Table/Table.doc.mjs +11 -0
- package/src/Table/Table.test.tsx +85 -0
- package/src/Table/TableCell.tsx +3 -3
- package/src/Table/TableHeaderCell.tsx +3 -3
- package/src/Table/index.ts +5 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +15 -8
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +24 -17
- package/src/Table/plugins/rowStatus/index.ts +7 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +138 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +189 -0
- package/src/Table/plugins/selection/useTableSelection.test.tsx +77 -3
- package/src/Table/plugins/selection/useTableSelection.tsx +22 -1
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -1
- package/src/Table/plugins/tree/useTableTreeData.test.tsx +135 -3
- package/src/Table/plugins/tree/useTableTreeData.tsx +139 -8
- package/src/Table/plugins/tree/useTableTreeState.test.tsx +104 -0
- package/src/Table/plugins/tree/useTableTreeState.tsx +46 -2
- package/src/Table/types.ts +33 -0
- package/src/Table/useBaseTablePlugins.ts +10 -6
- package/src/Table/useTableRowStatus.doc.mjs +30 -0
- package/src/Table/useTableSelection.doc.mjs +65 -14
- package/src/Table/useTableTreeData.doc.mjs +29 -0
- package/src/Table/useTableTreeState.doc.mjs +2 -2
- package/src/TextArea/TextArea.doc.mjs +21 -0
- package/src/TextArea/TextArea.test.tsx +32 -1
- package/src/TextArea/TextArea.tsx +27 -26
- package/src/TextInput/TextInput.doc.mjs +21 -0
- package/src/TextInput/TextInput.test.tsx +150 -0
- package/src/TextInput/TextInput.tsx +28 -25
- package/src/Thumbnail/Thumbnail.doc.mjs +19 -10
- package/src/Thumbnail/Thumbnail.test.tsx +98 -7
- package/src/Thumbnail/Thumbnail.tsx +142 -42
- package/src/Thumbnail/thumbnail.markers.stylex.ts +12 -0
- package/src/TimeInput/TimeInput.doc.mjs +21 -0
- package/src/TimeInput/TimeInput.test.tsx +99 -1
- package/src/TimeInput/TimeInput.tsx +43 -31
- package/src/Timestamp/Timestamp.doc.mjs +4 -4
- package/src/Timestamp/Timestamp.test.tsx +32 -0
- package/src/Timestamp/Timestamp.tsx +28 -8
- package/src/Toast/useToast.tsx +7 -8
- package/src/ToggleButton/ToggleButtonGroup.tsx +1 -1
- package/src/Token/Token.test.tsx +21 -15
- package/src/Token/Token.tsx +31 -14
- package/src/Token/index.ts +1 -1
- package/src/Tokenizer/Tokenizer.doc.mjs +38 -2
- package/src/Tokenizer/Tokenizer.test.tsx +206 -2
- package/src/Tokenizer/Tokenizer.tsx +30 -6
- package/src/Tooltip/Tooltip.test.tsx +46 -0
- package/src/Tooltip/useTooltip.tsx +20 -0
- package/src/TopNav/TopNav.test.tsx +125 -1
- package/src/TopNav/TopNavHeading.tsx +24 -8
- package/src/TopNav/TopNavMegaMenu.test.tsx +149 -1
- package/src/TopNav/TopNavMegaMenu.tsx +10 -4
- package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +3 -3
- package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +19 -2
- package/src/TopNav/TopNavMenu.test.tsx +118 -4
- package/src/TopNav/TopNavMenu.tsx +83 -5
- package/src/TreeList/TreeList.doc.mjs +28 -0
- package/src/TreeList/TreeList.test.tsx +272 -0
- package/src/TreeList/TreeList.tsx +23 -2
- package/src/TreeList/TreeListBranches.tsx +24 -8
- package/src/TreeList/TreeListItem.tsx +84 -22
- package/src/TreeList/TreeListTypes.ts +27 -1
- package/src/TreeList/index.ts +2 -2
- package/src/Typeahead/BaseTypeahead.tsx +30 -15
- package/src/Typeahead/Typeahead.doc.mjs +13 -0
- package/src/Typeahead/Typeahead.test.tsx +50 -0
- package/src/Typeahead/Typeahead.tsx +11 -1
- package/src/Typeahead/TypeaheadItem.tsx +2 -1
- package/src/__tests__/inputWidthContract.test.tsx +62 -0
- package/src/authoring/doc.ts +1 -3
- package/src/doc-mjs.d.ts +19 -0
- package/src/docs-types.ts +5 -0
- package/src/hooks/computeOverflow.test.ts +422 -0
- package/src/hooks/computeOverflow.ts +290 -0
- package/src/hooks/index.ts +8 -0
- package/src/hooks/isRtlElement.ts +27 -0
- package/src/hooks/useDevWarning.test.tsx +45 -0
- package/src/hooks/useDevWarning.ts +54 -0
- package/src/hooks/useGridFocus.doc.mjs +3 -3
- package/src/hooks/useGridFocus.test.tsx +41 -0
- package/src/hooks/useGridFocus.ts +21 -10
- package/src/hooks/useInputStatusIcon.test.tsx +162 -0
- package/src/hooks/useInputStatusIcon.tsx +224 -0
- package/src/hooks/useListFocus.doc.mjs +25 -3
- package/src/hooks/useListFocus.test.tsx +153 -1
- package/src/hooks/useListFocus.ts +102 -9
- package/src/hooks/useOverflow.test.ts +96 -4
- package/src/hooks/useOverflow.ts +74 -33
- package/src/i18n/InternationalizationContext.ts +4 -0
- package/src/i18n/InternationalizationProvider.doc.mjs +99 -2
- package/src/i18n/InternationalizationProvider.tsx +12 -2
- package/src/i18n/__tests__/getLocaleDirection.test.ts +40 -0
- package/src/i18n/__tests__/useDirection.test.tsx +66 -0
- package/src/i18n/getLocaleDirection.ts +29 -0
- package/src/i18n/index.ts +6 -0
- package/src/i18n/resolve.ts +9 -21
- package/src/i18n/useDirection.ts +29 -0
- package/src/reset.css +0 -26
- package/src/reset.test.ts +60 -0
- package/src/theme/Theme.tsx +11 -14
- package/src/theme/derivedVarRegistry.test.ts +1 -0
- package/src/theme/derivedVarRegistry.ts +6 -0
- package/src/theme/generateThemeRules.test.ts +107 -0
- package/src/theme/generateThemeRules.ts +56 -0
- package/src/theme/hct.ts +1 -1
- package/src/theme/syntax/defineSyntaxTheme.ts +5 -6
- package/src/utils/devWarning.test.ts +56 -0
- package/src/utils/devWarning.ts +102 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/plainDate.test.ts +46 -6
- package/src/utils/plainDate.ts +69 -3
- package/src/utils/rtlStyles.ts +27 -0
- package/src/utils/types.ts +14 -0
|
@@ -10,6 +10,7 @@ import type {ReactNode} from 'react';
|
|
|
10
10
|
import * as stylex from '@stylexjs/stylex';
|
|
11
11
|
import {Divider} from '../Divider';
|
|
12
12
|
import {DropdownMenuItem} from './DropdownMenuItem';
|
|
13
|
+
import {DropdownMenuSubMenu} from './DropdownMenuSubMenu';
|
|
13
14
|
import {
|
|
14
15
|
spacingVars,
|
|
15
16
|
typographyVars,
|
|
@@ -49,18 +50,14 @@ function getSectionKey(section: DropdownMenuSection, index: number): string {
|
|
|
49
50
|
* Converts data-driven items into DropdownMenuItem components,
|
|
50
51
|
* so both modes share the same rendering and keyboard navigation path.
|
|
51
52
|
*/
|
|
52
|
-
export function renderDropdownItems(
|
|
53
|
-
items: DropdownMenuOption[],
|
|
54
|
-
): ReactNode {
|
|
53
|
+
export function renderDropdownItems(items: DropdownMenuOption[]): ReactNode {
|
|
55
54
|
const elements: ReactNode[] = [];
|
|
56
55
|
|
|
57
56
|
for (let i = 0; i < items.length; i++) {
|
|
58
57
|
const option = items[i];
|
|
59
58
|
|
|
60
59
|
if ('type' in option && option.type === 'divider') {
|
|
61
|
-
elements.push(
|
|
62
|
-
<Divider key={`divider-${i}`} xstyle={styles.divider} />,
|
|
63
|
-
);
|
|
60
|
+
elements.push(<Divider key={`divider-${i}`} xstyle={styles.divider} />);
|
|
64
61
|
} else if ('type' in option && option.type === 'section') {
|
|
65
62
|
elements.push(
|
|
66
63
|
<div
|
|
@@ -84,15 +81,32 @@ export function renderDropdownItems(
|
|
|
84
81
|
</div>,
|
|
85
82
|
);
|
|
86
83
|
} else if (!('type' in option)) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
84
|
+
// A plain item that declares nested `items` becomes a submenu (data-mode
|
|
85
|
+
// parity with the compound DropdownMenuSubMenu API); otherwise it's a
|
|
86
|
+
// leaf. renderDropdownItems owns the recursion and hands the rendered
|
|
87
|
+
// children to DropdownMenuSubMenu — so DropdownMenuSubMenu never imports
|
|
88
|
+
// this module back (no import cycle).
|
|
89
|
+
if (option.items && option.items.length > 0) {
|
|
90
|
+
elements.push(
|
|
91
|
+
<DropdownMenuSubMenu
|
|
92
|
+
key={getItemKey(option)}
|
|
93
|
+
icon={option.icon}
|
|
94
|
+
label={option.label}
|
|
95
|
+
isDisabled={option.isDisabled}>
|
|
96
|
+
{renderDropdownItems(option.items)}
|
|
97
|
+
</DropdownMenuSubMenu>,
|
|
98
|
+
);
|
|
99
|
+
} else {
|
|
100
|
+
elements.push(
|
|
101
|
+
<DropdownMenuItem
|
|
102
|
+
key={getItemKey(option)}
|
|
103
|
+
icon={option.icon}
|
|
104
|
+
label={option.label}
|
|
105
|
+
onClick={option.onClick}
|
|
106
|
+
isDisabled={option.isDisabled}
|
|
107
|
+
/>,
|
|
108
|
+
);
|
|
109
|
+
}
|
|
96
110
|
}
|
|
97
111
|
}
|
|
98
112
|
|
package/src/Field/Field.test.tsx
CHANGED
|
@@ -9,10 +9,22 @@
|
|
|
9
9
|
* SYNC: When Field.tsx changes, update tests to match new behavior
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {describe, it, expect, vi} from 'vitest';
|
|
13
|
-
import {render, screen} from '@testing-library/react';
|
|
12
|
+
import {describe, it, expect, vi, afterEach} from 'vitest';
|
|
13
|
+
import {render, screen, waitFor} from '@testing-library/react';
|
|
14
14
|
import {Field} from './Field';
|
|
15
15
|
import {FormLayoutContext} from '../FormLayout/FormLayoutContext';
|
|
16
|
+
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
17
|
+
|
|
18
|
+
function politeRegion(): HTMLElement | null {
|
|
19
|
+
return document.querySelector('[data-astryx-live-region="polite"]');
|
|
20
|
+
}
|
|
21
|
+
function assertiveRegion(): HTMLElement | null {
|
|
22
|
+
return document.querySelector('[data-astryx-live-region="assertive"]');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
__resetLiveRegionsForTest();
|
|
27
|
+
});
|
|
16
28
|
|
|
17
29
|
describe('Field', () => {
|
|
18
30
|
it('renders with label', () => {
|
|
@@ -228,7 +240,11 @@ describe('Field', () => {
|
|
|
228
240
|
expect(document.querySelector('svg')).not.toBeInTheDocument();
|
|
229
241
|
});
|
|
230
242
|
|
|
231
|
-
|
|
243
|
+
// The status message is announced through the persistent useAnnounce live
|
|
244
|
+
// regions rather than role/aria-live on the (conditionally mounted)
|
|
245
|
+
// FieldStatus element itself — regions born with their content are not
|
|
246
|
+
// reliably announced by assistive technology.
|
|
247
|
+
it('announces error status assertively via the persistent live region', async () => {
|
|
232
248
|
render(
|
|
233
249
|
<Field
|
|
234
250
|
label="Email"
|
|
@@ -237,12 +253,13 @@ describe('Field', () => {
|
|
|
237
253
|
<input id="email-input" />
|
|
238
254
|
</Field>,
|
|
239
255
|
);
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
256
|
+
expect(screen.getByText('Invalid email')).not.toHaveAttribute('role');
|
|
257
|
+
await waitFor(() => {
|
|
258
|
+
expect(assertiveRegion()).toHaveTextContent('Invalid email');
|
|
259
|
+
});
|
|
243
260
|
});
|
|
244
261
|
|
|
245
|
-
it('
|
|
262
|
+
it('announces warning status politely via the persistent live region', async () => {
|
|
246
263
|
render(
|
|
247
264
|
<Field
|
|
248
265
|
label="Email"
|
|
@@ -251,9 +268,34 @@ describe('Field', () => {
|
|
|
251
268
|
<input id="email-input" />
|
|
252
269
|
</Field>,
|
|
253
270
|
);
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
271
|
+
expect(screen.getByText('Check this')).not.toHaveAttribute('aria-live');
|
|
272
|
+
await waitFor(() => {
|
|
273
|
+
expect(politeRegion()).toHaveTextContent('Check this');
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// Regression: the status live region must NOT be born together with its
|
|
278
|
+
// content. A message that appears after mount (the common validation flow)
|
|
279
|
+
// has to land in the persistent announce region.
|
|
280
|
+
it('announces a status message that appears after mount', async () => {
|
|
281
|
+
const {rerender} = render(
|
|
282
|
+
<Field label="Email" inputID="email-input">
|
|
283
|
+
<input id="email-input" />
|
|
284
|
+
</Field>,
|
|
285
|
+
);
|
|
286
|
+
expect(assertiveRegion()).toBeNull();
|
|
287
|
+
|
|
288
|
+
rerender(
|
|
289
|
+
<Field
|
|
290
|
+
label="Email"
|
|
291
|
+
inputID="email-input"
|
|
292
|
+
status={{type: 'error', message: 'Email is required'}}>
|
|
293
|
+
<input id="email-input" />
|
|
294
|
+
</Field>,
|
|
295
|
+
);
|
|
296
|
+
await waitFor(() => {
|
|
297
|
+
expect(assertiveRegion()).toHaveTextContent('Email is required');
|
|
298
|
+
});
|
|
257
299
|
});
|
|
258
300
|
|
|
259
301
|
it('auto-generates description ID as {inputID}-desc when descriptionID is not provided', () => {
|
|
@@ -277,7 +319,10 @@ describe('Field', () => {
|
|
|
277
319
|
<input id="my-input" />
|
|
278
320
|
</Field>,
|
|
279
321
|
);
|
|
280
|
-
expect(screen.
|
|
322
|
+
expect(screen.getByText('Required')).toHaveAttribute(
|
|
323
|
+
'id',
|
|
324
|
+
'my-input-status',
|
|
325
|
+
);
|
|
281
326
|
});
|
|
282
327
|
|
|
283
328
|
it('warns when isOptional and isRequired are both set', () => {
|
|
@@ -421,7 +466,7 @@ describe('Field', () => {
|
|
|
421
466
|
</Field>,
|
|
422
467
|
{wrapper: horizontalLabelsWrapper},
|
|
423
468
|
);
|
|
424
|
-
const statusEl = screen.
|
|
469
|
+
const statusEl = screen.getByText('Required');
|
|
425
470
|
const inputEl = screen.getByTestId('email');
|
|
426
471
|
// Both status and input should be inside the same wrapper div (column 2)
|
|
427
472
|
expect(statusEl.parentElement).toBe(inputEl.parentElement);
|
package/src/Field/Field.tsx
CHANGED
|
@@ -22,9 +22,11 @@ import type {BaseProps} from '../BaseProps';
|
|
|
22
22
|
import type {SizeValue} from '../utils/types';
|
|
23
23
|
import {FieldLabel} from './FieldLabel';
|
|
24
24
|
import {FieldStatus} from '../FieldStatus/FieldStatus';
|
|
25
|
+
import type {FieldStatusVariant} from '../FieldStatus/FieldStatus';
|
|
25
26
|
import {spacingVars, borderVars} from '../theme/tokens.stylex';
|
|
26
27
|
import type {IconType} from '../Icon';
|
|
27
28
|
import {mergeProps} from '../utils';
|
|
29
|
+
import {useDevWarning} from '../hooks/useDevWarning';
|
|
28
30
|
import {FormLayoutContext} from '../FormLayout/FormLayoutContext';
|
|
29
31
|
import {Text} from '../Text';
|
|
30
32
|
import {themeProps} from '../utils/themeProps';
|
|
@@ -155,9 +157,10 @@ export interface FieldProps extends Omit<
|
|
|
155
157
|
* How the status message is rendered relative to the input.
|
|
156
158
|
* - 'attached': Status sits directly below the input (default, for bordered inputs)
|
|
157
159
|
* - 'detached': Status is a separate element below the field (for checkboxes, switches, sliders)
|
|
160
|
+
* - 'tooltip': No message box; the input surfaces status through a tooltip on its on-field icon
|
|
158
161
|
* @default 'attached'
|
|
159
162
|
*/
|
|
160
|
-
statusVariant?:
|
|
163
|
+
statusVariant?: FieldStatusVariant;
|
|
161
164
|
/**
|
|
162
165
|
* Width of the field. Numbers are treated as pixels, strings are used as-is
|
|
163
166
|
* (e.g. `'100%'`). Sizes the whole field — label, control, and status — so
|
|
@@ -215,11 +218,11 @@ export function Field({
|
|
|
215
218
|
const resolvedMessageID =
|
|
216
219
|
status?.messageID ?? (status?.message ? `${inputID}-status` : undefined);
|
|
217
220
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
221
|
+
useDevWarning(
|
|
222
|
+
'Field',
|
|
223
|
+
'isOptional and isRequired are mutually exclusive. isOptional takes precedence.',
|
|
224
|
+
isOptional && isRequired,
|
|
225
|
+
);
|
|
223
226
|
|
|
224
227
|
const labelNode = (
|
|
225
228
|
<FieldLabel
|
|
@@ -238,14 +241,17 @@ export function Field({
|
|
|
238
241
|
/>
|
|
239
242
|
);
|
|
240
243
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
244
|
+
// The 'tooltip' variant surfaces status through the input's on-field icon
|
|
245
|
+
// tooltip, so Field renders no message box for it.
|
|
246
|
+
const statusNode =
|
|
247
|
+
status?.message && statusVariant !== 'tooltip' ? (
|
|
248
|
+
<FieldStatus
|
|
249
|
+
type={status.type}
|
|
250
|
+
message={status.message}
|
|
251
|
+
id={resolvedMessageID}
|
|
252
|
+
variant={statusVariant}
|
|
253
|
+
/>
|
|
254
|
+
) : null;
|
|
249
255
|
|
|
250
256
|
// ─── Horizontal-labels mode ───────────────────────────────────────────
|
|
251
257
|
// Use display:contents so the parent grid's `auto 1fr` columns place
|
package/src/Field/FieldLabel.tsx
CHANGED
|
@@ -48,7 +48,7 @@ const styles = stylex.create({
|
|
|
48
48
|
borderStyle: 'none',
|
|
49
49
|
clip: 'rect(0, 0, 0, 0)',
|
|
50
50
|
height: 1,
|
|
51
|
-
|
|
51
|
+
insetInlineStart: 0,
|
|
52
52
|
margin: -1,
|
|
53
53
|
overflow: 'hidden',
|
|
54
54
|
padding: 0,
|
|
@@ -171,7 +171,11 @@ export function FieldLabel({
|
|
|
171
171
|
labelTooltip,
|
|
172
172
|
description,
|
|
173
173
|
descriptionID,
|
|
174
|
+
className,
|
|
175
|
+
style,
|
|
176
|
+
xstyle,
|
|
174
177
|
ref,
|
|
178
|
+
...rest
|
|
175
179
|
}: FieldLabelProps) {
|
|
176
180
|
const statusText = isOptional ? 'Optional' : isRequired ? 'Required' : null;
|
|
177
181
|
|
|
@@ -207,13 +211,17 @@ export function FieldLabel({
|
|
|
207
211
|
// `htmlFor` only applies to a real `<label>` associating with a single
|
|
208
212
|
// control; a group label (span) has no `htmlFor`.
|
|
209
213
|
htmlFor={isGroupLabel ? undefined : inputID}
|
|
214
|
+
{...rest}
|
|
210
215
|
{...mergeProps(
|
|
211
216
|
themeProps('field-label'),
|
|
212
217
|
stylex.props(
|
|
213
218
|
styles.label,
|
|
214
219
|
isDisabled && styles.labelDisabled,
|
|
215
220
|
isLabelHidden && styles.srOnly,
|
|
221
|
+
xstyle,
|
|
216
222
|
),
|
|
223
|
+
className,
|
|
224
|
+
style,
|
|
217
225
|
)}>
|
|
218
226
|
{labelContent}
|
|
219
227
|
</LabelElement>
|
|
@@ -67,6 +67,8 @@ export const inputWrapperStyles = stylex.create({
|
|
|
67
67
|
cursor: 'not-allowed',
|
|
68
68
|
opacity: 0.5,
|
|
69
69
|
borderColor: colorVars['--color-border-emphasized'],
|
|
70
|
+
// Suppress the base hover ring — a disabled control must not react to hover.
|
|
71
|
+
boxShadow: 'none',
|
|
70
72
|
},
|
|
71
73
|
});
|
|
72
74
|
|
|
@@ -8,7 +8,7 @@ export const docs = {
|
|
|
8
8
|
category: 'Data Input',
|
|
9
9
|
isHiddenFromOverview: true,
|
|
10
10
|
description:
|
|
11
|
-
'Status message component for form field validation feedback.',
|
|
11
|
+
'Status message component for form field validation feedback. Messages are announced to screen readers through persistent live regions (assertive for errors, polite otherwise), so conditional mounting is safe.',
|
|
12
12
|
theming: {
|
|
13
13
|
targets: [
|
|
14
14
|
{className: 'astryx-field-status', visualProps: ['type', 'variant']},
|
|
@@ -66,12 +66,24 @@ export const docs = {
|
|
|
66
66
|
/** @type {import('../docs-types').TranslationDoc} */
|
|
67
67
|
export const docsDense = {
|
|
68
68
|
description:
|
|
69
|
-
'Validation feedback message for fields/custom controls. Supports error, warning, success and attached/detached variants.',
|
|
69
|
+
'Validation feedback message for fields/custom controls. Supports error, warning, success and attached/detached variants. Announced via persistent live regions (assertive for errors, polite otherwise).',
|
|
70
70
|
usage: {
|
|
71
71
|
bestPractices: [
|
|
72
|
-
{
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
{
|
|
73
|
+
guidance: true,
|
|
74
|
+
description:
|
|
75
|
+
'Use attached status below bordered inputs when message belongs to that input.',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
guidance: true,
|
|
79
|
+
description:
|
|
80
|
+
'Use detached status for checkboxes, switches, and custom controls where overlap is visually awkward.',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
guidance: false,
|
|
84
|
+
description:
|
|
85
|
+
'Use FieldStatus for general alerts or page-level notices; use Banner or Toast instead.',
|
|
86
|
+
},
|
|
75
87
|
],
|
|
76
88
|
},
|
|
77
89
|
propDescriptions: {
|
|
@@ -9,15 +9,27 @@
|
|
|
9
9
|
* SYNC: When FieldStatus.tsx changes, update tests to match new behavior
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {describe, it, expect, vi} from 'vitest';
|
|
13
|
-
import {render, screen} from '@testing-library/react';
|
|
12
|
+
import {describe, it, expect, vi, afterEach} from 'vitest';
|
|
13
|
+
import {render, screen, waitFor} from '@testing-library/react';
|
|
14
14
|
import * as stylex from '@stylexjs/stylex';
|
|
15
15
|
import {FieldStatus} from './FieldStatus';
|
|
16
|
+
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
16
17
|
|
|
17
18
|
const testStyles = stylex.create({
|
|
18
19
|
custom: {color: 'rebeccapurple'},
|
|
19
20
|
});
|
|
20
21
|
|
|
22
|
+
function politeRegion(): HTMLElement | null {
|
|
23
|
+
return document.querySelector('[data-astryx-live-region="polite"]');
|
|
24
|
+
}
|
|
25
|
+
function assertiveRegion(): HTMLElement | null {
|
|
26
|
+
return document.querySelector('[data-astryx-live-region="assertive"]');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
__resetLiveRegionsForTest();
|
|
31
|
+
});
|
|
32
|
+
|
|
21
33
|
describe('FieldStatus', () => {
|
|
22
34
|
it('renders the message text', () => {
|
|
23
35
|
render(<FieldStatus type="error" message="This field is required" />);
|
|
@@ -29,47 +41,75 @@ describe('FieldStatus', () => {
|
|
|
29
41
|
expect(screen.getByTestId('fs').tagName).toBe('DIV');
|
|
30
42
|
});
|
|
31
43
|
|
|
32
|
-
describe('
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
44
|
+
describe('screen-reader announcements', () => {
|
|
45
|
+
// The rendered element is NOT itself a live region: FieldStatus is
|
|
46
|
+
// conditionally mounted by every caller, and live regions born together
|
|
47
|
+
// with their content are not reliably announced. Announcements go through
|
|
48
|
+
// the persistent useAnnounce singletons instead.
|
|
49
|
+
it('does not carry role or aria-live on the rendered element', () => {
|
|
50
|
+
render(<FieldStatus type="error" message="msg" data-testid="fs" />);
|
|
51
|
+
const el = screen.getByTestId('fs');
|
|
52
|
+
expect(el).not.toHaveAttribute('role');
|
|
53
|
+
expect(el).not.toHaveAttribute('aria-live');
|
|
37
54
|
});
|
|
38
55
|
|
|
39
|
-
//
|
|
40
|
-
it('
|
|
41
|
-
render(<FieldStatus type="
|
|
42
|
-
|
|
43
|
-
|
|
56
|
+
// Errors are urgent — they interrupt via the assertive channel.
|
|
57
|
+
it('announces error messages assertively, including on first mount', async () => {
|
|
58
|
+
render(<FieldStatus type="error" message="This field is required" />);
|
|
59
|
+
await waitFor(() => {
|
|
60
|
+
expect(assertiveRegion()).toHaveTextContent('This field is required');
|
|
61
|
+
});
|
|
62
|
+
expect(politeRegion()).toHaveTextContent('');
|
|
44
63
|
});
|
|
45
64
|
|
|
46
|
-
it('
|
|
47
|
-
render(<FieldStatus type="
|
|
48
|
-
|
|
65
|
+
it('announces warning messages politely', async () => {
|
|
66
|
+
render(<FieldStatus type="warning" message="Check this value" />);
|
|
67
|
+
await waitFor(() => {
|
|
68
|
+
expect(politeRegion()).toHaveTextContent('Check this value');
|
|
69
|
+
});
|
|
70
|
+
expect(assertiveRegion()).toHaveTextContent('');
|
|
49
71
|
});
|
|
50
|
-
});
|
|
51
72
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
'aria-live',
|
|
58
|
-
'assertive',
|
|
59
|
-
);
|
|
73
|
+
it('announces success messages politely', async () => {
|
|
74
|
+
render(<FieldStatus type="success" message="Looks good" />);
|
|
75
|
+
await waitFor(() => {
|
|
76
|
+
expect(politeRegion()).toHaveTextContent('Looks good');
|
|
77
|
+
});
|
|
60
78
|
});
|
|
61
79
|
|
|
62
|
-
it('
|
|
63
|
-
render(<FieldStatus type="
|
|
64
|
-
|
|
80
|
+
it('announces message changes', async () => {
|
|
81
|
+
const {rerender} = render(<FieldStatus type="error" message="First" />);
|
|
82
|
+
await waitFor(() => {
|
|
83
|
+
expect(assertiveRegion()).toHaveTextContent('First');
|
|
84
|
+
});
|
|
85
|
+
rerender(<FieldStatus type="error" message="Second" />);
|
|
86
|
+
await waitFor(() => {
|
|
87
|
+
expect(assertiveRegion()).toHaveTextContent('Second');
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Severity changes re-route the announcement to the matching channel.
|
|
92
|
+
it('re-routes to the polite channel when type changes from error', async () => {
|
|
93
|
+
const {rerender} = render(<FieldStatus type="error" message="msg" />);
|
|
94
|
+
await waitFor(() => {
|
|
95
|
+
expect(assertiveRegion()).toHaveTextContent('msg');
|
|
96
|
+
});
|
|
97
|
+
rerender(<FieldStatus type="success" message="msg" />);
|
|
98
|
+
await waitFor(() => {
|
|
99
|
+
expect(politeRegion()).toHaveTextContent('msg');
|
|
100
|
+
});
|
|
65
101
|
});
|
|
66
102
|
|
|
67
|
-
it('
|
|
68
|
-
render(<FieldStatus type="
|
|
69
|
-
|
|
103
|
+
it('does not announce an empty message', () => {
|
|
104
|
+
render(<FieldStatus type="error" message="" />);
|
|
105
|
+
// The live regions are created lazily on first announce; an empty
|
|
106
|
+
// message must not trigger one.
|
|
107
|
+
expect(assertiveRegion()).toBeNull();
|
|
108
|
+
expect(politeRegion()).toBeNull();
|
|
70
109
|
});
|
|
71
110
|
|
|
72
|
-
// The
|
|
111
|
+
// The visible message stays perceivable by assistive tech (it is the
|
|
112
|
+
// aria-describedby target for the input).
|
|
73
113
|
it('does not mark itself aria-hidden', () => {
|
|
74
114
|
render(<FieldStatus type="error" message="msg" data-testid="fs" />);
|
|
75
115
|
expect(screen.getByTestId('fs')).not.toHaveAttribute('aria-hidden');
|
|
@@ -245,20 +285,90 @@ describe('FieldStatus', () => {
|
|
|
245
285
|
expect(screen.getByTestId('fs')).toHaveTextContent('Second');
|
|
246
286
|
});
|
|
247
287
|
|
|
248
|
-
//
|
|
249
|
-
//
|
|
250
|
-
it('
|
|
288
|
+
// The element must never regain live-region semantics when the type
|
|
289
|
+
// changes — announcements always flow through the persistent regions.
|
|
290
|
+
it('keeps the element role-free when type changes from error', () => {
|
|
251
291
|
const {rerender} = render(
|
|
252
292
|
<FieldStatus type="error" message="msg" data-testid="fs" />,
|
|
253
293
|
);
|
|
254
|
-
|
|
255
|
-
expect(el).toHaveAttribute('role', 'alert');
|
|
256
|
-
expect(el).toHaveAttribute('aria-live', 'assertive');
|
|
294
|
+
expect(screen.getByTestId('fs')).not.toHaveAttribute('role');
|
|
257
295
|
|
|
258
296
|
rerender(<FieldStatus type="success" message="msg" data-testid="fs" />);
|
|
259
|
-
el = screen.getByTestId('fs');
|
|
260
|
-
expect(el).toHaveAttribute('role'
|
|
261
|
-
expect(el).toHaveAttribute('aria-live'
|
|
297
|
+
const el = screen.getByTestId('fs');
|
|
298
|
+
expect(el).not.toHaveAttribute('role');
|
|
299
|
+
expect(el).not.toHaveAttribute('aria-live');
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// The detached message must convey status by more than color/position:
|
|
304
|
+
// a leading status glyph precedes the message text (WCAG 1.4.1). The glyph
|
|
305
|
+
// is decorative for AT (aria-hidden) because the message text already names
|
|
306
|
+
// the status in words and it is announced via the live region.
|
|
307
|
+
describe('detached leading status icon (use-of-color a11y)', () => {
|
|
308
|
+
it('renders a leading status icon before the message for the detached variant', () => {
|
|
309
|
+
render(
|
|
310
|
+
<FieldStatus
|
|
311
|
+
type="error"
|
|
312
|
+
message="Something went wrong"
|
|
313
|
+
variant="detached"
|
|
314
|
+
data-testid="fs"
|
|
315
|
+
/>,
|
|
316
|
+
);
|
|
317
|
+
const el = screen.getByTestId('fs');
|
|
318
|
+
const icon = el.querySelector('[aria-hidden="true"]');
|
|
319
|
+
const text = screen.getByText('Something went wrong');
|
|
320
|
+
expect(icon).toBeInTheDocument();
|
|
321
|
+
// Icon comes before the message text in document order.
|
|
322
|
+
expect(
|
|
323
|
+
icon!.compareDocumentPosition(text) & Node.DOCUMENT_POSITION_FOLLOWING,
|
|
324
|
+
).toBeTruthy();
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it('marks the status icon aria-hidden (visual redundancy, not a second announcement)', () => {
|
|
328
|
+
render(
|
|
329
|
+
<FieldStatus
|
|
330
|
+
type="warning"
|
|
331
|
+
message="Heads up"
|
|
332
|
+
variant="detached"
|
|
333
|
+
data-testid="fs"
|
|
334
|
+
/>,
|
|
335
|
+
);
|
|
336
|
+
const icon = screen
|
|
337
|
+
.getByTestId('fs')
|
|
338
|
+
.querySelector('[aria-hidden="true"]');
|
|
339
|
+
expect(icon).toBeInTheDocument();
|
|
340
|
+
expect(icon).toHaveAttribute('aria-hidden', 'true');
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
it('renders a status icon for each status type in the detached variant', () => {
|
|
344
|
+
for (const type of ['error', 'warning', 'success'] as const) {
|
|
345
|
+
const {unmount} = render(
|
|
346
|
+
<FieldStatus
|
|
347
|
+
type={type}
|
|
348
|
+
message="msg"
|
|
349
|
+
variant="detached"
|
|
350
|
+
data-testid="fs"
|
|
351
|
+
/>,
|
|
352
|
+
);
|
|
353
|
+
expect(
|
|
354
|
+
screen.getByTestId('fs').querySelector('[aria-hidden="true"]'),
|
|
355
|
+
).toBeInTheDocument();
|
|
356
|
+
unmount();
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
it('does not render a leading status icon for the attached variant', () => {
|
|
361
|
+
render(
|
|
362
|
+
<FieldStatus
|
|
363
|
+
type="error"
|
|
364
|
+
message="msg"
|
|
365
|
+
variant="attached"
|
|
366
|
+
data-testid="fs"
|
|
367
|
+
/>,
|
|
368
|
+
);
|
|
369
|
+
expect(
|
|
370
|
+
screen.getByTestId('fs').querySelector('[aria-hidden="true"]'),
|
|
371
|
+
).toBeNull();
|
|
262
372
|
});
|
|
263
373
|
});
|
|
264
374
|
|