@astryxdesign/core 0.1.6 → 0.1.7-canary.04cd8f7
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 +68 -0
- package/README.md +25 -14
- package/dist/AlertDialog/AlertDialog.d.ts +1 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +4 -1
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +3 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts +1 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +4 -1
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +8 -6
- package/dist/Breadcrumbs/Breadcrumbs.d.ts +1 -1
- package/dist/Breadcrumbs/Breadcrumbs.d.ts.map +1 -1
- package/dist/Breadcrumbs/Breadcrumbs.js +4 -1
- package/dist/Button/Button.d.ts +10 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +49 -6
- package/dist/ButtonGroup/ButtonGroup.d.ts +20 -5
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +27 -11
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +29 -7
- package/dist/Carousel/Carousel.d.ts +1 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +8 -5
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +4 -1
- package/dist/Chat/ChatComposerDrawer.d.ts +1 -1
- package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
- package/dist/Chat/ChatComposerDrawer.js +9 -2
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +6 -2
- package/dist/Chat/ChatLayout.d.ts +1 -11
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +6 -4
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +4 -2
- package/dist/Chat/ChatMessage.d.ts +1 -1
- package/dist/Chat/ChatMessage.d.ts.map +1 -1
- package/dist/Chat/ChatMessage.js +8 -2
- package/dist/Chat/ChatMessageBubble.d.ts +1 -1
- package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
- package/dist/Chat/ChatMessageBubble.js +3 -1
- package/dist/Chat/ChatMessageList.d.ts +1 -1
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +3 -1
- package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
- package/dist/Chat/ChatMessageMetadata.js +13 -8
- package/dist/Chat/ChatPastedTextToken.d.ts.map +1 -1
- package/dist/Chat/ChatPastedTextToken.js +3 -1
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.js +3 -1
- package/dist/Chat/index.d.ts +1 -1
- package/dist/Chat/index.d.ts.map +1 -1
- package/dist/Chat/useChatStreamScroll.d.ts +12 -1
- package/dist/Chat/useChatStreamScroll.d.ts.map +1 -1
- package/dist/Chat/useChatStreamScroll.js +43 -6
- package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
- package/dist/Chat/useSpeechRecognition.js +4 -2
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +4 -2
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +4 -2
- package/dist/CheckboxList/CheckboxList.d.ts +1 -1
- package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxList.js +3 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +3 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +10 -2
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +71 -53
- package/dist/Collapsible/Collapsible.d.ts +11 -1
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +36 -4
- package/dist/CommandPalette/CommandPalette.d.ts +1 -1
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +8 -3
- package/dist/CommandPalette/CommandPaletteInput.d.ts +1 -1
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +4 -1
- package/dist/CommandPalette/CommandPaletteList.d.ts +1 -1
- package/dist/CommandPalette/CommandPaletteList.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteList.js +4 -1
- package/dist/ContextMenu/ContextMenu.d.ts +1 -1
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +8 -4
- package/dist/ContextMenu/index.d.ts +3 -0
- package/dist/ContextMenu/index.d.ts.map +1 -1
- package/dist/ContextMenu/index.js +7 -1
- package/dist/DateInput/DateInput.d.ts +1 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +10 -5
- package/dist/DateRangeInput/DateRangeInput.d.ts +1 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +11 -6
- package/dist/DateTimeInput/DateTimeInput.d.ts +1 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +15 -7
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +15 -12
- package/dist/Dialog/DialogHeader.d.ts +1 -1
- package/dist/Dialog/DialogHeader.d.ts.map +1 -1
- package/dist/Dialog/DialogHeader.js +7 -3
- package/dist/DropdownMenu/DropdownMenu.d.ts +1 -1
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +19 -9
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +89 -0
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +170 -0
- package/dist/DropdownMenu/DropdownMenuContext.d.ts +17 -1
- package/dist/DropdownMenu/DropdownMenuContext.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuContext.js +18 -0
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +69 -0
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +70 -0
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +69 -0
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +178 -0
- package/dist/DropdownMenu/index.d.ts +5 -1
- package/dist/DropdownMenu/index.d.ts.map +1 -1
- package/dist/DropdownMenu/index.js +10 -1
- package/dist/DropdownMenu/menuItemRoles.d.ts +13 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -0
- package/dist/DropdownMenu/menuItemRoles.js +15 -0
- package/dist/EmptyState/EmptyState.d.ts +4 -1
- package/dist/EmptyState/EmptyState.d.ts.map +1 -1
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +11 -1
- package/dist/Icon/Icon.d.ts +17 -12
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +28 -20
- package/dist/Kbd/Kbd.js +1 -1
- package/dist/Layer/useLayer.d.ts +10 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +23 -1
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +6 -4
- package/dist/Link/Link.d.ts +5 -1
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +32 -1
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +10 -8
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +4 -2
- package/dist/MobileNav/MobileNavToggle.d.ts +1 -1
- package/dist/MobileNav/MobileNavToggle.d.ts.map +1 -1
- package/dist/MobileNav/MobileNavToggle.js +4 -1
- package/dist/MoreMenu/MoreMenu.d.ts +1 -1
- package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
- package/dist/MoreMenu/MoreMenu.js +4 -1
- package/dist/MultiSelector/MultiSelector.d.ts +1 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +13 -6
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +5 -1
- package/dist/Outline/Outline.d.ts +1 -1
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +4 -1
- package/dist/Pagination/Pagination.d.ts +1 -1
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +38 -11
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +4 -1
- package/dist/PowerSearch/PowerSearch.d.ts +1 -1
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +22 -12
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +26 -20
- package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchToken.js +7 -3
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +34 -21
- package/dist/PowerSearch/formatFilterValue.d.ts +2 -1
- package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
- package/dist/PowerSearch/formatFilterValue.js +19 -9
- package/dist/PowerSearch/index.d.ts +2 -1
- package/dist/PowerSearch/index.d.ts.map +1 -1
- package/dist/PowerSearch/index.js +1 -0
- package/dist/PowerSearch/resolveOperatorLabel.d.ts +23 -0
- package/dist/PowerSearch/resolveOperatorLabel.d.ts.map +1 -0
- package/dist/PowerSearch/resolveOperatorLabel.js +28 -0
- package/dist/PowerSearch/types.d.ts +28 -2
- package/dist/PowerSearch/types.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchConfig.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchConfig.js +27 -27
- package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchSource.js +15 -8
- package/dist/Resizable/ResizeHandle.d.ts +1 -1
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +4 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +52 -14
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +4 -2
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +3 -1
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +5 -3
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +7 -1
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +4 -2
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +2 -2
- package/dist/TabList/TabList.d.ts +1 -1
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +6 -1
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +29 -16
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +5 -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/columnResize/useTableColumnResize.js +1 -1
- package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
- package/dist/Table/plugins/filtering/useTableFiltering.js +56 -19
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +12 -5
- package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +6 -3
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +8 -6
- package/dist/Table/plugins/rowIndex/useTableRowIndex.d.ts +1 -1
- package/dist/Table/plugins/rowIndex/useTableRowIndex.js +1 -1
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +5 -2
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +6 -4
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +2 -2
- package/dist/Table/plugins/tree/index.d.ts +5 -0
- package/dist/Table/plugins/tree/index.d.ts.map +1 -0
- package/dist/Table/plugins/tree/index.js +4 -0
- package/dist/Table/plugins/tree/useTableTreeData.d.ts +38 -0
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -0
- package/dist/Table/plugins/tree/useTableTreeData.js +358 -0
- package/dist/Table/plugins/tree/useTableTreeState.d.ts +51 -0
- package/dist/Table/plugins/tree/useTableTreeState.d.ts.map +1 -0
- package/dist/Table/plugins/tree/useTableTreeState.js +175 -0
- package/dist/Table/types.d.ts +17 -10
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +6 -3
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +5 -1
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +8 -2
- package/dist/TimeInput/TimeInput.d.ts +1 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +7 -2
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +18 -3
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +3 -1
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +3 -1
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +8 -2
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +3 -1
- package/dist/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.js +8 -1
- package/dist/TopNav/TopNav.d.ts +2 -1
- package/dist/TopNav/TopNav.d.ts.map +1 -1
- package/dist/TopNav/TopNav.js +4 -1
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +5 -3
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +5 -1
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +7 -1
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +8 -4
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +3 -1
- package/dist/VisuallyHidden/VisuallyHidden.d.ts +1 -0
- package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -1
- package/dist/VisuallyHidden/VisuallyHidden.js +1 -0
- package/dist/astryx.css +38 -4
- package/dist/astryx.umd.js +62 -60
- package/dist/astryx.umd.js.map +4 -4
- package/dist/authoring/doc.d.ts +145 -0
- package/dist/authoring/doc.d.ts.map +1 -0
- package/dist/authoring/doc.js +100 -0
- package/dist/authoring/index.d.ts +29 -0
- package/dist/authoring/index.d.ts.map +1 -0
- package/dist/authoring/index.js +28 -0
- package/dist/authoring/integration.d.ts +35 -0
- package/dist/authoring/integration.d.ts.map +1 -0
- package/dist/authoring/integration.js +30 -0
- package/dist/authoring/template.d.ts +66 -0
- package/dist/authoring/template.d.ts.map +1 -0
- package/dist/authoring/template.js +55 -0
- package/dist/config.d.ts +80 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +40 -0
- package/dist/docs-types.d.ts +13 -4
- package/dist/docs-types.d.ts.map +1 -1
- package/dist/i18n/InternationalizationContext.d.ts +12 -0
- package/dist/i18n/InternationalizationContext.d.ts.map +1 -0
- package/dist/i18n/InternationalizationContext.js +29 -0
- package/dist/i18n/InternationalizationProvider.d.ts +61 -0
- package/dist/i18n/InternationalizationProvider.d.ts.map +1 -0
- package/dist/i18n/InternationalizationProvider.js +44 -0
- package/dist/i18n/index.d.ts +24 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +21 -0
- package/dist/i18n/resolve.d.ts +22 -0
- package/dist/i18n/resolve.d.ts.map +1 -0
- package/dist/i18n/resolve.js +141 -0
- package/dist/i18n/translator.d.ts +25 -0
- package/dist/i18n/translator.d.ts.map +1 -0
- package/dist/i18n/translator.js +1 -0
- package/dist/i18n/types.d.ts +47 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n/types.js +1 -0
- package/dist/i18n/useTranslator.d.ts +15 -0
- package/dist/i18n/useTranslator.d.ts.map +1 -0
- package/dist/i18n/useTranslator.js +39 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/theme/Theme.js +1 -1
- package/dist/theme/defineTheme.d.ts +1 -1
- package/dist/theme/defineTheme.js +1 -1
- package/dist/theme/hct.d.ts +0 -1
- package/dist/theme/hct.d.ts.map +1 -1
- package/dist/theme/hct.js +0 -3
- package/dist/utils/color.d.ts +13 -1
- package/dist/utils/color.d.ts.map +1 -1
- package/dist/utils/color.js +23 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -1
- package/locales/en.json +754 -0
- package/locales/pseudo.json +566 -0
- package/package.json +23 -2
- package/src/AlertDialog/AlertDialog.doc.mjs +5 -0
- package/src/AlertDialog/AlertDialog.tsx +4 -1
- package/src/AppShell/AppShell.doc.mjs +8 -2
- package/src/AppShell/AppShell.tsx +3 -1
- package/src/AvatarGroup/AvatarGroup.tsx +4 -1
- package/src/Banner/Banner.tsx +10 -5
- package/src/Breadcrumbs/Breadcrumbs.tsx +4 -1
- package/src/Button/Button.doc.mjs +8 -0
- package/src/Button/Button.test.tsx +27 -0
- package/src/Button/Button.tsx +51 -5
- package/src/ButtonGroup/ButtonGroup.test.tsx +386 -2
- package/src/ButtonGroup/ButtonGroup.tsx +27 -11
- package/src/Calendar/Calendar.test.tsx +103 -2
- package/src/Calendar/Calendar.tsx +29 -6
- package/src/Card/Card.doc.mjs +3 -3
- package/src/Carousel/Carousel.tsx +10 -7
- package/src/Chat/ChatComposer.tsx +5 -1
- package/src/Chat/ChatComposerDrawer.tsx +9 -2
- package/src/Chat/ChatComposerInput.tsx +10 -4
- package/src/Chat/ChatLayout.test.tsx +127 -2
- package/src/Chat/ChatLayout.tsx +5 -12
- package/src/Chat/ChatLayoutScrollButton.tsx +4 -2
- package/src/Chat/ChatMessage.tsx +5 -1
- package/src/Chat/ChatMessageBubble.tsx +2 -0
- package/src/Chat/ChatMessageList.doc.mjs +1 -1
- package/src/Chat/ChatMessageList.tsx +2 -0
- package/src/Chat/ChatMessageMetadata.tsx +15 -9
- package/src/Chat/ChatPastedTextToken.tsx +3 -1
- package/src/Chat/ChatSendButton.tsx +3 -1
- package/src/Chat/ChatToolCalls.doc.mjs +1 -1
- package/src/Chat/index.ts +1 -0
- package/src/Chat/useChatStreamScroll.test.tsx +168 -0
- package/src/Chat/useChatStreamScroll.ts +67 -11
- package/src/Chat/useSpeechRecognition.ts +11 -2
- package/src/Chat/useTriggerMenu.tsx +4 -2
- package/src/CheckboxInput/CheckboxInput.doc.mjs +1 -1
- package/src/CheckboxInput/CheckboxInput.test.tsx +16 -0
- package/src/CheckboxInput/CheckboxInput.tsx +4 -2
- package/src/CheckboxList/CheckboxList.doc.mjs +6 -1
- package/src/CheckboxList/CheckboxList.tsx +2 -0
- package/src/CheckboxList/CheckboxListItem.tsx +7 -1
- package/src/Citation/Citation.tsx +4 -2
- package/src/ClickableCard/ClickableCard.doc.mjs +1 -1
- package/src/CodeBlock/CodeBlock.tsx +91 -40
- package/src/Collapsible/Collapsible.doc.mjs +7 -0
- package/src/Collapsible/Collapsible.test.tsx +80 -0
- package/src/Collapsible/Collapsible.tsx +58 -5
- package/src/CommandPalette/CommandPalette.tsx +10 -3
- package/src/CommandPalette/CommandPaletteInput.test.tsx +1 -1
- package/src/CommandPalette/CommandPaletteInput.tsx +5 -1
- package/src/CommandPalette/CommandPaletteList.tsx +4 -1
- package/src/ContextMenu/ContextMenu.test.tsx +75 -1
- package/src/ContextMenu/ContextMenu.tsx +14 -6
- package/src/ContextMenu/index.ts +15 -0
- package/src/DateInput/DateInput.doc.mjs +2 -2
- package/src/DateInput/DateInput.test.tsx +17 -5
- package/src/DateInput/DateInput.tsx +13 -5
- package/src/DateRangeInput/DateRangeInput.doc.mjs +1 -1
- package/src/DateRangeInput/DateRangeInput.tsx +14 -6
- package/src/DateTimeInput/DateTimeInput.doc.mjs +2 -2
- package/src/DateTimeInput/DateTimeInput.tsx +17 -7
- package/src/Dialog/Dialog.tsx +11 -15
- package/src/Dialog/DialogHeader.tsx +7 -3
- package/src/DropdownMenu/DropdownMenu.doc.mjs +23 -0
- package/src/DropdownMenu/DropdownMenu.tsx +23 -14
- package/src/DropdownMenu/DropdownMenuCheckboxItem.doc.mjs +95 -0
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +237 -0
- package/src/DropdownMenu/DropdownMenuContext.tsx +29 -1
- package/src/DropdownMenu/DropdownMenuItem.doc.mjs +7 -1
- package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +80 -0
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +119 -0
- package/src/DropdownMenu/DropdownMenuRadioItem.doc.mjs +80 -0
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +232 -0
- package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +163 -0
- package/src/DropdownMenu/index.ts +23 -3
- package/src/DropdownMenu/menuItemRoles.ts +22 -0
- package/src/EmptyState/EmptyState.doc.mjs +3 -3
- package/src/EmptyState/EmptyState.tsx +4 -1
- package/src/Field/Field.doc.mjs +3 -3
- package/src/Field/FieldLabel.doc.mjs +1 -1
- package/src/FileInput/FileInput.test.tsx +40 -1
- package/src/FileInput/FileInput.tsx +12 -1
- package/src/Grid/Grid.doc.mjs +5 -5
- package/src/Icon/Icon.test.tsx +46 -0
- package/src/Icon/Icon.tsx +37 -24
- package/src/InputGroup/InputGroup.doc.mjs +1 -1
- package/src/Kbd/Kbd.test.tsx +26 -0
- package/src/Kbd/Kbd.tsx +1 -1
- package/src/Layer/useLayer.doc.mjs +8 -5
- package/src/Layer/useLayer.test.tsx +136 -1
- package/src/Layer/useLayer.tsx +34 -2
- package/src/Lightbox/Lightbox.doc.mjs +7 -2
- package/src/Lightbox/Lightbox.tsx +6 -4
- package/src/Link/Link.test.tsx +74 -2
- package/src/Link/Link.tsx +48 -1
- package/src/Markdown/Markdown.tsx +12 -4
- package/src/MobileNav/MobileNav.tsx +4 -2
- package/src/MobileNav/MobileNavToggle.tsx +5 -3
- package/src/MoreMenu/MoreMenu.tsx +4 -1
- package/src/MultiSelector/MultiSelector.tsx +14 -5
- package/src/NumberInput/NumberInput.doc.mjs +2 -2
- package/src/NumberInput/NumberInput.tsx +3 -1
- package/src/Outline/Outline.tsx +4 -1
- package/src/OverflowList/OverflowList.doc.mjs +2 -2
- package/src/Pagination/Pagination.tsx +35 -12
- package/src/Popover/usePopover.tsx +6 -1
- package/src/PowerSearch/PowerSearch.doc.mjs +9 -4
- package/src/PowerSearch/PowerSearch.tsx +22 -10
- package/src/PowerSearch/PowerSearchEditPopover.tsx +27 -20
- package/src/PowerSearch/PowerSearchToken.tsx +17 -6
- package/src/PowerSearch/PowerSearchValueEditor.tsx +34 -21
- package/src/PowerSearch/formatFilterValue.test.ts +282 -0
- package/src/PowerSearch/formatFilterValue.ts +21 -8
- package/src/PowerSearch/index.ts +5 -0
- package/src/PowerSearch/resolveOperatorLabel.ts +34 -0
- package/src/PowerSearch/types.ts +33 -9
- package/src/PowerSearch/usePowerSearchConfig.ts +59 -27
- package/src/PowerSearch/usePowerSearchSource.ts +17 -8
- package/src/RadioList/RadioList.doc.mjs +1 -1
- package/src/Resizable/ResizeHandle.tsx +4 -1
- package/src/Section/Section.doc.mjs +4 -4
- package/src/SelectableCard/SelectableCard.doc.mjs +1 -1
- package/src/Selector/Selector.doc.mjs +6 -3
- package/src/Selector/Selector.test.tsx +114 -6
- package/src/Selector/Selector.tsx +68 -17
- package/src/Selector/SelectorOption.doc.mjs +1 -1
- package/src/SideNav/SideNav.tsx +4 -2
- package/src/SideNav/SideNavCollapseButton.tsx +3 -1
- package/src/SideNav/SideNavHeading.tsx +5 -3
- package/src/SideNav/SideNavItem.doc.mjs +2 -2
- package/src/SideNav/SideNavItem.tsx +3 -1
- package/src/Slider/Slider.doc.mjs +2 -2
- package/src/Stack/Stack.doc.mjs +10 -10
- package/src/Switch/Switch.doc.mjs +3 -3
- package/src/Switch/Switch.test.tsx +16 -0
- package/src/Switch/Switch.tsx +4 -2
- package/src/TabList/Tab.tsx +5 -1
- package/src/TabList/TabList.doc.mjs +3 -3
- package/src/TabList/TabList.test.tsx +66 -0
- package/src/TabList/TabList.tsx +12 -1
- package/src/TabList/TabMenu.tsx +4 -1
- package/src/Table/BaseTable.tsx +36 -19
- package/src/Table/Table.doc.mjs +2 -0
- package/src/Table/Table.test.tsx +132 -1
- package/src/Table/Table.tsx +6 -4
- package/src/Table/index.ts +7 -0
- package/src/Table/plugins/columnResize/useTableColumnResize.tsx +1 -1
- package/src/Table/plugins/filtering/useTableFiltering.tsx +31 -30
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +7 -5
- package/src/Table/plugins/pagination/useTablePagination.tsx +4 -1
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +9 -8
- package/src/Table/plugins/rowIndex/useTableRowIndex.tsx +1 -1
- package/src/Table/plugins/selection/useTableSelection.tsx +6 -7
- package/src/Table/plugins/sortable/useTableSortable.tsx +8 -5
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +4 -4
- package/src/Table/plugins/tree/index.ts +12 -0
- package/src/Table/plugins/tree/useTableTreeData-perf.test.tsx +163 -0
- package/src/Table/plugins/tree/useTableTreeData.test.tsx +594 -0
- package/src/Table/plugins/tree/useTableTreeData.tsx +495 -0
- package/src/Table/plugins/tree/useTableTreeState.test.tsx +636 -0
- package/src/Table/plugins/tree/useTableTreeState.tsx +253 -0
- package/src/Table/types.ts +18 -12
- package/src/Table/useBaseTablePlugins.ts +6 -2
- package/src/Table/useTableFiltering.doc.mjs +2 -2
- package/src/Table/useTableGroupedRows.doc.mjs +3 -3
- package/src/Table/useTableSortable.doc.mjs +11 -11
- package/src/Table/useTableTreeData.doc.mjs +75 -0
- package/src/Table/useTableTreeState.doc.mjs +98 -0
- package/src/Text/Text.doc.mjs +2 -2
- package/src/TextArea/TextArea.doc.mjs +1 -1
- package/src/TextInput/TextInput.doc.mjs +1 -1
- package/src/TextInput/TextInput.tsx +3 -1
- package/src/Thumbnail/Thumbnail.tsx +4 -2
- package/src/TimeInput/TimeInput.doc.mjs +2 -2
- package/src/TimeInput/TimeInput.tsx +6 -2
- package/src/Timestamp/Timestamp.doc.mjs +4 -4
- package/src/Timestamp/Timestamp.test.tsx +120 -7
- package/src/Timestamp/Timestamp.tsx +21 -1
- package/src/Toast/Toast.tsx +3 -1
- package/src/Toast/ToastViewport.tsx +3 -1
- package/src/Token/Token.tsx +4 -2
- package/src/Tokenizer/Tokenizer.doc.mjs +2 -2
- package/src/Tokenizer/Tokenizer.tsx +4 -4
- package/src/Toolbar/Toolbar.doc.mjs +1 -1
- package/src/Toolbar/Toolbar.tsx +10 -3
- package/src/TopNav/TopNav.doc.mjs +1 -0
- package/src/TopNav/TopNav.test.tsx +30 -0
- package/src/TopNav/TopNav.tsx +6 -4
- package/src/TopNav/TopNavHeading.tsx +5 -3
- package/src/TreeList/TreeList.tsx +5 -1
- package/src/TreeList/TreeListItem.tsx +6 -1
- package/src/Typeahead/BaseTypeahead.tsx +11 -4
- package/src/Typeahead/Typeahead.doc.mjs +1 -1
- package/src/Typeahead/Typeahead.tsx +3 -1
- package/src/VisuallyHidden/VisuallyHidden.tsx +1 -0
- package/src/authoring/doc.ts +166 -0
- package/src/authoring/index.test.ts +52 -0
- package/src/authoring/index.ts +50 -0
- package/src/authoring/integration.ts +42 -0
- package/src/authoring/template.ts +74 -0
- package/src/config.test.ts +16 -0
- package/src/config.ts +92 -0
- package/src/docPropLiterals.test.ts +938 -0
- package/src/docs-types.ts +15 -10
- package/src/i18n/InternationalizationContext.ts +39 -0
- package/src/i18n/InternationalizationProvider.doc.mjs +72 -0
- package/src/i18n/InternationalizationProvider.tsx +82 -0
- package/src/i18n/__tests__/e2e-pagination.test.tsx +172 -0
- package/src/i18n/__tests__/e2e-powersearch.test.tsx +130 -0
- package/src/i18n/__tests__/resolve.test.ts +284 -0
- package/src/i18n/index.ts +32 -0
- package/src/i18n/resolve.ts +165 -0
- package/src/i18n/translator.ts +31 -0
- package/src/i18n/types.ts +53 -0
- package/src/i18n/useTranslator.doc.mjs +46 -0
- package/src/i18n/useTranslator.ts +50 -0
- package/src/index.ts +3 -0
- package/src/theme/Theme.doc.mjs +4 -4
- package/src/theme/Theme.tsx +1 -1
- package/src/theme/defineTheme.ts +1 -1
- package/src/theme/hct.ts +0 -4
- package/src/utils/color.test.ts +101 -1
- package/src/utils/color.ts +23 -1
- package/src/utils/index.ts +8 -1
- package/dist/NavItem/index.d.ts +0 -9
- package/dist/NavItem/index.d.ts.map +0 -1
- package/dist/NavItem/index.js +0 -10
- package/src/NavItem/index.ts +0 -11
|
@@ -42,6 +42,7 @@ import {Divider} from '../Divider';
|
|
|
42
42
|
import {layerAnimations} from '../Layer/layerAnimations.stylex';
|
|
43
43
|
import type {LayerPlacement} from '../Layer/useLayer';
|
|
44
44
|
import {Spinner} from '../Spinner';
|
|
45
|
+
import {useAnnounce} from '../hooks/useAnnounce';
|
|
45
46
|
import {
|
|
46
47
|
colorVars,
|
|
47
48
|
sizeVars,
|
|
@@ -72,6 +73,7 @@ import {themeProps} from '../utils/themeProps';
|
|
|
72
73
|
import {groupStyles} from '../InputGroup/groupStyles';
|
|
73
74
|
import {useInputGroup} from '../InputGroup/InputGroupContext';
|
|
74
75
|
import {VisuallyHidden} from '../VisuallyHidden';
|
|
76
|
+
import {useTranslator} from '../i18n';
|
|
75
77
|
|
|
76
78
|
const styles = stylex.create({
|
|
77
79
|
// Trigger container — the enhanced click target wrapping the combobox button and clear button as siblings
|
|
@@ -524,8 +526,7 @@ type SelectorPropsClearable<T extends SelectorOptionType = SelectorOptionType> =
|
|
|
524
526
|
};
|
|
525
527
|
|
|
526
528
|
export type SelectorProps<T extends SelectorOptionType = SelectorOptionType> =
|
|
527
|
-
|
|
|
528
|
-
| SelectorPropsClearable<T>;
|
|
529
|
+
SelectorPropsNonClearable<T> | SelectorPropsClearable<T>;
|
|
529
530
|
|
|
530
531
|
/**
|
|
531
532
|
* Default option renderer
|
|
@@ -536,6 +537,23 @@ function DefaultOption({option}: {option: SelectorOptionData}) {
|
|
|
536
537
|
);
|
|
537
538
|
}
|
|
538
539
|
|
|
540
|
+
// Case-insensitive substring filter over the selectable options. Shared by the
|
|
541
|
+
// `filteredItems` memo (rendering) and the search-change handler, which needs
|
|
542
|
+
// the count for the *next* query synchronously to announce it exactly once per
|
|
543
|
+
// keystroke rather than reacting to state in an effect.
|
|
544
|
+
function filterOptionsByQuery(
|
|
545
|
+
items: SelectorOptionData[],
|
|
546
|
+
query: string,
|
|
547
|
+
): SelectorOptionData[] {
|
|
548
|
+
if (!query) {
|
|
549
|
+
return items;
|
|
550
|
+
}
|
|
551
|
+
const q = query.toLowerCase();
|
|
552
|
+
return items.filter(item =>
|
|
553
|
+
(item.label ?? item.value).toLowerCase().includes(q),
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
|
|
539
557
|
/**
|
|
540
558
|
* A selector/dropdown component for choosing from a list of options.
|
|
541
559
|
*
|
|
@@ -553,6 +571,7 @@ function DefaultOption({option}: {option: SelectorOptionData}) {
|
|
|
553
571
|
export function Selector<T extends SelectorOptionType>(
|
|
554
572
|
props: SelectorProps<T>,
|
|
555
573
|
) {
|
|
574
|
+
const t = useTranslator();
|
|
556
575
|
const {
|
|
557
576
|
label,
|
|
558
577
|
isLabelHidden = false,
|
|
@@ -566,7 +585,7 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
566
585
|
onChange,
|
|
567
586
|
changeAction,
|
|
568
587
|
isLoading = false,
|
|
569
|
-
placeholder
|
|
588
|
+
placeholder: placeholderFromProps,
|
|
570
589
|
size: sizeProp,
|
|
571
590
|
status,
|
|
572
591
|
labelTooltip,
|
|
@@ -574,7 +593,7 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
574
593
|
htmlName,
|
|
575
594
|
renderOption,
|
|
576
595
|
hasSearch = false,
|
|
577
|
-
searchPlaceholder
|
|
596
|
+
searchPlaceholder: searchPlaceholderFromProps,
|
|
578
597
|
placement,
|
|
579
598
|
isDefaultOpen = false,
|
|
580
599
|
'data-testid': testId,
|
|
@@ -585,6 +604,9 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
585
604
|
hasClear: hasClearProp,
|
|
586
605
|
...rest
|
|
587
606
|
} = props as SelectorPropsClearable<T>;
|
|
607
|
+
const placeholder = placeholderFromProps ?? t('@astryx.selector.placeholder');
|
|
608
|
+
const searchPlaceholder =
|
|
609
|
+
searchPlaceholderFromProps ?? t('@astryx.selector.searchPlaceholder');
|
|
588
610
|
const hasClear = hasClearProp === true;
|
|
589
611
|
const size = useSize(sizeProp, 'md');
|
|
590
612
|
|
|
@@ -637,15 +659,10 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
637
659
|
);
|
|
638
660
|
|
|
639
661
|
// Filter items by search query
|
|
640
|
-
const filteredItems = useMemo(
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
const query = searchQuery.toLowerCase();
|
|
645
|
-
return selectableItems.filter(item =>
|
|
646
|
-
(item.label ?? item.value).toLowerCase().includes(query),
|
|
647
|
-
);
|
|
648
|
-
}, [selectableItems, searchQuery]);
|
|
662
|
+
const filteredItems = useMemo(
|
|
663
|
+
() => filterOptionsByQuery(selectableItems, searchQuery),
|
|
664
|
+
[selectableItems, searchQuery],
|
|
665
|
+
);
|
|
649
666
|
|
|
650
667
|
// Find selected item and its index for positioning
|
|
651
668
|
const selectedItemIndex = useMemo(() => {
|
|
@@ -661,11 +678,20 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
661
678
|
// Ref for listbox to measure selected item position
|
|
662
679
|
const listboxRef = useRef<HTMLDivElement>(null);
|
|
663
680
|
|
|
681
|
+
// Announce match counts / "No results found" politely as the user types, so
|
|
682
|
+
// screen-reader users hear how many options remain. Filtering was previously
|
|
683
|
+
// silent (comboboxes-7). Mirrors BaseTypeahead, which announces from its
|
|
684
|
+
// query-change callback (not a reactive effect) via the same useAnnounce hook.
|
|
685
|
+
const announce = useAnnounce();
|
|
686
|
+
|
|
664
687
|
// Layer for dropdown positioning
|
|
665
688
|
const handleLayerHide = useCallback(() => {
|
|
666
689
|
setSearchQuery('');
|
|
690
|
+
// Clear any lingering result count when the popover closes so stale status
|
|
691
|
+
// text does not linger in the a11y tree.
|
|
692
|
+
announce('');
|
|
667
693
|
triggerRef.current?.focus();
|
|
668
|
-
}, []);
|
|
694
|
+
}, [announce]);
|
|
669
695
|
|
|
670
696
|
const popover = usePopover({
|
|
671
697
|
onHide: handleLayerHide,
|
|
@@ -685,6 +711,29 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
685
711
|
// eslint-disable-next-line @eslint-react/exhaustive-deps -- mount-only: isDefaultOpen is not reactive
|
|
686
712
|
}, []);
|
|
687
713
|
|
|
714
|
+
// Announce the filtered result count from the query-change handler (matching
|
|
715
|
+
// BaseTypeahead) rather than a reactive effect: computing the count for the
|
|
716
|
+
// next query here fires the announcement exactly once per keystroke and does
|
|
717
|
+
// not re-speak on unrelated re-renders.
|
|
718
|
+
const handleSearchChange = useCallback(
|
|
719
|
+
(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
720
|
+
const nextQuery = event.target.value;
|
|
721
|
+
setSearchQuery(nextQuery);
|
|
722
|
+
if (nextQuery.length === 0) {
|
|
723
|
+
// Emptying the query clears the region rather than announcing a count.
|
|
724
|
+
announce('');
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
const count = filterOptionsByQuery(selectableItems, nextQuery).length;
|
|
728
|
+
announce(
|
|
729
|
+
count === 0
|
|
730
|
+
? 'No results found'
|
|
731
|
+
: `${count} result${count === 1 ? '' : 's'}`,
|
|
732
|
+
);
|
|
733
|
+
},
|
|
734
|
+
[announce, selectableItems],
|
|
735
|
+
);
|
|
736
|
+
|
|
688
737
|
// Calculate offset to position selected item over trigger. Explicit
|
|
689
738
|
// placement opts out of the selector-specific overlay behavior and uses the
|
|
690
739
|
// standard layer positioning API instead.
|
|
@@ -803,10 +852,10 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
803
852
|
? getItemId(highlightedIndex)
|
|
804
853
|
: undefined
|
|
805
854
|
}
|
|
806
|
-
aria-label=
|
|
855
|
+
aria-label={t('@astryx.selector.searchOptions')}
|
|
807
856
|
type="text"
|
|
808
857
|
value={searchQuery}
|
|
809
|
-
onChange={
|
|
858
|
+
onChange={handleSearchChange}
|
|
810
859
|
onKeyDown={e => {
|
|
811
860
|
// Arrow keys navigate options; Enter selects; Escape/Tab close.
|
|
812
861
|
// Home/End are left to the input for caret movement.
|
|
@@ -831,10 +880,12 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
831
880
|
listboxId,
|
|
832
881
|
searchQuery,
|
|
833
882
|
searchPlaceholder,
|
|
883
|
+
handleSearchChange,
|
|
834
884
|
onKeyDown,
|
|
835
885
|
popover.isOpen,
|
|
836
886
|
highlightedIndex,
|
|
837
887
|
getItemId,
|
|
888
|
+
t,
|
|
838
889
|
]);
|
|
839
890
|
|
|
840
891
|
// Render an individual item
|
|
@@ -1014,7 +1065,7 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
1014
1065
|
<button
|
|
1015
1066
|
type="button"
|
|
1016
1067
|
onClick={handleClear}
|
|
1017
|
-
aria-label={
|
|
1068
|
+
aria-label={t('@astryx.selector.clearLabel', {label})}
|
|
1018
1069
|
{...stylex.props(styles.clearButton)}>
|
|
1019
1070
|
<Icon icon="close" size="sm" color="secondary" />
|
|
1020
1071
|
</button>
|
|
@@ -20,7 +20,7 @@ export const docs = {
|
|
|
20
20
|
name: 'icon',
|
|
21
21
|
type: 'IconType',
|
|
22
22
|
description:
|
|
23
|
-
'Icon displayed before the label. See `
|
|
23
|
+
'Icon displayed before the label. See `astryx docs icons` for valid semantic names.',
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
26
|
name: 'description',
|
package/src/SideNav/SideNav.tsx
CHANGED
|
@@ -45,6 +45,7 @@ import {useResizable} from '../Resizable/useResizable';
|
|
|
45
45
|
import type {ResizableConfig} from '../Resizable/useResizable';
|
|
46
46
|
import {ResizeHandle} from '../Resizable/ResizeHandle';
|
|
47
47
|
import {themeProps} from '../utils/themeProps';
|
|
48
|
+
import {useTranslator} from '../i18n';
|
|
48
49
|
|
|
49
50
|
// =============================================================================
|
|
50
51
|
// Constants
|
|
@@ -330,6 +331,7 @@ export function SideNav({
|
|
|
330
331
|
handleRef,
|
|
331
332
|
...props
|
|
332
333
|
}: SideNavProps) {
|
|
334
|
+
const t = useTranslator();
|
|
333
335
|
// Parse collapsible prop
|
|
334
336
|
const collapsibleConfig = typeof collapsible === 'object' ? collapsible : {};
|
|
335
337
|
const isCollapsible = !!collapsible;
|
|
@@ -504,7 +506,7 @@ export function SideNav({
|
|
|
504
506
|
<nav
|
|
505
507
|
ref={mergeRefs(ref, navRef)}
|
|
506
508
|
role="navigation"
|
|
507
|
-
aria-label=
|
|
509
|
+
aria-label={t('@astryx.sideNav.label')}
|
|
508
510
|
data-testid={testId}
|
|
509
511
|
{...mergeProps(
|
|
510
512
|
themeProps('side-nav'),
|
|
@@ -569,7 +571,7 @@ export function SideNav({
|
|
|
569
571
|
pillPlacement="end"
|
|
570
572
|
isAlwaysVisible={false}
|
|
571
573
|
resizable={resizableHook.props}
|
|
572
|
-
label=
|
|
574
|
+
label={t('@astryx.sideNav.resizeSidebar')}
|
|
573
575
|
/>
|
|
574
576
|
</div>
|
|
575
577
|
) : (
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
type SideNavImperativeCollapseHandle,
|
|
31
31
|
} from './SideNavCollapseContext';
|
|
32
32
|
import {useAppShellMobile} from '../AppShell/AppShellMobileContext';
|
|
33
|
+
import {useTranslator} from '../i18n';
|
|
33
34
|
|
|
34
35
|
// =============================================================================
|
|
35
36
|
// Styles
|
|
@@ -105,6 +106,7 @@ export function SideNavCollapseButton({
|
|
|
105
106
|
onClick: onClickProp,
|
|
106
107
|
...props
|
|
107
108
|
}: SideNavCollapseButtonProps) {
|
|
109
|
+
const t = useTranslator();
|
|
108
110
|
const {isCollapsed, toggle, isCollapsible} =
|
|
109
111
|
useSideNavCollapseState(handleRef);
|
|
110
112
|
const {isMobile} = useAppShellMobile();
|
|
@@ -118,7 +120,7 @@ export function SideNavCollapseButton({
|
|
|
118
120
|
return (
|
|
119
121
|
<Button
|
|
120
122
|
ref={ref}
|
|
121
|
-
label={label ?? (isCollapsed ? '
|
|
123
|
+
label={label ?? (isCollapsed ? t('@astryx.sideNavCollapseButton.expandSidebar') : t('@astryx.sideNavCollapseButton.collapseSidebar'))}
|
|
122
124
|
variant="ghost"
|
|
123
125
|
{...props}
|
|
124
126
|
onClick={composeEventHandlers(onClickProp, toggle)}
|
|
@@ -44,6 +44,7 @@ import type {BaseProps} from '../BaseProps';
|
|
|
44
44
|
import {useMenuHover} from '../hooks/useMenuHover';
|
|
45
45
|
import {NavHeadingCloseContext} from '../NavMenu/NavMenuContext';
|
|
46
46
|
import {themeProps} from '../utils/themeProps';
|
|
47
|
+
import {useTranslator} from '../i18n';
|
|
47
48
|
|
|
48
49
|
// =============================================================================
|
|
49
50
|
// Styles
|
|
@@ -342,13 +343,14 @@ export function SideNavHeading({
|
|
|
342
343
|
ref,
|
|
343
344
|
...props
|
|
344
345
|
}: SideNavHeadingProps) {
|
|
346
|
+
const t = useTranslator();
|
|
345
347
|
const LinkComponent = useLinkComponent(as);
|
|
346
348
|
const {isCollapsed} = useSideNavCollapse();
|
|
347
349
|
const rootRef = useRef<HTMLDivElement>(null);
|
|
348
350
|
const collapsedItemRef = useRef<HTMLElement>(null);
|
|
349
351
|
|
|
350
352
|
const popover = usePopover({
|
|
351
|
-
dialogLabel: '
|
|
353
|
+
dialogLabel: t('@astryx.sideNav.heading.dialogLabel'),
|
|
352
354
|
hasCloseButton: false,
|
|
353
355
|
});
|
|
354
356
|
|
|
@@ -603,7 +605,7 @@ export function SideNavHeading({
|
|
|
603
605
|
{renderTextContent(
|
|
604
606
|
<button
|
|
605
607
|
type="button"
|
|
606
|
-
aria-label=
|
|
608
|
+
aria-label={t('@astryx.sideNav.heading.openMenu')}
|
|
607
609
|
onClick={e => {
|
|
608
610
|
e.stopPropagation();
|
|
609
611
|
triggerProps.onClick();
|
|
@@ -665,7 +667,7 @@ export function SideNavHeading({
|
|
|
665
667
|
showChevron ? (
|
|
666
668
|
<button
|
|
667
669
|
type="button"
|
|
668
|
-
aria-label=
|
|
670
|
+
aria-label={t('@astryx.sideNav.heading.openMenu')}
|
|
669
671
|
onClick={e => {
|
|
670
672
|
e.stopPropagation();
|
|
671
673
|
triggerProps.onClick();
|
|
@@ -23,12 +23,12 @@ export const docs = {
|
|
|
23
23
|
{
|
|
24
24
|
name: 'icon',
|
|
25
25
|
type: 'IconType',
|
|
26
|
-
description: 'Icon displayed in the outline (unselected) variant. See `
|
|
26
|
+
description: 'Icon displayed in the outline (unselected) variant. See `astryx docs icons` for valid semantic names.',
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
name: 'selectedIcon',
|
|
30
30
|
type: 'IconType',
|
|
31
|
-
description: 'Icon displayed when the item is selected (filled variant). See `
|
|
31
|
+
description: 'Icon displayed when the item is selected (filled variant). See `astryx docs icons` for valid semantic names.',
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
34
|
name: 'isSelected',
|
|
@@ -54,6 +54,7 @@ import {getIcon} from '../Icon/globalIconRegistry';
|
|
|
54
54
|
import {useSideNavRenderMode} from './SideNavRenderContext';
|
|
55
55
|
import {useAppShellMobile} from '../AppShell/AppShellMobileContext';
|
|
56
56
|
import {themeProps} from '../utils/themeProps';
|
|
57
|
+
import {useTranslator} from '../i18n';
|
|
57
58
|
|
|
58
59
|
// =============================================================================
|
|
59
60
|
// Styles
|
|
@@ -356,6 +357,7 @@ export function SideNavItem({
|
|
|
356
357
|
'data-testid': testId,
|
|
357
358
|
ref,
|
|
358
359
|
}: SideNavItemProps) {
|
|
360
|
+
const t = useTranslator();
|
|
359
361
|
const {isCollapsed} = useSideNavCollapse();
|
|
360
362
|
const renderMode = useSideNavRenderMode();
|
|
361
363
|
const {closeMobileNav} = useAppShellMobile();
|
|
@@ -626,7 +628,7 @@ export function SideNavItem({
|
|
|
626
628
|
<button
|
|
627
629
|
type="button"
|
|
628
630
|
onClick={handleToggleClick}
|
|
629
|
-
aria-label={isItemCollapsed ?
|
|
631
|
+
aria-label={isItemCollapsed ? t('@astryx.sideNavItem.expand', {label}) : t('@astryx.sideNavItem.collapse', {label})}
|
|
630
632
|
aria-expanded={!isItemCollapsed}
|
|
631
633
|
aria-controls={`${id}-children`}
|
|
632
634
|
{...stylex.props(styles.expandToggle)}>
|
|
@@ -132,7 +132,7 @@ export const docs = {
|
|
|
132
132
|
},
|
|
133
133
|
{
|
|
134
134
|
name: 'status',
|
|
135
|
-
type: '
|
|
135
|
+
type: "{type: 'warning' | 'error' | 'success', message?: string}",
|
|
136
136
|
description:
|
|
137
137
|
'Status indicator object (`{ type, message }`) for validation feedback.',
|
|
138
138
|
},
|
|
@@ -286,7 +286,7 @@ export const docsZh = {
|
|
|
286
286
|
},
|
|
287
287
|
{
|
|
288
288
|
name: 'status',
|
|
289
|
-
type: '
|
|
289
|
+
type: "{type: 'warning' | 'error' | 'success', message?: string}",
|
|
290
290
|
description:
|
|
291
291
|
'验证反馈的状态指示器对象(`{ type, message }`)。',
|
|
292
292
|
},
|
package/src/Stack/Stack.doc.mjs
CHANGED
|
@@ -24,25 +24,25 @@ export const docs = {
|
|
|
24
24
|
props: [
|
|
25
25
|
{
|
|
26
26
|
name: 'gap',
|
|
27
|
-
type: '
|
|
27
|
+
type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
|
|
28
28
|
description:
|
|
29
29
|
'Spacing step (number literal): 0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10. Pass as a JSX number expression e.g. gap={4}, NOT a string like gap="4".',
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
name: 'padding',
|
|
33
|
-
type: '
|
|
33
|
+
type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
|
|
34
34
|
description:
|
|
35
35
|
'Inner padding on all sides, using the spacing scale (0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10). Matches the padding prop on Card, LayoutContent, and LayoutPanel. Pass as a JSX number expression e.g. padding={3}.',
|
|
36
36
|
},
|
|
37
37
|
{
|
|
38
38
|
name: 'paddingInline',
|
|
39
|
-
type: '
|
|
39
|
+
type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
|
|
40
40
|
description:
|
|
41
41
|
'Inline (horizontal) padding, using the spacing scale. Overrides padding on the inline axis when both are set.',
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
name: 'paddingBlock',
|
|
45
|
-
type: '
|
|
45
|
+
type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
|
|
46
46
|
description:
|
|
47
47
|
'Block (vertical) padding, using the spacing scale. Overrides padding on the block axis when both are set.',
|
|
48
48
|
},
|
|
@@ -127,25 +127,25 @@ export const docs = {
|
|
|
127
127
|
props: [
|
|
128
128
|
{
|
|
129
129
|
name: 'gap',
|
|
130
|
-
type: '
|
|
130
|
+
type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
|
|
131
131
|
description:
|
|
132
132
|
'Spacing step (number literal): 0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10. Pass as a JSX number expression e.g. gap={4}, NOT a string like gap="4".',
|
|
133
133
|
},
|
|
134
134
|
{
|
|
135
135
|
name: 'padding',
|
|
136
|
-
type: '
|
|
136
|
+
type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
|
|
137
137
|
description:
|
|
138
138
|
'Inner padding on all sides, using the spacing scale (0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10). Matches the padding prop on Card, LayoutContent, and LayoutPanel. Pass as a JSX number expression e.g. padding={3}.',
|
|
139
139
|
},
|
|
140
140
|
{
|
|
141
141
|
name: 'paddingInline',
|
|
142
|
-
type: '
|
|
142
|
+
type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
|
|
143
143
|
description:
|
|
144
144
|
'Inline (horizontal) padding, using the spacing scale. Overrides padding on the inline axis when both are set.',
|
|
145
145
|
},
|
|
146
146
|
{
|
|
147
147
|
name: 'paddingBlock',
|
|
148
|
-
type: '
|
|
148
|
+
type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
|
|
149
149
|
description:
|
|
150
150
|
'Block (vertical) padding, using the spacing scale. Overrides padding on the block axis when both are set.',
|
|
151
151
|
},
|
|
@@ -289,7 +289,7 @@ export const docsZh = {
|
|
|
289
289
|
props: [
|
|
290
290
|
{
|
|
291
291
|
name: 'gap',
|
|
292
|
-
type: '
|
|
292
|
+
type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
|
|
293
293
|
description:
|
|
294
294
|
'间距步进(数字字面量):0、0.5、1、1.5、2、3、4、5、6、8、10。在 JSX 中使用数字表达式 e.g. gap={4},不要使用字符串 gap="4"。',
|
|
295
295
|
},
|
|
@@ -358,7 +358,7 @@ export const docsZh = {
|
|
|
358
358
|
props: [
|
|
359
359
|
{
|
|
360
360
|
name: 'gap',
|
|
361
|
-
type: '
|
|
361
|
+
type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
|
|
362
362
|
description:
|
|
363
363
|
'间距步进(数字字面量):0、0.5、1、1.5、2、3、4、5、6、8、10。在 JSX 中使用数字表达式 e.g. gap={4},不要使用字符串 gap="4"。',
|
|
364
364
|
},
|
|
@@ -90,7 +90,7 @@ export const docs = {
|
|
|
90
90
|
},
|
|
91
91
|
{
|
|
92
92
|
name: 'status',
|
|
93
|
-
type: '
|
|
93
|
+
type: "{type: 'warning' | 'error' | 'success', message?: string}",
|
|
94
94
|
description:
|
|
95
95
|
'Status indicator with type and message. Displays a colored message box below the switch and sets aria-invalid when type is "error".',
|
|
96
96
|
},
|
|
@@ -107,7 +107,7 @@ export const docs = {
|
|
|
107
107
|
{
|
|
108
108
|
name: 'labelIcon',
|
|
109
109
|
type: 'IconType',
|
|
110
|
-
description: 'Icon displayed before the label text. See `
|
|
110
|
+
description: 'Icon displayed before the label text. See `astryx docs icons` for valid semantic names.',
|
|
111
111
|
},
|
|
112
112
|
{
|
|
113
113
|
name: 'labelTooltip',
|
|
@@ -236,7 +236,7 @@ export const docsZh = {
|
|
|
236
236
|
},
|
|
237
237
|
{
|
|
238
238
|
name: 'status',
|
|
239
|
-
type: '
|
|
239
|
+
type: "{type: 'warning' | 'error' | 'success', message?: string}",
|
|
240
240
|
description:
|
|
241
241
|
'带类型和消息的状态指示器。在开关下方显示彩色消息框,当类型为 "error" 时设置 aria-invalid。',
|
|
242
242
|
},
|
|
@@ -197,6 +197,22 @@ describe('Switch', () => {
|
|
|
197
197
|
expect(screen.getByLabelText('Toggle row')).toBeInTheDocument();
|
|
198
198
|
});
|
|
199
199
|
|
|
200
|
+
it('keeps description linked via aria-describedby when isLabelHidden', () => {
|
|
201
|
+
render(
|
|
202
|
+
<Switch
|
|
203
|
+
label="Toggle row"
|
|
204
|
+
isLabelHidden
|
|
205
|
+
description="Enables sync for this row"
|
|
206
|
+
value={false}
|
|
207
|
+
onChange={() => {}}
|
|
208
|
+
/>,
|
|
209
|
+
);
|
|
210
|
+
const switchEl = screen.getByRole('switch');
|
|
211
|
+
const description = screen.getByText('Enables sync for this row');
|
|
212
|
+
expect(description.id).not.toBe('');
|
|
213
|
+
expect(switchEl.getAttribute('aria-describedby')).toContain(description.id);
|
|
214
|
+
});
|
|
215
|
+
|
|
200
216
|
it('shows label visually by default', () => {
|
|
201
217
|
render(
|
|
202
218
|
<Switch label="Enable notifications" value={false} onChange={() => {}} />,
|
package/src/Switch/Switch.tsx
CHANGED
|
@@ -393,9 +393,11 @@ export function Switch({
|
|
|
393
393
|
});
|
|
394
394
|
|
|
395
395
|
// Build aria-describedby from description and status message
|
|
396
|
-
// Only include descriptionID when the element actually renders
|
|
396
|
+
// Only include descriptionID when the element actually renders.
|
|
397
|
+
// FieldLabel renders the description (with descriptionID) even when the
|
|
398
|
+
// label is visually hidden — it's sr-only, so keep it linked.
|
|
397
399
|
const describedByParts: string[] = [];
|
|
398
|
-
if (description
|
|
400
|
+
if (description) {
|
|
399
401
|
describedByParts.push(descriptionID);
|
|
400
402
|
}
|
|
401
403
|
if (status?.message) {
|
package/src/TabList/Tab.tsx
CHANGED
|
@@ -138,7 +138,11 @@ const styles = stylex.create({
|
|
|
138
138
|
},
|
|
139
139
|
indicator: {
|
|
140
140
|
position: 'absolute',
|
|
141
|
-
bottom
|
|
141
|
+
// Sits on the tab's bottom edge by default (-1px). When the tab strip
|
|
142
|
+
// reserves space for a divider rail — TabList `hasDivider` or a Toolbar
|
|
143
|
+
// with a bottom divider — that ancestor sets `--_tab-indicator-bottom`
|
|
144
|
+
// to drop the indicator onto the rail beneath the reserved gap.
|
|
145
|
+
bottom: 'var(--_tab-indicator-bottom, -1px)',
|
|
142
146
|
left: spacingVars['--spacing-3'],
|
|
143
147
|
right: spacingVars['--spacing-3'],
|
|
144
148
|
height: '2px',
|
|
@@ -92,7 +92,7 @@ export const docs = {
|
|
|
92
92
|
bestPractices: [
|
|
93
93
|
{ guidance: true, description: 'Keep tab labels short and descriptive so users can quickly scan available sections.' },
|
|
94
94
|
{ guidance: true, description: 'Use TabMenu to group overflow items when horizontal space is limited rather than scrolling tabs off-screen.' },
|
|
95
|
-
{ guidance: true, description: 'When using hasDivider with action buttons alongside tabs,
|
|
95
|
+
{ guidance: true, description: 'When using hasDivider with action buttons alongside tabs, match the Button size to the TabList size (both md, both sm) — the divided tab strip reserves space so tabs and same-size buttons align to a shared baseline above the rail.' },
|
|
96
96
|
{ guidance: false, description: 'Use tabs for sequential steps or workflows; use a stepper or wizard pattern instead.' },
|
|
97
97
|
{ guidance: false, description: 'Place more than 6–8 visible tabs before the overflow menu; prioritize the most important categories.' },
|
|
98
98
|
{ guidance: false, description: 'Confuse TabList with SegmentedControl or ToggleButton. TabList is for navigation between views. SegmentedControl and ToggleButton are input controls: SegmentedControl always has exactly one selected option, while ToggleButton can be toggled on or off.' },
|
|
@@ -113,7 +113,7 @@ export const docsZh = {
|
|
|
113
113
|
bestPractices: [
|
|
114
114
|
{ guidance: true, description: 'Keep tab labels short and descriptive so users can quickly scan available sections.' },
|
|
115
115
|
{ guidance: true, description: 'Use TabMenu to group overflow items when horizontal space is limited rather than scrolling tabs off-screen.' },
|
|
116
|
-
{ guidance: true, description: 'When using hasDivider with action buttons alongside tabs,
|
|
116
|
+
{ guidance: true, description: 'When using hasDivider with action buttons alongside tabs, match the Button size to the TabList size (both md, both sm) — the divided tab strip reserves space so tabs and same-size buttons align to a shared baseline above the rail.' },
|
|
117
117
|
{ guidance: false, description: 'Use tabs for sequential steps or workflows; use a stepper or wizard pattern instead.' },
|
|
118
118
|
{ guidance: false, description: 'Place more than 6–8 visible tabs before the overflow menu; prioritize the most important categories.' },
|
|
119
119
|
{ guidance: false, description: 'Confuse TabList with SegmentedControl or ToggleButton. TabList is for navigation between views. SegmentedControl and ToggleButton are input controls: SegmentedControl always has exactly one selected option, while ToggleButton can be toggled on or off.' },
|
|
@@ -135,7 +135,7 @@ export const docsDense = {
|
|
|
135
135
|
bestPractices: [
|
|
136
136
|
{ guidance: true, description: 'Keep tab labels short and descriptive so users can quickly scan available sections.' },
|
|
137
137
|
{ guidance: true, description: 'Use TabMenu to group overflow items when horizontal space is limited rather than scrolling tabs off-screen.' },
|
|
138
|
-
{ guidance: true, description: 'When using hasDivider with action buttons alongside tabs,
|
|
138
|
+
{ guidance: true, description: 'When using hasDivider with action buttons alongside tabs, match the Button size to the TabList size (both md, both sm) — the divided tab strip reserves space so tabs and same-size buttons align to a shared baseline above the rail.' },
|
|
139
139
|
{ guidance: false, description: 'Use tabs for sequential steps or workflows; use a stepper or wizard pattern instead.' },
|
|
140
140
|
{ guidance: false, description: 'Place more than 6–8 visible tabs before the overflow menu; prioritize the most important categories.' },
|
|
141
141
|
{ guidance: false, description: 'Confuse TabList with SegmentedControl or ToggleButton. TabList is for navigation between views. SegmentedControl and ToggleButton are input controls: SegmentedControl always has exactly one selected option, while ToggleButton can be toggled on or off.' },
|
|
@@ -323,6 +323,72 @@ describe('TabList', () => {
|
|
|
323
323
|
});
|
|
324
324
|
});
|
|
325
325
|
|
|
326
|
+
describe('TabList divider gap', () => {
|
|
327
|
+
// The divider adds the reserved gap + indicator offset via a single class
|
|
328
|
+
// (StyleX applies deterministic classes in the test env). Capture that
|
|
329
|
+
// class set once so the assertions describe intent, not opaque hashes.
|
|
330
|
+
function navClasses(hasDivider: boolean): Set<string> {
|
|
331
|
+
const {unmount} = render(
|
|
332
|
+
<TabList value="home" onChange={() => {}} hasDivider={hasDivider}>
|
|
333
|
+
<Tab value="home" label="Home" />
|
|
334
|
+
</TabList>,
|
|
335
|
+
);
|
|
336
|
+
const nav = screen.getByRole('navigation');
|
|
337
|
+
const classes = new Set(nav.className.split(/\s+/).filter(Boolean));
|
|
338
|
+
unmount();
|
|
339
|
+
return classes;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
it('adds divider-only styling classes when hasDivider is set', () => {
|
|
343
|
+
const withDivider = navClasses(true);
|
|
344
|
+
const withoutDivider = navClasses(false);
|
|
345
|
+
|
|
346
|
+
// Every class the plain nav has must still be present when divided: the
|
|
347
|
+
// divider only adds styling (border + reserved gap + indicator offset),
|
|
348
|
+
// it never removes the base nav styles.
|
|
349
|
+
for (const cls of withoutDivider) {
|
|
350
|
+
expect(withDivider.has(cls)).toBe(true);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// And it must add at least one class the undivided nav does not have.
|
|
354
|
+
const added = [...withDivider].filter(c => !withoutDivider.has(c));
|
|
355
|
+
expect(added.length).toBeGreaterThan(0);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
it('does not add divider styling to an undivided tab list (default)', () => {
|
|
359
|
+
// Default (no hasDivider) and explicit hasDivider={false} are identical:
|
|
360
|
+
// the non-divided path is untouched by the divider gap change.
|
|
361
|
+
expect(navClasses(false)).toEqual(
|
|
362
|
+
(() => {
|
|
363
|
+
const {unmount} = render(
|
|
364
|
+
<TabList value="home" onChange={() => {}}>
|
|
365
|
+
<Tab value="home" label="Home" />
|
|
366
|
+
</TabList>,
|
|
367
|
+
);
|
|
368
|
+
const nav = screen.getByRole('navigation');
|
|
369
|
+
const classes = new Set(nav.className.split(/\s+/).filter(Boolean));
|
|
370
|
+
unmount();
|
|
371
|
+
return classes;
|
|
372
|
+
})(),
|
|
373
|
+
);
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
it('keeps the selected indicator rendered under a divider', () => {
|
|
377
|
+
render(
|
|
378
|
+
<TabList value="home" onChange={() => {}} hasDivider>
|
|
379
|
+
<Tab value="home" label="Home" />
|
|
380
|
+
<Tab value="away" label="Away" />
|
|
381
|
+
</TabList>,
|
|
382
|
+
);
|
|
383
|
+
const selected = screen.getByRole('button', {name: 'Home'});
|
|
384
|
+
// The indicator span carries the selected marker; the divider must not
|
|
385
|
+
// drop it (it is repositioned onto the rail, not removed).
|
|
386
|
+
expect(
|
|
387
|
+
selected.querySelector('[data-selected="selected"]'),
|
|
388
|
+
).toBeInTheDocument();
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
|
|
326
392
|
describe('TabList keyboard navigation (roving tabindex)', () => {
|
|
327
393
|
it('exposes the tab strip as a single Tab stop (only selected tab is tabbable)', () => {
|
|
328
394
|
render(
|
package/src/TabList/TabList.tsx
CHANGED
|
@@ -29,6 +29,7 @@ import {useListFocus} from '../hooks/useListFocus';
|
|
|
29
29
|
import {useKeyboardHint} from '../hooks/useKeyboardHint';
|
|
30
30
|
import {EDGE_COMP_ATTR} from '../Layout/edgeCompensation.stylex';
|
|
31
31
|
import {themeProps} from '../utils/themeProps';
|
|
32
|
+
import {useTranslator} from '../i18n';
|
|
32
33
|
|
|
33
34
|
/**
|
|
34
35
|
* Selector matching the focusable stops in the tab strip: every Tab
|
|
@@ -95,6 +96,14 @@ const styles = stylex.create({
|
|
|
95
96
|
borderBottomWidth: borderVars['--border-width'],
|
|
96
97
|
borderBottomStyle: 'solid',
|
|
97
98
|
borderBottomColor: colorVars['--color-border'],
|
|
99
|
+
// Reserve a gap between the tabs and the divider rail so the hover pill
|
|
100
|
+
// (which fills the tab height) no longer touches the underline, and an
|
|
101
|
+
// adjacent same-size Button aligns to the tabs rather than butting the
|
|
102
|
+
// rail. The tabs keep their element-size height; this padding grows the
|
|
103
|
+
// strip. `--_tab-indicator-bottom` drops the selected indicator through
|
|
104
|
+
// the reserved gap (+ the 1px border) so it still sits on the rail.
|
|
105
|
+
paddingBlockEnd: spacingVars['--spacing-1'],
|
|
106
|
+
'--_tab-indicator-bottom': `calc(-1 * (${spacingVars['--spacing-1']} + ${borderVars['--border-width']}))`,
|
|
98
107
|
},
|
|
99
108
|
});
|
|
100
109
|
|
|
@@ -129,11 +138,13 @@ export function TabList({
|
|
|
129
138
|
onKeyDown: onKeyDownProp,
|
|
130
139
|
onFocus: onFocusProp,
|
|
131
140
|
onBlur: onBlurProp,
|
|
132
|
-
'aria-label':
|
|
141
|
+
'aria-label': ariaLabelFromProps,
|
|
133
142
|
'aria-orientation': _ariaOrientation,
|
|
134
143
|
[EDGE_COMP_ATTR]: _edgeCompAttr,
|
|
135
144
|
...restProps
|
|
136
145
|
}: TabListProps) {
|
|
146
|
+
const t = useTranslator();
|
|
147
|
+
const ariaLabel = ariaLabelFromProps ?? t('@astryx.tabList.label');
|
|
137
148
|
const size = useSize(sizeProp, 'md');
|
|
138
149
|
|
|
139
150
|
// Roving-tabindex keyboard navigation across the tab strip via the shared
|