@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
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file Tokenizer.tsx
|
|
7
|
-
* @input Uses React, BaseTypeahead, Field, Token
|
|
7
|
+
* @input Uses React, BaseTypeahead, Field, Token, useAnnounce
|
|
8
8
|
* @output Exports Tokenizer multi-select typeahead component
|
|
9
9
|
* @position Composed component; forwards DOM ref and exposes focus control via
|
|
10
10
|
* handleRef
|
|
@@ -37,12 +37,14 @@ import {
|
|
|
37
37
|
inputStatusBorderStyles,
|
|
38
38
|
inputStatusHoverShadowStyles,
|
|
39
39
|
inputStatusFocusWithinStyles,
|
|
40
|
+
type FieldStatusVariant,
|
|
40
41
|
} from '../Field';
|
|
41
42
|
import {Token} from '../Token';
|
|
42
43
|
import {renderIconSlot, type IconType} from '../Icon';
|
|
43
44
|
import {OverflowList} from '../OverflowList';
|
|
44
45
|
import {useLayer} from '../Layer/useLayer';
|
|
45
46
|
import {useTooltip} from '../Tooltip';
|
|
47
|
+
import {useAnnounce} from '../hooks/useAnnounce';
|
|
46
48
|
import {
|
|
47
49
|
colorVars,
|
|
48
50
|
spacingVars,
|
|
@@ -110,6 +112,13 @@ export interface TokenizerProps<T extends SearchableItem> extends Omit<
|
|
|
110
112
|
isOptional?: boolean;
|
|
111
113
|
/** Validation status. */
|
|
112
114
|
status?: InputStatus;
|
|
115
|
+
/**
|
|
116
|
+
* How the status message is placed relative to the input.
|
|
117
|
+
* - 'attached': message overlaps directly below the input (bordered treatment)
|
|
118
|
+
* - 'detached': message floats below as a separate element with spacing
|
|
119
|
+
* @default 'attached'
|
|
120
|
+
*/
|
|
121
|
+
statusVariant?: FieldStatusVariant;
|
|
113
122
|
/**
|
|
114
123
|
* Icon to display at the start of the input.
|
|
115
124
|
* Accepts a ReactNode (e.g. `<Icon icon={SearchIcon} />`) or an SVG icon component directly.
|
|
@@ -369,6 +378,7 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
369
378
|
isRequired = false,
|
|
370
379
|
isOptional = false,
|
|
371
380
|
status,
|
|
381
|
+
statusVariant = 'attached',
|
|
372
382
|
startIcon,
|
|
373
383
|
labelTooltip,
|
|
374
384
|
searchSource,
|
|
@@ -560,6 +570,12 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
560
570
|
[],
|
|
561
571
|
);
|
|
562
572
|
|
|
573
|
+
// Announce token add/remove politely via the persistent live region.
|
|
574
|
+
// Tokens previously appeared and disappeared silently — Backspace on an
|
|
575
|
+
// empty input removes the trailing token, and the per-token remove buttons
|
|
576
|
+
// gave no audible feedback either.
|
|
577
|
+
const announce = useAnnounce();
|
|
578
|
+
|
|
563
579
|
// Handle adding an item — detect creatable synthetic items
|
|
564
580
|
const handleAdd = useCallback(
|
|
565
581
|
(item: T | null) => {
|
|
@@ -584,6 +600,7 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
584
600
|
const realItem = base as T;
|
|
585
601
|
const newItems = [...value, realItem];
|
|
586
602
|
onChange(newItems, {item: realItem, type: 'create'});
|
|
603
|
+
announce(`Added ${createdValue}`);
|
|
587
604
|
return;
|
|
588
605
|
}
|
|
589
606
|
|
|
@@ -592,18 +609,22 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
592
609
|
}
|
|
593
610
|
const newItems = [...value, item];
|
|
594
611
|
onChange(newItems, {item, type: 'add'});
|
|
612
|
+
announce(`Added ${item.label}`);
|
|
595
613
|
},
|
|
596
|
-
[value, onChange, isAtMax, selectedIds, hasCreate],
|
|
614
|
+
[value, onChange, isAtMax, selectedIds, hasCreate, announce],
|
|
597
615
|
);
|
|
598
616
|
|
|
599
|
-
// Handle removing an item
|
|
617
|
+
// Handle removing an item. Single removal path: both Backspace on an empty
|
|
618
|
+
// input and the per-token remove buttons route through here, so the
|
|
619
|
+
// announcement covers both.
|
|
600
620
|
const handleRemove = useCallback(
|
|
601
621
|
(item: T) => {
|
|
602
622
|
const newItems = value.filter(v => v.id !== item.id);
|
|
603
623
|
onChange(newItems, {item, type: 'remove'});
|
|
624
|
+
announce(`Removed ${item.label}`);
|
|
604
625
|
inputRef.current?.focus();
|
|
605
626
|
},
|
|
606
|
-
[value, onChange],
|
|
627
|
+
[value, onChange, announce],
|
|
607
628
|
);
|
|
608
629
|
|
|
609
630
|
// Handle clearing all items
|
|
@@ -718,7 +739,7 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
718
739
|
isTruncated && styles.truncatedWrapper,
|
|
719
740
|
isDisabled && inputWrapperStyles.disabled,
|
|
720
741
|
status && inputStatusBorderStyles[status.type],
|
|
721
|
-
status && inputStatusHoverShadowStyles[status.type],
|
|
742
|
+
status && !isDisabled && inputStatusHoverShadowStyles[status.type],
|
|
722
743
|
status && inputStatusFocusWithinStyles[status.type],
|
|
723
744
|
),
|
|
724
745
|
)}>
|
|
@@ -816,7 +837,9 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
816
837
|
isTruncated && styles.truncatedWrapper,
|
|
817
838
|
isDisabled && inputWrapperStyles.disabled,
|
|
818
839
|
status && inputStatusBorderStyles[status.type],
|
|
819
|
-
status &&
|
|
840
|
+
status &&
|
|
841
|
+
!isDisabled &&
|
|
842
|
+
inputStatusHoverShadowStyles[status.type],
|
|
820
843
|
status && inputStatusFocusWithinStyles[status.type],
|
|
821
844
|
),
|
|
822
845
|
)}>
|
|
@@ -879,6 +902,7 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
879
902
|
}
|
|
880
903
|
: undefined
|
|
881
904
|
}
|
|
905
|
+
statusVariant={statusVariant}
|
|
882
906
|
labelTooltip={labelTooltip}
|
|
883
907
|
width={width}
|
|
884
908
|
xstyle={xstyle}
|
|
@@ -221,4 +221,50 @@ describe('Tooltip', () => {
|
|
|
221
221
|
expect(onOpenChange).not.toHaveBeenCalledWith(false);
|
|
222
222
|
});
|
|
223
223
|
});
|
|
224
|
+
|
|
225
|
+
describe('press-to-dismiss', () => {
|
|
226
|
+
it('hides the tooltip when the trigger is pressed', async () => {
|
|
227
|
+
const onOpenChange = vi.fn();
|
|
228
|
+
render(
|
|
229
|
+
<Tooltip content="Copy link" onOpenChange={onOpenChange} delay={0}>
|
|
230
|
+
<button type="button">Trigger</button>
|
|
231
|
+
</Tooltip>,
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
const trigger = screen.getByRole('button', {name: 'Trigger'});
|
|
235
|
+
fireEvent.mouseEnter(trigger);
|
|
236
|
+
await waitFor(() => {
|
|
237
|
+
expect(onOpenChange).toHaveBeenCalledWith(true);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
fireEvent.pointerDown(trigger);
|
|
241
|
+
await waitFor(() => {
|
|
242
|
+
expect(onOpenChange).toHaveBeenCalledWith(false);
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('does not press-dismiss a controlled tooltip', async () => {
|
|
247
|
+
const onOpenChange = vi.fn();
|
|
248
|
+
render(
|
|
249
|
+
<Tooltip
|
|
250
|
+
content="Controlled"
|
|
251
|
+
isOpen
|
|
252
|
+
onOpenChange={onOpenChange}
|
|
253
|
+
delay={0}>
|
|
254
|
+
<button type="button">Trigger</button>
|
|
255
|
+
</Tooltip>,
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
const trigger = screen.getByRole('button', {name: 'Trigger'});
|
|
259
|
+
await waitFor(() => {
|
|
260
|
+
expect(onOpenChange).toHaveBeenCalledWith(true);
|
|
261
|
+
});
|
|
262
|
+
onOpenChange.mockClear();
|
|
263
|
+
|
|
264
|
+
fireEvent.pointerDown(trigger);
|
|
265
|
+
// Give any (incorrect) async hide a chance to run.
|
|
266
|
+
await new Promise(r => setTimeout(r, 20));
|
|
267
|
+
expect(onOpenChange).not.toHaveBeenCalledWith(false);
|
|
268
|
+
});
|
|
269
|
+
});
|
|
224
270
|
});
|
|
@@ -366,6 +366,19 @@ export function useTooltip(options: TooltipOptions = {}): TooltipReturn {
|
|
|
366
366
|
scheduleHide();
|
|
367
367
|
}, [scheduleHide]);
|
|
368
368
|
|
|
369
|
+
// Pressing the trigger hides its own tooltip: once the control is activated
|
|
370
|
+
// the hint has served its purpose, and a tooltip lingering over a
|
|
371
|
+
// just-pressed control reads as stale. Fires on pointerdown so it feels
|
|
372
|
+
// immediate. Uncontrolled tooltips only — a controlled tooltip's visibility
|
|
373
|
+
// is owned by the consumer. `layer.hide()` self-guards when already closed.
|
|
374
|
+
const handlePointerDown = useCallback(() => {
|
|
375
|
+
if (isOpen !== undefined) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
clearTimeouts();
|
|
379
|
+
layer.hide();
|
|
380
|
+
}, [isOpen, clearTimeouts, layer]);
|
|
381
|
+
|
|
369
382
|
// Interaction ref that handles event listeners only
|
|
370
383
|
const interactionRef: RefCallback<HTMLElement> = useCallback(
|
|
371
384
|
(el: HTMLElement | null) => {
|
|
@@ -375,12 +388,18 @@ export function useTooltip(options: TooltipOptions = {}): TooltipReturn {
|
|
|
375
388
|
triggerRef.current.removeEventListener('mouseleave', handleMouseLeave);
|
|
376
389
|
triggerRef.current.removeEventListener('focusin', handleFocusIn);
|
|
377
390
|
triggerRef.current.removeEventListener('focusout', handleFocusOut);
|
|
391
|
+
triggerRef.current.removeEventListener(
|
|
392
|
+
'pointerdown',
|
|
393
|
+
handlePointerDown,
|
|
394
|
+
);
|
|
378
395
|
}
|
|
379
396
|
|
|
380
397
|
if (el) {
|
|
381
398
|
// Attach hover listeners
|
|
382
399
|
el.addEventListener('mouseenter', handleMouseEnter);
|
|
383
400
|
el.addEventListener('mouseleave', handleMouseLeave);
|
|
401
|
+
// Press-to-dismiss: activating the trigger hides its own tooltip.
|
|
402
|
+
el.addEventListener('pointerdown', handlePointerDown);
|
|
384
403
|
|
|
385
404
|
// Attach focus listeners based on focusTrigger option
|
|
386
405
|
const shouldAttachFocus =
|
|
@@ -401,6 +420,7 @@ export function useTooltip(options: TooltipOptions = {}): TooltipReturn {
|
|
|
401
420
|
handleMouseLeave,
|
|
402
421
|
handleFocusIn,
|
|
403
422
|
handleFocusOut,
|
|
423
|
+
handlePointerDown,
|
|
404
424
|
],
|
|
405
425
|
);
|
|
406
426
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import {describe, it, expect, vi} from 'vitest';
|
|
13
|
-
import {render, screen} from '@testing-library/react';
|
|
13
|
+
import {fireEvent, render, screen} from '@testing-library/react';
|
|
14
14
|
import userEvent from '@testing-library/user-event';
|
|
15
15
|
import {TopNav} from './TopNav';
|
|
16
16
|
import {TopNavRenderContext} from './TopNavRenderContext';
|
|
@@ -297,6 +297,85 @@ describe('TopNavHeading', () => {
|
|
|
297
297
|
render(<TopNavHeading heading="Test" ref={ref} />);
|
|
298
298
|
expect(ref).toHaveBeenCalledWith(expect.any(HTMLElement));
|
|
299
299
|
});
|
|
300
|
+
|
|
301
|
+
// ===========================================================================
|
|
302
|
+
// Menu popover semantics — the popup must not be announced as a modal
|
|
303
|
+
// dialog, and role="menu" must be scoped to the actual menu items so the
|
|
304
|
+
// heading button is not an invalid child of the menu.
|
|
305
|
+
// ===========================================================================
|
|
306
|
+
|
|
307
|
+
// The popover layer keeps `popover` content display:none in jsdom even
|
|
308
|
+
// when open, hiding it from role queries — so these tests assert the
|
|
309
|
+
// popup's ARIA semantics at the DOM level instead.
|
|
310
|
+
describe('menu popover semantics', () => {
|
|
311
|
+
const menuItems = (
|
|
312
|
+
<>
|
|
313
|
+
<div role="menuitem">Alpha</div>
|
|
314
|
+
<div role="menuitem">Beta</div>
|
|
315
|
+
</>
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
it('does not wrap the heading menu popup in a modal dialog', async () => {
|
|
319
|
+
const user = userEvent.setup();
|
|
320
|
+
render(<TopNavHeading heading="My App" menu={menuItems} />);
|
|
321
|
+
await user.click(screen.getByRole('button', {name: 'Open menu'}));
|
|
322
|
+
expect(document.querySelector('[role="dialog"]')).toBeNull();
|
|
323
|
+
expect(document.querySelector('[aria-modal="true"]')).toBeNull();
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
it('scopes role="menu" to only menuitem children with an accessible name', async () => {
|
|
327
|
+
const user = userEvent.setup();
|
|
328
|
+
render(<TopNavHeading heading="My App" menu={menuItems} />);
|
|
329
|
+
await user.click(screen.getByRole('button', {name: 'Open menu'}));
|
|
330
|
+
const menu = document.querySelector('[role="menu"]');
|
|
331
|
+
expect(menu).not.toBeNull();
|
|
332
|
+
expect(menu).toHaveAttribute('aria-label', 'My App');
|
|
333
|
+
const children = Array.from(menu!.children);
|
|
334
|
+
expect(children.length).toBeGreaterThan(0);
|
|
335
|
+
for (const child of children) {
|
|
336
|
+
expect(child).toHaveAttribute('role', 'menuitem');
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it('keeps the popup heading button outside the menu and closes on click', async () => {
|
|
341
|
+
const user = userEvent.setup();
|
|
342
|
+
render(<TopNavHeading heading="My App" menu={menuItems} />);
|
|
343
|
+
const trigger = screen.getByRole('button', {name: 'Open menu'});
|
|
344
|
+
await user.click(trigger);
|
|
345
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
346
|
+
const menu = document.querySelector('[role="menu"]');
|
|
347
|
+
expect(menu).not.toBeNull();
|
|
348
|
+
// The heading replica button in the popup is a sibling of the menu,
|
|
349
|
+
// not an invalid menu child.
|
|
350
|
+
const headingButton = Array.from(
|
|
351
|
+
document.querySelectorAll('button'),
|
|
352
|
+
).find(b => b !== trigger && b.textContent?.includes('My App'));
|
|
353
|
+
expect(headingButton).toBeDefined();
|
|
354
|
+
expect(menu!.contains(headingButton!)).toBe(false);
|
|
355
|
+
// Clicking it still closes the popup.
|
|
356
|
+
fireEvent.click(headingButton!);
|
|
357
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
it('applies the same semantics in mixed mode (menu + hrefs)', async () => {
|
|
361
|
+
const user = userEvent.setup();
|
|
362
|
+
render(
|
|
363
|
+
<TopNavHeading
|
|
364
|
+
heading="Product"
|
|
365
|
+
headingHref="/product"
|
|
366
|
+
menu={menuItems}
|
|
367
|
+
/>,
|
|
368
|
+
);
|
|
369
|
+
await user.click(screen.getByRole('button', {name: 'Open menu'}));
|
|
370
|
+
expect(document.querySelector('[role="dialog"]')).toBeNull();
|
|
371
|
+
const menu = document.querySelector('[role="menu"]');
|
|
372
|
+
expect(menu).not.toBeNull();
|
|
373
|
+
expect(menu).toHaveAttribute('aria-label', 'Product');
|
|
374
|
+
for (const child of Array.from(menu!.children)) {
|
|
375
|
+
expect(child).toHaveAttribute('role', 'menuitem');
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
});
|
|
300
379
|
});
|
|
301
380
|
|
|
302
381
|
describe('NavIcon', () => {
|
|
@@ -444,4 +523,49 @@ describe('TopNavItem', () => {
|
|
|
444
523
|
expect(card).toHaveAttribute('aria-label', 'Featured');
|
|
445
524
|
});
|
|
446
525
|
});
|
|
526
|
+
|
|
527
|
+
describe('TopNavMegaMenuFeaturedCard image alt handling', () => {
|
|
528
|
+
it('marks the image as explicitly decorative when imageAlt is omitted', () => {
|
|
529
|
+
render(
|
|
530
|
+
<TopNavMegaMenuFeaturedCard
|
|
531
|
+
title="What's new"
|
|
532
|
+
image="/promo.jpg"
|
|
533
|
+
data-testid="featured-card"
|
|
534
|
+
/>,
|
|
535
|
+
);
|
|
536
|
+
const img = screen.getByTestId('featured-card').querySelector('img');
|
|
537
|
+
expect(img).toHaveAttribute('alt', '');
|
|
538
|
+
expect(img).toHaveAttribute('role', 'presentation');
|
|
539
|
+
expect(img).toHaveAttribute('aria-hidden', 'true');
|
|
540
|
+
// The image must not be exposed to assistive technology as a nameless img.
|
|
541
|
+
expect(screen.queryByRole('img')).toBeNull();
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
it('exposes the image with normal img semantics when imageAlt is provided', () => {
|
|
545
|
+
render(
|
|
546
|
+
<TopNavMegaMenuFeaturedCard
|
|
547
|
+
title="What's new"
|
|
548
|
+
image="/promo.jpg"
|
|
549
|
+
imageAlt="Team collaboration"
|
|
550
|
+
/>,
|
|
551
|
+
);
|
|
552
|
+
const img = screen.getByRole('img', {name: 'Team collaboration'});
|
|
553
|
+
expect(img).not.toHaveAttribute('role');
|
|
554
|
+
expect(img).not.toHaveAttribute('aria-hidden');
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
it('keeps title and link semantics unchanged with a decorative image', () => {
|
|
558
|
+
render(
|
|
559
|
+
<TopNavMegaMenuFeaturedCard
|
|
560
|
+
title="What's new"
|
|
561
|
+
image="/promo.jpg"
|
|
562
|
+
linkLabel="Read the announcement"
|
|
563
|
+
linkHref="/blog/v4"
|
|
564
|
+
/>,
|
|
565
|
+
);
|
|
566
|
+
expect(screen.getByText("What's new")).toBeInTheDocument();
|
|
567
|
+
const link = screen.getByRole('link', {name: /Read the announcement/});
|
|
568
|
+
expect(link).toHaveAttribute('href', '/blog/v4');
|
|
569
|
+
});
|
|
570
|
+
});
|
|
447
571
|
});
|
|
@@ -332,6 +332,10 @@ export function TopNavHeading({
|
|
|
332
332
|
|
|
333
333
|
const popover = usePopover({
|
|
334
334
|
dialogLabel: t('@astryx.topNav.heading.dialogLabel'),
|
|
335
|
+
// The popup exposes its own role="menu" semantics; a role="dialog"
|
|
336
|
+
// aria-modal wrapper would announce "dialog, Navigation menu" around a
|
|
337
|
+
// menu (the anti-pattern removed in a478a3dcf).
|
|
338
|
+
role: 'none',
|
|
335
339
|
hasCloseButton: false,
|
|
336
340
|
});
|
|
337
341
|
|
|
@@ -511,13 +515,19 @@ export function TopNavHeading({
|
|
|
511
515
|
{popover.render(
|
|
512
516
|
<div
|
|
513
517
|
ref={menuRef}
|
|
514
|
-
role="menu"
|
|
515
518
|
{...stylex.props(styles.popoverContent)}
|
|
516
519
|
{...contentProps}>
|
|
517
520
|
{popoverHeadingContent}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
+
{/* The menu role is scoped to the actual menu items so the
|
|
522
|
+
heading button above stays a valid sibling, not an invalid
|
|
523
|
+
child of a role="menu" element. */}
|
|
524
|
+
<div
|
|
525
|
+
role="menu"
|
|
526
|
+
aria-label={heading ?? t('@astryx.topNav.heading.dialogLabel')}>
|
|
527
|
+
<NavHeadingCloseContext value={closeMenuCtx}>
|
|
528
|
+
{menu}
|
|
529
|
+
</NavHeadingCloseContext>
|
|
530
|
+
</div>
|
|
521
531
|
</div>,
|
|
522
532
|
{
|
|
523
533
|
placement: 'below',
|
|
@@ -575,13 +585,19 @@ export function TopNavHeading({
|
|
|
575
585
|
{popover.render(
|
|
576
586
|
<div
|
|
577
587
|
ref={menuRef}
|
|
578
|
-
role="menu"
|
|
579
588
|
{...stylex.props(styles.popoverContent)}
|
|
580
589
|
{...contentProps}>
|
|
581
590
|
{popoverHeadingContent}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
591
|
+
{/* The menu role is scoped to the actual menu items so the
|
|
592
|
+
heading button above stays a valid sibling, not an invalid
|
|
593
|
+
child of a role="menu" element. */}
|
|
594
|
+
<div
|
|
595
|
+
role="menu"
|
|
596
|
+
aria-label={heading ?? t('@astryx.topNav.heading.dialogLabel')}>
|
|
597
|
+
<NavHeadingCloseContext value={closeMenuCtx}>
|
|
598
|
+
{menu}
|
|
599
|
+
</NavHeadingCloseContext>
|
|
600
|
+
</div>
|
|
585
601
|
</div>,
|
|
586
602
|
{
|
|
587
603
|
placement: 'below',
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* SYNC: When TopNavMegaMenu changes, update tests to match new behavior
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {describe, it, expect, vi} from 'vitest';
|
|
12
|
+
import {describe, it, expect, vi, beforeAll, afterAll} from 'vitest';
|
|
13
13
|
import {render, screen} from '@testing-library/react';
|
|
14
14
|
import userEvent from '@testing-library/user-event';
|
|
15
15
|
import {TopNavMegaMenu} from './TopNavMegaMenu';
|
|
@@ -75,6 +75,154 @@ describe('TopNavMegaMenu — default mode', () => {
|
|
|
75
75
|
});
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
+
// =============================================================================
|
|
79
|
+
// Popup semantics (default mode)
|
|
80
|
+
// =============================================================================
|
|
81
|
+
|
|
82
|
+
describe('TopNavMegaMenu — popup semantics', () => {
|
|
83
|
+
// Mock the Popover API (not implemented in jsdom).
|
|
84
|
+
const originalMatches = HTMLElement.prototype.matches;
|
|
85
|
+
|
|
86
|
+
beforeAll(() => {
|
|
87
|
+
HTMLElement.prototype.showPopover = vi.fn(function (this: HTMLElement) {
|
|
88
|
+
this.setAttribute('popover-open', '');
|
|
89
|
+
const event = new Event('toggle', {bubbles: false});
|
|
90
|
+
Object.defineProperty(event, 'newState', {value: 'open'});
|
|
91
|
+
this.dispatchEvent(event);
|
|
92
|
+
});
|
|
93
|
+
HTMLElement.prototype.hidePopover = vi.fn(function (this: HTMLElement) {
|
|
94
|
+
this.removeAttribute('popover-open');
|
|
95
|
+
const event = new Event('toggle', {bubbles: false});
|
|
96
|
+
Object.defineProperty(event, 'newState', {value: 'closed'});
|
|
97
|
+
this.dispatchEvent(event);
|
|
98
|
+
});
|
|
99
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
100
|
+
(HTMLElement.prototype as any).matches = function (
|
|
101
|
+
selector: string,
|
|
102
|
+
): boolean {
|
|
103
|
+
if (selector === ':popover-open') {
|
|
104
|
+
return this.hasAttribute('popover-open');
|
|
105
|
+
}
|
|
106
|
+
return originalMatches.call(this, selector);
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
afterAll(() => {
|
|
111
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
112
|
+
(HTMLElement.prototype as any).matches = originalMatches;
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('trigger aria-controls resolves to the popup element', async () => {
|
|
116
|
+
const user = userEvent.setup();
|
|
117
|
+
render(
|
|
118
|
+
<TopNavMegaMenu
|
|
119
|
+
label="Products"
|
|
120
|
+
items={<TopNavMegaMenuItem title="Analytics" href="/analytics" />}
|
|
121
|
+
/>,
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
const trigger = screen.getByRole('button', {name: 'Products'});
|
|
125
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
126
|
+
|
|
127
|
+
// aria-controls must be present and point at the real popup element.
|
|
128
|
+
const controlsId = trigger.getAttribute('aria-controls');
|
|
129
|
+
expect(controlsId).toBeTruthy();
|
|
130
|
+
const popup = document.getElementById(controlsId as string);
|
|
131
|
+
expect(popup).not.toBeNull();
|
|
132
|
+
|
|
133
|
+
await user.click(trigger);
|
|
134
|
+
|
|
135
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
136
|
+
// The referenced element is the popup that contains the panel content.
|
|
137
|
+
expect(popup).toContainElement(
|
|
138
|
+
screen.getByRole('group', {name: 'Products', hidden: true}),
|
|
139
|
+
);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('does not wrap the panel in a role="dialog" aria-modal element', async () => {
|
|
143
|
+
const user = userEvent.setup();
|
|
144
|
+
render(
|
|
145
|
+
<TopNavMegaMenu
|
|
146
|
+
label="Products"
|
|
147
|
+
items={<TopNavMegaMenuItem title="Analytics" href="/analytics" />}
|
|
148
|
+
/>,
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
await user.click(screen.getByRole('button', {name: 'Products'}));
|
|
152
|
+
|
|
153
|
+
// Focus stays on the trigger while the panel is open, so a modal dialog
|
|
154
|
+
// wrapper would tell assistive tech the focused control is inert.
|
|
155
|
+
expect(
|
|
156
|
+
screen.queryByRole('dialog', {hidden: true}),
|
|
157
|
+
).not.toBeInTheDocument();
|
|
158
|
+
expect(document.querySelector('[aria-modal="true"]')).toBeNull();
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('does not expose role="menu" — a link grid is not an ARIA menu', async () => {
|
|
162
|
+
const user = userEvent.setup();
|
|
163
|
+
render(
|
|
164
|
+
<TopNavMegaMenu
|
|
165
|
+
label="Products"
|
|
166
|
+
items={
|
|
167
|
+
<>
|
|
168
|
+
<TopNavMegaMenuItem title="Analytics" href="/analytics" />
|
|
169
|
+
<TopNavMegaMenuItem title="Reports" href="/reports" />
|
|
170
|
+
</>
|
|
171
|
+
}
|
|
172
|
+
/>,
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
await user.click(screen.getByRole('button', {name: 'Products'}));
|
|
176
|
+
|
|
177
|
+
// Per the WAI-ARIA APG, mega menu panels of navigation links must not use
|
|
178
|
+
// the menu role (reserved for action menus with menuitem children).
|
|
179
|
+
expect(screen.queryByRole('menu', {hidden: true})).not.toBeInTheDocument();
|
|
180
|
+
expect(screen.queryAllByRole('menuitem', {hidden: true})).toHaveLength(0);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('exposes the panel as a labeled group', async () => {
|
|
184
|
+
const user = userEvent.setup();
|
|
185
|
+
render(
|
|
186
|
+
<TopNavMegaMenu
|
|
187
|
+
label="Products"
|
|
188
|
+
items={<TopNavMegaMenuItem title="Analytics" href="/analytics" />}
|
|
189
|
+
/>,
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
await user.click(screen.getByRole('button', {name: 'Products'}));
|
|
193
|
+
|
|
194
|
+
expect(
|
|
195
|
+
screen.getByRole('group', {name: 'Products', hidden: true}),
|
|
196
|
+
).toBeInTheDocument();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('keeps item links with accessible names inside the panel', async () => {
|
|
200
|
+
const user = userEvent.setup();
|
|
201
|
+
render(
|
|
202
|
+
<TopNavMegaMenu
|
|
203
|
+
label="Products"
|
|
204
|
+
items={
|
|
205
|
+
<>
|
|
206
|
+
<TopNavMegaMenuItem title="Analytics" href="/analytics" />
|
|
207
|
+
<TopNavMegaMenuItem title="Reports" href="/reports" />
|
|
208
|
+
</>
|
|
209
|
+
}
|
|
210
|
+
/>,
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
await user.click(screen.getByRole('button', {name: 'Products'}));
|
|
214
|
+
|
|
215
|
+
const analytics = screen.getByRole('link', {
|
|
216
|
+
name: /Analytics/,
|
|
217
|
+
hidden: true,
|
|
218
|
+
});
|
|
219
|
+
expect(analytics).toHaveAttribute('href', '/analytics');
|
|
220
|
+
expect(
|
|
221
|
+
screen.getByRole('link', {name: /Reports/, hidden: true}),
|
|
222
|
+
).toHaveAttribute('href', '/reports');
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
|
|
78
226
|
// =============================================================================
|
|
79
227
|
// Mobile-bar mode — should be hidden
|
|
80
228
|
// =============================================================================
|
|
@@ -354,7 +354,11 @@ function DefaultMegaMenu({
|
|
|
354
354
|
}, [onOpenChange]);
|
|
355
355
|
|
|
356
356
|
const popover = usePopover({
|
|
357
|
-
|
|
357
|
+
// role: 'none' — the panel exposes its own role="group" labeled by
|
|
358
|
+
// `label`. Focus stays on the trigger while the panel is open, so a
|
|
359
|
+
// role="dialog" aria-modal="true" wrapper would announce an unnamed
|
|
360
|
+
// modal dialog around a grid of links.
|
|
361
|
+
role: 'none',
|
|
358
362
|
// hasSurface: false — mega menu provides its own surface (panelContainer)
|
|
359
363
|
// with border-top and custom overflow. Animation is applied via the
|
|
360
364
|
// render() call's xstyle prop (panelAnimation), not the hook options.
|
|
@@ -434,8 +438,7 @@ function DefaultMegaMenu({
|
|
|
434
438
|
<button
|
|
435
439
|
ref={mergeRefs(triggerButtonRef, ref)}
|
|
436
440
|
type="button"
|
|
437
|
-
|
|
438
|
-
aria-expanded={popover.isOpen}
|
|
441
|
+
{...popover.triggerProps}
|
|
439
442
|
onClick={handleClick}
|
|
440
443
|
onMouseEnter={handleMouseEnter}
|
|
441
444
|
onMouseLeave={handleMouseLeave}
|
|
@@ -454,7 +457,10 @@ function DefaultMegaMenu({
|
|
|
454
457
|
</button>
|
|
455
458
|
{popover.render(
|
|
456
459
|
<div
|
|
457
|
-
role="menu
|
|
460
|
+
// role="group" — a mega menu is a browsing grid of links, not an
|
|
461
|
+
// ARIA menu of menuitems (per the WAI-ARIA APG, the menu role is
|
|
462
|
+
// for action menus; link mega menus are the documented anti-case).
|
|
463
|
+
role="group"
|
|
458
464
|
aria-label={label}
|
|
459
465
|
onMouseEnter={handleMouseEnter}
|
|
460
466
|
onMouseLeave={handleMouseLeave}
|
|
@@ -27,7 +27,7 @@ export const docs = {
|
|
|
27
27
|
{
|
|
28
28
|
name: 'imageAlt',
|
|
29
29
|
type: 'string',
|
|
30
|
-
description: 'Alt text for the image.',
|
|
30
|
+
description: 'Alt text for the image. When omitted, the image is explicitly decorative (alt="", role="presentation", aria-hidden), usually correct since the card already has a visible title. Provide it only when the image conveys information beyond the title and description.',
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
33
|
name: 'linkLabel',
|
|
@@ -71,7 +71,7 @@ export const docsZh = {
|
|
|
71
71
|
{
|
|
72
72
|
name: 'imageAlt',
|
|
73
73
|
type: 'string',
|
|
74
|
-
description: '
|
|
74
|
+
description: '图片的替代文本。省略时图片会被显式标记为装饰性(alt=""、role="presentation"、aria-hidden)——由于卡片已有可见标题,这通常是正确的。仅当图片传达标题和描述之外的信息时才提供。',
|
|
75
75
|
},
|
|
76
76
|
{
|
|
77
77
|
name: 'linkLabel',
|
|
@@ -99,7 +99,7 @@ export const docsDense = {
|
|
|
99
99
|
title: 'Card title.',
|
|
100
100
|
description: 'Description below title.',
|
|
101
101
|
image: 'Image URL above body.',
|
|
102
|
-
imageAlt: 'Image alt text.',
|
|
102
|
+
imageAlt: 'Image alt text. Omitted → explicitly decorative (hidden from screen readers); usually correct since card has visible title.',
|
|
103
103
|
linkLabel: 'CTA link text.',
|
|
104
104
|
linkHref: 'CTA link URL.',
|
|
105
105
|
children: 'Custom content below standard body.',
|
|
@@ -84,7 +84,15 @@ export interface TopNavMegaMenuFeaturedCardProps extends BaseProps<HTMLDivElemen
|
|
|
84
84
|
description?: string;
|
|
85
85
|
/** Optional image URL displayed above the body. */
|
|
86
86
|
image?: string;
|
|
87
|
-
/**
|
|
87
|
+
/**
|
|
88
|
+
* Alt text for the image.
|
|
89
|
+
*
|
|
90
|
+
* When omitted, the image is explicitly decorative (`alt=""` +
|
|
91
|
+
* `role="presentation"` + `aria-hidden`, matching Avatar) and hidden from
|
|
92
|
+
* assistive technology. Since the card already has a visible `title`, a
|
|
93
|
+
* decorative image is usually correct; pass `imageAlt` only when the image
|
|
94
|
+
* conveys information beyond the title and description.
|
|
95
|
+
*/
|
|
88
96
|
imageAlt?: string;
|
|
89
97
|
/** CTA link text. */
|
|
90
98
|
linkLabel?: string;
|
|
@@ -149,7 +157,16 @@ export function TopNavMegaMenuFeaturedCard({
|
|
|
149
157
|
)}
|
|
150
158
|
{...rest}>
|
|
151
159
|
{image && (
|
|
152
|
-
|
|
160
|
+
// Without `imageAlt`, the image is explicitly decorative rather than
|
|
161
|
+
// silently empty-alt, matching Avatar's handling of unnamed images.
|
|
162
|
+
// Usually correct here: the card already has a visible title.
|
|
163
|
+
<img
|
|
164
|
+
src={image}
|
|
165
|
+
alt={imageAlt ?? ''}
|
|
166
|
+
role={imageAlt ? undefined : 'presentation'}
|
|
167
|
+
aria-hidden={imageAlt ? undefined : true}
|
|
168
|
+
{...stylex.props(styles.image)}
|
|
169
|
+
/>
|
|
153
170
|
)}
|
|
154
171
|
<div {...stylex.props(styles.body)}>
|
|
155
172
|
<span {...stylex.props(styles.title)}>{title}</span>
|