@astryxdesign/core 0.1.9-canary.d2d84f8 → 0.1.9-canary.e00a241
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/dist/Avatar/Avatar.d.ts +6 -1
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +46 -12
- package/dist/Avatar/AvatarStatusDot.d.ts +6 -4
- package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +11 -4
- package/dist/Breadcrumbs/index.d.ts +1 -0
- package/dist/Breadcrumbs/index.d.ts.map +1 -1
- package/dist/Breadcrumbs/index.js +2 -1
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +50 -9
- package/dist/Calendar/dayCellUtils.d.ts +4 -4
- package/dist/Calendar/dayCellUtils.js +2 -2
- 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.js +1 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +22 -12
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +3 -1
- package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
- package/dist/Chat/ChatMessageBubble.js +8 -8
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +10 -3
- package/dist/CheckboxInput/CheckboxInput.js +4 -4
- 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/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +13 -7
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +3 -1
- package/dist/CommandPalette/CommandPalette.d.ts +1 -1
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +42 -3
- 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 +1 -0
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +31 -19
- package/dist/DateRangeInput/DateRangeInput.d.ts +1 -0
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +20 -19
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +23 -18
- package/dist/Divider/Divider.d.ts +2 -2
- package/dist/Divider/Divider.d.ts.map +1 -1
- package/dist/Divider/Divider.js +13 -0
- 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.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +4 -1
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +4 -1
- 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 +4 -1
- 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 +4 -1
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +4 -2
- package/dist/FileInput/FileInput.d.ts +1 -0
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +91 -65
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +10 -4
- package/dist/Icon/Icon.d.ts +15 -1
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +19 -3
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +15 -9
- package/dist/List/List.d.ts.map +1 -1
- package/dist/List/List.js +6 -3
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +7 -0
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +65 -40
- package/dist/NumberInput/NumberInput.d.ts +1 -0
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +20 -17
- package/dist/Outline/Outline.js +2 -2
- package/dist/RadioList/RadioList.d.ts +2 -2
- package/dist/RadioList/RadioListItem.js +4 -4
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +49 -19
- 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/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +58 -16
- 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/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 +87 -34
- package/dist/Spinner/Spinner.d.ts +3 -2
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +11 -2
- 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/TabList.d.ts +2 -11
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +5 -9
- package/dist/TabList/TabListContext.d.ts +0 -5
- package/dist/TabList/TabListContext.d.ts.map +1 -1
- package/dist/TabList/TabListContext.js +0 -5
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +30 -4
- 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/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +3 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +14 -6
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.js +29 -23
- package/dist/Table/types.d.ts +32 -0
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/TextArea/TextArea.d.ts +1 -0
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +16 -19
- package/dist/TextInput/TextInput.d.ts +1 -0
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +18 -17
- package/dist/TimeInput/TimeInput.d.ts +1 -0
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +15 -17
- package/dist/Timestamp/Timestamp.d.ts +31 -3
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +47 -76
- package/dist/Timestamp/formatInstant.d.ts +41 -0
- package/dist/Timestamp/formatInstant.d.ts.map +1 -0
- package/dist/Timestamp/formatInstant.js +177 -0
- package/dist/Timestamp/index.d.ts +1 -0
- package/dist/Timestamp/index.d.ts.map +1 -1
- package/dist/Timestamp/tooltipEntries.d.ts +56 -0
- package/dist/Timestamp/tooltipEntries.d.ts.map +1 -0
- package/dist/Timestamp/tooltipEntries.js +163 -0
- 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.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +2 -2
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +17 -1
- package/dist/TopNav/TopNavItem.d.ts +3 -1
- package/dist/TopNav/TopNavItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavItem.js +30 -3
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +1 -0
- package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
- package/dist/TreeList/TreeListBranches.js +8 -6
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +32 -14
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +19 -10
- package/dist/Typeahead/Typeahead.js +1 -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 +38 -14
- package/dist/astryx.umd.js +52 -52
- package/dist/astryx.umd.js.map +4 -4
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- 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/useAnnounce.d.ts +3 -0
- package/dist/hooks/useAnnounce.d.ts.map +1 -1
- package/dist/hooks/useAnnounce.js +39 -1
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +52 -11
- 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/useHotkeys.d.ts +9 -0
- package/dist/hooks/useHotkeys.d.ts.map +1 -1
- package/dist/hooks/useHotkeys.js +9 -0
- 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/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +13 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -1
- package/dist/utils/plainDate.d.ts +17 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +23 -4
- 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/locales/en.json +76 -0
- package/locales/pseudo.json +57 -0
- package/package.json +6 -1
- package/src/Avatar/Avatar.doc.mjs +18 -4
- package/src/Avatar/Avatar.test.tsx +106 -0
- package/src/Avatar/Avatar.tsx +62 -10
- package/src/Avatar/AvatarStatusDot.doc.mjs +4 -4
- package/src/Avatar/AvatarStatusDot.tsx +6 -4
- package/src/AvatarGroup/AvatarGroup.test.tsx +16 -1
- package/src/Breadcrumbs/BreadcrumbItem.tsx +10 -10
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +51 -0
- package/src/Breadcrumbs/index.ts +4 -0
- package/src/Button/Button.doc.mjs +0 -4
- package/src/Calendar/Calendar.test.tsx +170 -20
- package/src/Calendar/Calendar.tsx +73 -16
- package/src/Calendar/dayCellUtils.test.ts +18 -18
- package/src/Calendar/dayCellUtils.ts +2 -2
- package/src/Calendar/styles.ts +33 -39
- package/src/Card/Card.tsx +1 -1
- package/src/Carousel/Carousel.tsx +25 -6
- package/src/Chat/ChatComposer.doc.mjs +2 -2
- package/src/Chat/ChatComposerInput.doc.mjs +1 -1
- package/src/Chat/ChatDictationButton.tsx +7 -1
- package/src/Chat/ChatMessageBubble.tsx +15 -10
- package/src/Chat/ChatSystemMessage.test.tsx +5 -0
- package/src/Chat/ChatToolCalls.tsx +9 -2
- package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
- package/src/CheckboxInput/CheckboxInput.tsx +4 -4
- package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
- 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/CodeBlock/CodeBlock.tsx +35 -8
- 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.test.tsx +95 -1
- package/src/CommandPalette/CommandPalette.tsx +41 -2
- package/src/ContextMenu/ContextMenu.test.tsx +42 -0
- package/src/ContextMenu/ContextMenu.tsx +13 -11
- package/src/ContextMenu/index.ts +5 -0
- package/src/DateInput/DateInput.doc.mjs +15 -5
- package/src/DateInput/DateInput.test.tsx +210 -3
- package/src/DateInput/DateInput.tsx +41 -29
- package/src/DateRangeInput/DateRangeInput.doc.mjs +11 -3
- package/src/DateRangeInput/DateRangeInput.test.tsx +120 -3
- package/src/DateRangeInput/DateRangeInput.tsx +29 -27
- package/src/DateTimeInput/DateTimeInput.doc.mjs +22 -1
- package/src/DateTimeInput/DateTimeInput.test.tsx +112 -0
- package/src/DateTimeInput/DateTimeInput.tsx +44 -39
- package/src/Divider/Divider.test.tsx +32 -8
- package/src/Divider/Divider.tsx +14 -1
- package/src/DropdownMenu/DropdownMenu.test.tsx +60 -0
- package/src/DropdownMenu/DropdownMenu.tsx +31 -12
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +8 -2
- package/src/DropdownMenu/DropdownMenuItem.tsx +8 -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.tsx +14 -9
- package/src/Field/inputStyles.stylex.ts +2 -0
- package/src/FieldStatus/FieldStatus.tsx +10 -4
- package/src/FileInput/FileInput.doc.mjs +13 -7
- package/src/FileInput/FileInput.test.tsx +84 -16
- package/src/FileInput/FileInput.tsx +96 -79
- package/src/HoverCard/useHoverCard.tsx +15 -3
- package/src/Icon/Icon.doc.mjs +13 -0
- package/src/Icon/Icon.test.tsx +89 -0
- package/src/Icon/Icon.tsx +51 -3
- package/src/Lightbox/Lightbox.tsx +11 -3
- package/src/List/List.test.tsx +17 -29
- package/src/List/List.tsx +6 -1
- package/src/Markdown/Markdown.test.tsx +21 -0
- package/src/Markdown/Markdown.tsx +4 -0
- package/src/MultiSelector/MultiSelector.doc.mjs +11 -0
- package/src/MultiSelector/MultiSelector.test.tsx +306 -3
- package/src/MultiSelector/MultiSelector.tsx +88 -57
- package/src/NumberInput/NumberInput.doc.mjs +11 -5
- package/src/NumberInput/NumberInput.test.tsx +48 -0
- package/src/NumberInput/NumberInput.tsx +25 -26
- package/src/Outline/Outline.test.tsx +12 -12
- package/src/Outline/Outline.tsx +2 -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/Resizable/ResizeHandle.test.tsx +94 -0
- package/src/Resizable/ResizeHandle.tsx +70 -20
- package/src/SegmentedControl/SegmentedControlItem.tsx +2 -0
- package/src/Selector/Selector.doc.mjs +8 -0
- package/src/Selector/Selector.test.tsx +328 -3
- package/src/Selector/Selector.tsx +70 -19
- package/src/SideNav/SideNav.tsx +1 -8
- package/src/SideNav/SideNavCollapseButton.tsx +9 -7
- package/src/SideNav/SideNavItem.tsx +5 -3
- package/src/Slider/Slider.doc.mjs +6 -0
- package/src/Slider/Slider.test.tsx +240 -12
- package/src/Slider/Slider.tsx +96 -23
- package/src/Spinner/Spinner.test.tsx +10 -8
- package/src/Spinner/Spinner.tsx +15 -5
- package/src/Switch/Switch.doc.mjs +142 -42
- package/src/Switch/Switch.test.tsx +22 -0
- package/src/Switch/Switch.tsx +90 -33
- package/src/TabList/TabList.doc.mjs +0 -6
- package/src/TabList/TabList.test.tsx +3 -15
- package/src/TabList/TabList.tsx +6 -17
- package/src/TabList/TabListContext.ts +0 -6
- package/src/Table/BaseTable.tsx +34 -2
- package/src/Table/Table.doc.mjs +11 -0
- package/src/Table/Table.test.tsx +85 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +9 -6
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +24 -17
- package/src/Table/plugins/selection/useTableSelection.test.tsx +61 -3
- package/src/Table/plugins/selection/useTableSelection.tsx +3 -0
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +37 -8
- package/src/Table/plugins/tree/useTableTreeData.tsx +17 -13
- package/src/Table/types.ts +33 -0
- package/src/Table/useTableRowStatus.doc.mjs +1 -1
- package/src/TextArea/TextArea.doc.mjs +11 -5
- package/src/TextArea/TextArea.tsx +17 -26
- package/src/TextInput/TextInput.doc.mjs +11 -5
- package/src/TextInput/TextInput.test.tsx +130 -3
- package/src/TextInput/TextInput.tsx +18 -25
- package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
- package/src/TimeInput/TimeInput.doc.mjs +11 -5
- package/src/TimeInput/TimeInput.tsx +14 -25
- package/src/Timestamp/Timestamp.doc.mjs +32 -6
- package/src/Timestamp/Timestamp.test.tsx +371 -0
- package/src/Timestamp/Timestamp.tsx +96 -93
- package/src/Timestamp/formatInstant.ts +218 -0
- package/src/Timestamp/index.ts +4 -0
- package/src/Timestamp/tooltipEntries.test.ts +552 -0
- package/src/Timestamp/tooltipEntries.ts +210 -0
- 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 +8 -1
- package/src/Tokenizer/Tokenizer.tsx +4 -2
- package/src/Tooltip/Tooltip.test.tsx +46 -0
- package/src/Tooltip/useTooltip.tsx +20 -0
- package/src/TopNav/TopNav.test.tsx +93 -2
- package/src/TopNav/TopNavItem.doc.mjs +3 -3
- package/src/TopNav/TopNavItem.tsx +35 -6
- package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +1 -1
- package/src/TreeList/TreeList.doc.mjs +6 -0
- package/src/TreeList/TreeList.test.tsx +50 -10
- package/src/TreeList/TreeList.tsx +5 -0
- package/src/TreeList/TreeListBranches.tsx +8 -6
- package/src/TreeList/TreeListItem.tsx +33 -11
- package/src/Typeahead/BaseTypeahead.tsx +29 -14
- package/src/Typeahead/Typeahead.doc.mjs +6 -0
- package/src/Typeahead/Typeahead.test.tsx +27 -0
- package/src/Typeahead/Typeahead.tsx +1 -1
- package/src/Typeahead/TypeaheadItem.tsx +2 -1
- package/src/__tests__/inputWidthContract.test.tsx +62 -0
- package/src/doc-mjs.d.ts +19 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/isRtlElement.ts +27 -0
- package/src/hooks/useAnnounce.test.tsx +75 -2
- package/src/hooks/useAnnounce.ts +47 -1
- package/src/hooks/useFocusTrap.test.tsx +104 -0
- package/src/hooks/useFocusTrap.ts +61 -12
- 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/useHotkeys.ts +9 -0
- 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/reset.css +0 -26
- package/src/reset.test.ts +60 -0
- package/src/theme/derivedVarRegistry.test.ts +1 -0
- package/src/theme/derivedVarRegistry.ts +6 -0
- package/src/theme/generateThemeRules.test.ts +42 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/plainDate.test.ts +24 -6
- package/src/utils/plainDate.ts +18 -4
- package/src/utils/rtlStyles.ts +27 -0
|
@@ -68,6 +68,28 @@ describe('Switch', () => {
|
|
|
68
68
|
expect(screen.getByRole('switch')).toBeChecked();
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
+
it('renders with custom size prop (sm / md)', () => {
|
|
72
|
+
const {rerender} = render(
|
|
73
|
+
<Switch
|
|
74
|
+
label="Small switch"
|
|
75
|
+
value={false}
|
|
76
|
+
size="sm"
|
|
77
|
+
onChange={() => {}}
|
|
78
|
+
/>,
|
|
79
|
+
);
|
|
80
|
+
expect(screen.getByRole('switch')).toBeInTheDocument();
|
|
81
|
+
|
|
82
|
+
rerender(
|
|
83
|
+
<Switch
|
|
84
|
+
label="Medium switch"
|
|
85
|
+
value={false}
|
|
86
|
+
size="md"
|
|
87
|
+
onChange={() => {}}
|
|
88
|
+
/>,
|
|
89
|
+
);
|
|
90
|
+
expect(screen.getByRole('switch')).toBeInTheDocument();
|
|
91
|
+
});
|
|
92
|
+
|
|
71
93
|
it('calls onChange with new checked state when clicked', async () => {
|
|
72
94
|
const user = userEvent.setup();
|
|
73
95
|
const handleChange = vi.fn();
|
package/src/Switch/Switch.tsx
CHANGED
|
@@ -47,17 +47,75 @@ import type {SizeValue} from '../utils/types';
|
|
|
47
47
|
import {themeProps} from '../utils/themeProps';
|
|
48
48
|
import {VisuallyHidden} from '../VisuallyHidden';
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
50
|
+
const wrapperSizeStyles = stylex.create({
|
|
51
|
+
sm: {
|
|
52
|
+
width: 32,
|
|
53
|
+
height: 20,
|
|
54
|
+
},
|
|
55
|
+
md: {
|
|
56
|
+
width: 40,
|
|
57
|
+
height: 24,
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const inputSizeStyles = stylex.create({
|
|
62
|
+
sm: {
|
|
63
|
+
width: 32,
|
|
64
|
+
height: 20,
|
|
65
|
+
},
|
|
66
|
+
md: {
|
|
67
|
+
width: 40,
|
|
68
|
+
height: 24,
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const trackSizeStyles = stylex.create({
|
|
73
|
+
sm: {
|
|
74
|
+
width: 32,
|
|
75
|
+
height: 20,
|
|
76
|
+
padding: 2,
|
|
77
|
+
},
|
|
78
|
+
md: {
|
|
79
|
+
width: 40,
|
|
80
|
+
height: 24,
|
|
81
|
+
padding: 4,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const thumbOffSizeStyles = stylex.create({
|
|
86
|
+
sm: {
|
|
87
|
+
width: 14,
|
|
88
|
+
height: 14,
|
|
89
|
+
transform: 'translateX(0)',
|
|
90
|
+
},
|
|
91
|
+
md: {
|
|
92
|
+
width: 16,
|
|
93
|
+
height: 16,
|
|
94
|
+
transform: 'translateX(0)',
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const thumbOnSizeStyles = stylex.create({
|
|
99
|
+
sm: {
|
|
100
|
+
width: 16,
|
|
101
|
+
height: 16,
|
|
102
|
+
transform: 'translateX(12px)',
|
|
103
|
+
},
|
|
104
|
+
md: {
|
|
105
|
+
width: 20,
|
|
106
|
+
height: 20,
|
|
107
|
+
transform: 'translateX(14px)',
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const labelWrapperSizeStyles = stylex.create({
|
|
112
|
+
sm: {
|
|
113
|
+
minHeight: 20,
|
|
114
|
+
},
|
|
115
|
+
md: {
|
|
116
|
+
minHeight: 24,
|
|
117
|
+
},
|
|
118
|
+
});
|
|
61
119
|
|
|
62
120
|
const styles = stylex.create({
|
|
63
121
|
container: {
|
|
@@ -77,8 +135,6 @@ const styles = stylex.create({
|
|
|
77
135
|
display: 'flex',
|
|
78
136
|
alignItems: 'center',
|
|
79
137
|
flexShrink: 0,
|
|
80
|
-
width: SWITCH_WIDTH,
|
|
81
|
-
height: SWITCH_HEIGHT,
|
|
82
138
|
isolation: 'isolate',
|
|
83
139
|
},
|
|
84
140
|
input: {
|
|
@@ -88,8 +144,6 @@ const styles = stylex.create({
|
|
|
88
144
|
opacity: 0,
|
|
89
145
|
cursor: 'pointer',
|
|
90
146
|
zIndex: 1,
|
|
91
|
-
width: SWITCH_WIDTH,
|
|
92
|
-
height: SWITCH_HEIGHT,
|
|
93
147
|
},
|
|
94
148
|
inputDisabled: {
|
|
95
149
|
cursor: 'not-allowed',
|
|
@@ -100,9 +154,6 @@ const styles = stylex.create({
|
|
|
100
154
|
track: {
|
|
101
155
|
display: 'flex',
|
|
102
156
|
alignItems: 'center',
|
|
103
|
-
width: SWITCH_WIDTH,
|
|
104
|
-
height: SWITCH_HEIGHT,
|
|
105
|
-
padding: TRACK_PADDING,
|
|
106
157
|
borderRadius: radiusVars['--radius-full'],
|
|
107
158
|
transitionProperty: 'background-color',
|
|
108
159
|
transitionDuration: {
|
|
@@ -159,22 +210,11 @@ const styles = stylex.create({
|
|
|
159
210
|
},
|
|
160
211
|
transitionTimingFunction: easeVars['--ease-standard'],
|
|
161
212
|
},
|
|
162
|
-
thumbOff: {
|
|
163
|
-
width: THUMB_SIZE_OFF,
|
|
164
|
-
height: THUMB_SIZE_OFF,
|
|
165
|
-
transform: 'translateX(0)',
|
|
166
|
-
},
|
|
167
|
-
thumbOn: {
|
|
168
|
-
width: THUMB_SIZE_ON,
|
|
169
|
-
height: THUMB_SIZE_ON,
|
|
170
|
-
transform: `translateX(${THUMB_TRAVEL_ON}px)`,
|
|
171
|
-
},
|
|
172
213
|
labelWrapper: {
|
|
173
214
|
display: 'flex',
|
|
174
215
|
flexDirection: 'column',
|
|
175
216
|
gap: spacingVars['--spacing-0-5'],
|
|
176
217
|
justifyContent: 'center',
|
|
177
|
-
minHeight: SWITCH_HEIGHT,
|
|
178
218
|
},
|
|
179
219
|
description: {
|
|
180
220
|
fontFamily: typographyVars['--font-family-body'],
|
|
@@ -313,6 +353,13 @@ export interface SwitchProps extends Omit<BaseProps, 'onChange'> {
|
|
|
313
353
|
* When set with a message, displays a colored message box below the switch.
|
|
314
354
|
*/
|
|
315
355
|
status?: InputStatus;
|
|
356
|
+
/**
|
|
357
|
+
* Size variant controlling track and thumb dimensions.
|
|
358
|
+
* - 'sm': 34x20px (matches sm checkbox/radio vertical rhythm)
|
|
359
|
+
* - 'md': 40x24px (default, matches md checkbox/radio vertical rhythm)
|
|
360
|
+
* @default 'md'
|
|
361
|
+
*/
|
|
362
|
+
size?: 'sm' | 'md';
|
|
316
363
|
}
|
|
317
364
|
|
|
318
365
|
// Dynamic field width (number -> px, string used as-is).
|
|
@@ -358,6 +405,7 @@ export function Switch({
|
|
|
358
405
|
labelPosition = 'end',
|
|
359
406
|
labelSpacing = 'hug',
|
|
360
407
|
status,
|
|
408
|
+
size = 'md',
|
|
361
409
|
width,
|
|
362
410
|
xstyle,
|
|
363
411
|
className,
|
|
@@ -410,7 +458,7 @@ export function Switch({
|
|
|
410
458
|
describedByParts.length > 0 ? describedByParts.join(' ') : undefined;
|
|
411
459
|
|
|
412
460
|
const switchElement = (
|
|
413
|
-
<div {...stylex.props(styles.switchWrapper)}>
|
|
461
|
+
<div {...stylex.props(styles.switchWrapper, wrapperSizeStyles[size])}>
|
|
414
462
|
<input
|
|
415
463
|
ref={mergeRefs(ref, disabledMessageTooltip.positionRef)}
|
|
416
464
|
id={id}
|
|
@@ -447,6 +495,7 @@ export function Switch({
|
|
|
447
495
|
aria-busy={isBusy || undefined}
|
|
448
496
|
{...stylex.props(
|
|
449
497
|
styles.input,
|
|
498
|
+
inputSizeStyles[size],
|
|
450
499
|
isDisabled && styles.inputDisabled,
|
|
451
500
|
isBusy && styles.inputBusy,
|
|
452
501
|
)}
|
|
@@ -457,9 +506,11 @@ export function Switch({
|
|
|
457
506
|
themeProps('switch', {
|
|
458
507
|
checked: isOn ? 'checked' : null,
|
|
459
508
|
disabled: isDisabled ? 'disabled' : null,
|
|
509
|
+
size,
|
|
460
510
|
}),
|
|
461
511
|
stylex.props(
|
|
462
512
|
styles.track,
|
|
513
|
+
trackSizeStyles[size],
|
|
463
514
|
isOn ? styles.trackOn : styles.trackOff,
|
|
464
515
|
!isDisabled && styles.trackFocus,
|
|
465
516
|
isDisabled && styles.trackDisabled,
|
|
@@ -468,8 +519,14 @@ export function Switch({
|
|
|
468
519
|
)}>
|
|
469
520
|
<div
|
|
470
521
|
{...mergeProps(
|
|
471
|
-
themeProps('switch-thumb', {
|
|
472
|
-
|
|
522
|
+
themeProps('switch-thumb', {
|
|
523
|
+
checked: isOn ? 'checked' : null,
|
|
524
|
+
size,
|
|
525
|
+
}),
|
|
526
|
+
stylex.props(
|
|
527
|
+
styles.thumb,
|
|
528
|
+
isOn ? thumbOnSizeStyles[size] : thumbOffSizeStyles[size],
|
|
529
|
+
),
|
|
473
530
|
)}>
|
|
474
531
|
{isBusy && <Spinner size="sm" />}
|
|
475
532
|
</div>
|
|
@@ -479,7 +536,7 @@ export function Switch({
|
|
|
479
536
|
);
|
|
480
537
|
|
|
481
538
|
const labelElement = (
|
|
482
|
-
<div {...stylex.props(styles.labelWrapper)}>
|
|
539
|
+
<div {...stylex.props(styles.labelWrapper, labelWrapperSizeStyles[size])}>
|
|
483
540
|
<FieldLabel
|
|
484
541
|
label={label}
|
|
485
542
|
inputID={id}
|
|
@@ -55,12 +55,6 @@ export const docs = {
|
|
|
55
55
|
description: 'Whether to show a bottom border divider under the tab list.',
|
|
56
56
|
default: 'false',
|
|
57
57
|
},
|
|
58
|
-
{
|
|
59
|
-
name: 'orientation',
|
|
60
|
-
type: "'horizontal' | 'vertical'",
|
|
61
|
-
description: "Orientation of the tab strip, controlling which arrow keys move focus between tabs and the reported aria-orientation. 'horizontal': ArrowLeft/ArrowRight. 'vertical': ArrowUp/ArrowDown. Both axes' arrows are accepted regardless.",
|
|
62
|
-
default: "'horizontal'",
|
|
63
|
-
},
|
|
64
58
|
{
|
|
65
59
|
name: 'children',
|
|
66
60
|
type: 'ReactNode',
|
|
@@ -77,10 +77,9 @@ describe('TabList', () => {
|
|
|
77
77
|
|
|
78
78
|
it('does not set aria-orientation on the nav (invalid for role navigation)', () => {
|
|
79
79
|
// Regression: aria-orientation is not an allowed attribute on the
|
|
80
|
-
// navigation role and produces an axe aria-allowed-attr violation.
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
const {rerender} = render(
|
|
80
|
+
// navigation role and produces an axe aria-allowed-attr violation.
|
|
81
|
+
// TabList deliberately never sets this attribute.
|
|
82
|
+
render(
|
|
84
83
|
<TabList value="home" onChange={() => {}}>
|
|
85
84
|
<Tab value="home" label="Home" />
|
|
86
85
|
<Tab value="settings" label="Settings" />
|
|
@@ -90,17 +89,6 @@ describe('TabList', () => {
|
|
|
90
89
|
expect(screen.getByRole('navigation')).not.toHaveAttribute(
|
|
91
90
|
'aria-orientation',
|
|
92
91
|
);
|
|
93
|
-
|
|
94
|
-
rerender(
|
|
95
|
-
<TabList value="home" onChange={() => {}} orientation="vertical">
|
|
96
|
-
<Tab value="home" label="Home" />
|
|
97
|
-
<Tab value="settings" label="Settings" />
|
|
98
|
-
</TabList>,
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
expect(screen.getByRole('navigation')).not.toHaveAttribute(
|
|
102
|
-
'aria-orientation',
|
|
103
|
-
);
|
|
104
92
|
});
|
|
105
93
|
|
|
106
94
|
it('ignores a consumer-supplied aria-orientation on the nav', () => {
|
package/src/TabList/TabList.tsx
CHANGED
|
@@ -22,7 +22,7 @@ import * as stylex from '@stylexjs/stylex';
|
|
|
22
22
|
import {borderVars, colorVars, spacingVars} from '../theme/tokens.stylex';
|
|
23
23
|
import type {BaseProps} from '../BaseProps';
|
|
24
24
|
import {TabListContext} from './TabListContext';
|
|
25
|
-
import type {
|
|
25
|
+
import type {TabListSize} from './TabListContext';
|
|
26
26
|
import {useSize} from '../SizeContext/SizeContext';
|
|
27
27
|
import {mergeProps, mergeRefs} from '../utils';
|
|
28
28
|
import {useListFocus} from '../hooks/useListFocus';
|
|
@@ -66,15 +66,6 @@ export interface TabListProps extends Omit<BaseProps<HTMLElement>, 'onChange'> {
|
|
|
66
66
|
* @default false
|
|
67
67
|
*/
|
|
68
68
|
hasDivider?: boolean;
|
|
69
|
-
/**
|
|
70
|
-
* Orientation of the tab strip, controlling which arrow keys move
|
|
71
|
-
* focus between tabs.
|
|
72
|
-
* - `'horizontal'` (default): ArrowLeft / ArrowRight (ArrowUp / ArrowDown
|
|
73
|
-
* also work per the WAI-ARIA APG).
|
|
74
|
-
* - `'vertical'`: ArrowUp / ArrowDown (ArrowLeft / ArrowRight also work).
|
|
75
|
-
* @default 'horizontal'
|
|
76
|
-
*/
|
|
77
|
-
orientation?: TabListOrientation;
|
|
78
69
|
/**
|
|
79
70
|
* Tab and TabMenu children.
|
|
80
71
|
*/
|
|
@@ -130,7 +121,6 @@ export function TabList({
|
|
|
130
121
|
size: sizeProp,
|
|
131
122
|
layout = 'hug',
|
|
132
123
|
hasDivider = false,
|
|
133
|
-
orientation = 'horizontal',
|
|
134
124
|
xstyle,
|
|
135
125
|
className,
|
|
136
126
|
style,
|
|
@@ -150,14 +140,13 @@ export function TabList({
|
|
|
150
140
|
// Roving-tabindex keyboard navigation across the tab strip via the shared
|
|
151
141
|
// hook. `orientation: 'both'` accepts both arrow axes per the WAI-ARIA APG
|
|
152
142
|
// allowance for tab strips (ArrowRight/ArrowDown advance, ArrowLeft/ArrowUp
|
|
153
|
-
// retreat)
|
|
154
|
-
//
|
|
155
|
-
//
|
|
156
|
-
// navigation role and triggers an axe `aria-allowed-attr` violation.
|
|
143
|
+
// retreat). We do not set `aria-orientation` on the `<nav>`: that attribute
|
|
144
|
+
// is invalid on the navigation role and triggers an axe `aria-allowed-attr`
|
|
145
|
+
// violation.
|
|
157
146
|
//
|
|
158
147
|
// `hasRovingTabIndex` makes the hook own the single tab stop: it stamps
|
|
159
148
|
// tabindex 0/-1, repairs the stop on mount and as stops mount/unmount or
|
|
160
|
-
// toggle disabled, and
|
|
149
|
+
// toggle disabled, and -- via `handleFocus` on the nav -- keeps the stop in
|
|
161
150
|
// sync after clicks or programmatic focus. Individual Tabs still render
|
|
162
151
|
// `tabIndex={isSelected ? 0 : -1}` (see Tab.tsx) as the initial source of
|
|
163
152
|
// truth; the hook's repair preserves an existing tab stop and only promotes
|
|
@@ -173,7 +162,7 @@ export function TabList({
|
|
|
173
162
|
onKeyDown: onHintKeyDown,
|
|
174
163
|
onFocus: onHintFocus,
|
|
175
164
|
onBlur: onHintBlur,
|
|
176
|
-
} = useKeyboardHint(
|
|
165
|
+
} = useKeyboardHint();
|
|
177
166
|
|
|
178
167
|
const contextValue = useMemo(
|
|
179
168
|
() => ({value, onChange, size, layout}),
|
|
@@ -26,12 +26,6 @@ export type TabListSize = 'sm' | 'md' | 'lg';
|
|
|
26
26
|
*/
|
|
27
27
|
export type TabListLayout = 'hug' | 'fill';
|
|
28
28
|
|
|
29
|
-
/**
|
|
30
|
-
* Orientation of the tab strip. Controls which arrow keys move focus
|
|
31
|
-
* between tabs and the reported `aria-orientation`.
|
|
32
|
-
*/
|
|
33
|
-
export type TabListOrientation = 'horizontal' | 'vertical';
|
|
34
|
-
|
|
35
29
|
/**
|
|
36
30
|
* Context for communicating value/onChange/size/layout from TabList to children.
|
|
37
31
|
*/
|
package/src/Table/BaseTable.tsx
CHANGED
|
@@ -134,6 +134,12 @@ interface TableRowProps<T extends Record<string, unknown>> {
|
|
|
134
134
|
textOverflow: 'wrap' | 'truncate';
|
|
135
135
|
RowComponent: React.ComponentType<TableRowComponentProps>;
|
|
136
136
|
CellComponent: React.ComponentType<TableCellComponentProps>;
|
|
137
|
+
/**
|
|
138
|
+
* 1-based ARIA row index for this row's position in the full dataset.
|
|
139
|
+
* `undefined` when the table hasn't opted into ARIA row indexing, in which
|
|
140
|
+
* case no `aria-rowindex` is emitted (native table semantics).
|
|
141
|
+
*/
|
|
142
|
+
ariaRowIndex?: number;
|
|
137
143
|
}
|
|
138
144
|
|
|
139
145
|
/**
|
|
@@ -150,6 +156,7 @@ function TableRowInner<T extends Record<string, unknown>>({
|
|
|
150
156
|
textOverflow,
|
|
151
157
|
RowComponent,
|
|
152
158
|
CellComponent,
|
|
159
|
+
ariaRowIndex,
|
|
153
160
|
}: TableRowProps<T>): ReactElement {
|
|
154
161
|
// Build cells first
|
|
155
162
|
const cells = columns.map((col, columnIndex) => {
|
|
@@ -211,12 +218,14 @@ function TableRowInner<T extends Record<string, unknown>>({
|
|
|
211
218
|
);
|
|
212
219
|
});
|
|
213
220
|
|
|
214
|
-
// Apply plugin transforms for row (with pre-rendered children)
|
|
221
|
+
// Apply plugin transforms for row (with pre-rendered children).
|
|
222
|
+
// Seed `aria-rowindex` (when the table opts into ARIA row indexing) as a
|
|
223
|
+
// base htmlProp so plugins compose over it and can still override.
|
|
215
224
|
const rowRenderProps = applyPlugins(
|
|
216
225
|
plugins,
|
|
217
226
|
p => p.transformBodyRow,
|
|
218
227
|
{
|
|
219
|
-
htmlProps: {},
|
|
228
|
+
htmlProps: ariaRowIndex == null ? {} : {'aria-rowindex': ariaRowIndex},
|
|
220
229
|
xstyle: [],
|
|
221
230
|
children: <>{cells}</>,
|
|
222
231
|
} satisfies BodyRowRenderProps,
|
|
@@ -256,6 +265,9 @@ function areRowPropsEqual<T extends Record<string, unknown>>(
|
|
|
256
265
|
if (prevProps.rowIndex !== nextProps.rowIndex) {
|
|
257
266
|
return false;
|
|
258
267
|
}
|
|
268
|
+
if (prevProps.ariaRowIndex !== nextProps.ariaRowIndex) {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
259
271
|
|
|
260
272
|
if (prevProps.columns !== nextProps.columns) {
|
|
261
273
|
return false;
|
|
@@ -323,6 +335,8 @@ function BaseTableInner<T extends Record<string, unknown>>({
|
|
|
323
335
|
textOverflow = 'wrap',
|
|
324
336
|
scrollWrapper: ScrollWrapper,
|
|
325
337
|
emptyState,
|
|
338
|
+
rowIndexStart,
|
|
339
|
+
rowCount,
|
|
326
340
|
xstyle,
|
|
327
341
|
className,
|
|
328
342
|
style,
|
|
@@ -333,6 +347,18 @@ function BaseTableInner<T extends Record<string, unknown>>({
|
|
|
333
347
|
// Use stable empty array when no plugins provided
|
|
334
348
|
const plugins = pluginsProp ?? (EMPTY_PLUGINS as TablePlugin<T>[]);
|
|
335
349
|
|
|
350
|
+
// ARIA row indexing. The row ordinal is an accessibility concern that is
|
|
351
|
+
// independent of any visible index column: when the consumer opts in (by
|
|
352
|
+
// passing rowIndexStart or rowCount), body rows carry `aria-rowindex`
|
|
353
|
+
// reflecting their position in the full dataset, and the <table> carries
|
|
354
|
+
// `aria-rowcount`. `aria-rowindex` is 1-based and counts data rows from
|
|
355
|
+
// `rowIndexStart` (default 1); a windowed/paginated view passes the offset
|
|
356
|
+
// of its first visible row. `aria-rowcount` is `rowCount` when known, or
|
|
357
|
+
// `-1` (ARIA's "unknown count") for a windowed view with an unknown total.
|
|
358
|
+
const ariaRowIndexingEnabled = rowIndexStart != null || rowCount != null;
|
|
359
|
+
const firstRowAriaIndex = rowIndexStart ?? 1;
|
|
360
|
+
const ariaRowCount = ariaRowIndexingEnabled ? (rowCount ?? -1) : undefined;
|
|
361
|
+
|
|
336
362
|
const RowComponent = TableRow as React.ComponentType<TableRowComponentProps>;
|
|
337
363
|
const CellComponent =
|
|
338
364
|
TableCell as React.ComponentType<TableCellComponentProps>;
|
|
@@ -486,6 +512,7 @@ function BaseTableInner<T extends Record<string, unknown>>({
|
|
|
486
512
|
let tableElement: ReactNode = (
|
|
487
513
|
<table
|
|
488
514
|
ref={ref}
|
|
515
|
+
{...(ariaRowCount != null ? {'aria-rowcount': ariaRowCount} : null)}
|
|
489
516
|
{...tableRenderProps.htmlProps}
|
|
490
517
|
{...mergeProps(
|
|
491
518
|
themeProps('base-table'),
|
|
@@ -530,6 +557,11 @@ function BaseTableInner<T extends Record<string, unknown>>({
|
|
|
530
557
|
textOverflow={textOverflow}
|
|
531
558
|
RowComponent={RowComponent}
|
|
532
559
|
CellComponent={CellComponent}
|
|
560
|
+
ariaRowIndex={
|
|
561
|
+
ariaRowIndexingEnabled
|
|
562
|
+
? firstRowAriaIndex + rowIndex
|
|
563
|
+
: undefined
|
|
564
|
+
}
|
|
533
565
|
/>
|
|
534
566
|
);
|
|
535
567
|
})
|
package/src/Table/Table.doc.mjs
CHANGED
|
@@ -93,6 +93,17 @@ export const docs = {
|
|
|
93
93
|
type: 'Record<string, TablePlugin<T>>',
|
|
94
94
|
description: 'Named plugins that extend table behavior via the transform pipeline. Converted to an ordered array internally.',
|
|
95
95
|
},
|
|
96
|
+
{
|
|
97
|
+
name: 'rowIndexStart',
|
|
98
|
+
type: 'number',
|
|
99
|
+
description: 'ARIA row index (1-based) for the first rendered body row. The row ordinal is an accessibility concern independent of any visible index column, so setting this (or rowCount) makes the table emit aria-rowindex on body rows and aria-rowcount on the table. For a paginated/windowed view, pass the offset of the first visible row (e.g. (page - 1) * pageSize + 1) so aria-rowindex reflects position in the full dataset. Data-driven mode only.',
|
|
100
|
+
default: '1',
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: 'rowCount',
|
|
104
|
+
type: 'number',
|
|
105
|
+
description: 'Total number of body rows across all pages/windows, used for aria-rowcount so assistive tech can announce "row X of Y" against the full dataset. When omitted but rowIndexStart is set (windowed view with an unknown total), aria-rowcount is set to -1 per the ARIA unknown-count convention. Data-driven mode only.',
|
|
106
|
+
},
|
|
96
107
|
{
|
|
97
108
|
name: 'children',
|
|
98
109
|
type: 'ReactNode',
|
package/src/Table/Table.test.tsx
CHANGED
|
@@ -1451,3 +1451,88 @@ describe('emptyState', () => {
|
|
|
1451
1451
|
});
|
|
1452
1452
|
});
|
|
1453
1453
|
});
|
|
1454
|
+
|
|
1455
|
+
describe('ARIA row indexing (#3939)', () => {
|
|
1456
|
+
const bodyRows = (container: HTMLElement): HTMLTableRowElement[] =>
|
|
1457
|
+
Array.from(container.querySelectorAll('tbody tr'));
|
|
1458
|
+
|
|
1459
|
+
it('emits no aria-rowindex/aria-rowcount by default', () => {
|
|
1460
|
+
const {container} = render(<Table data={users} columns={columns} />);
|
|
1461
|
+
expect(screen.getByRole('table')).not.toHaveAttribute('aria-rowcount');
|
|
1462
|
+
for (const row of bodyRows(container)) {
|
|
1463
|
+
expect(row).not.toHaveAttribute('aria-rowindex');
|
|
1464
|
+
}
|
|
1465
|
+
});
|
|
1466
|
+
|
|
1467
|
+
it('numbers rows from 1 when rowCount is provided', () => {
|
|
1468
|
+
const {container} = render(
|
|
1469
|
+
<Table data={users} columns={columns} rowCount={users.length} />,
|
|
1470
|
+
);
|
|
1471
|
+
expect(screen.getByRole('table')).toHaveAttribute(
|
|
1472
|
+
'aria-rowcount',
|
|
1473
|
+
String(users.length),
|
|
1474
|
+
);
|
|
1475
|
+
const indices = bodyRows(container).map(r =>
|
|
1476
|
+
r.getAttribute('aria-rowindex'),
|
|
1477
|
+
);
|
|
1478
|
+
expect(indices).toEqual(['1', '2', '3']);
|
|
1479
|
+
});
|
|
1480
|
+
|
|
1481
|
+
it('offsets aria-rowindex by rowIndexStart for a paginated view', () => {
|
|
1482
|
+
// Page 3 of a 10-per-page dataset: first visible row is dataset row 21.
|
|
1483
|
+
const {container} = render(
|
|
1484
|
+
<Table
|
|
1485
|
+
data={users}
|
|
1486
|
+
columns={columns}
|
|
1487
|
+
rowIndexStart={21}
|
|
1488
|
+
rowCount={100}
|
|
1489
|
+
/>,
|
|
1490
|
+
);
|
|
1491
|
+
expect(screen.getByRole('table')).toHaveAttribute('aria-rowcount', '100');
|
|
1492
|
+
const indices = bodyRows(container).map(r =>
|
|
1493
|
+
r.getAttribute('aria-rowindex'),
|
|
1494
|
+
);
|
|
1495
|
+
expect(indices).toEqual(['21', '22', '23']);
|
|
1496
|
+
});
|
|
1497
|
+
|
|
1498
|
+
it('sets aria-rowcount to -1 (unknown) when only rowIndexStart is given', () => {
|
|
1499
|
+
// Windowed/cursor pagination: offset known, total unknown.
|
|
1500
|
+
const {container} = render(
|
|
1501
|
+
<Table data={users} columns={columns} rowIndexStart={5} />,
|
|
1502
|
+
);
|
|
1503
|
+
expect(screen.getByRole('table')).toHaveAttribute('aria-rowcount', '-1');
|
|
1504
|
+
const indices = bodyRows(container).map(r =>
|
|
1505
|
+
r.getAttribute('aria-rowindex'),
|
|
1506
|
+
);
|
|
1507
|
+
expect(indices).toEqual(['5', '6', '7']);
|
|
1508
|
+
});
|
|
1509
|
+
|
|
1510
|
+
it('does not assign an ARIA row index to the header row', () => {
|
|
1511
|
+
render(<Table data={users} columns={columns} rowCount={users.length} />);
|
|
1512
|
+
const header = screen.getAllByRole('row')[0];
|
|
1513
|
+
expect(header).not.toHaveAttribute('aria-rowindex');
|
|
1514
|
+
});
|
|
1515
|
+
|
|
1516
|
+
it('lets a plugin override the seeded aria-rowindex', () => {
|
|
1517
|
+
const plugin: TablePlugin<User> = {
|
|
1518
|
+
transformBodyRow(props, _item, index) {
|
|
1519
|
+
return {
|
|
1520
|
+
...props,
|
|
1521
|
+
htmlProps: {...props.htmlProps, 'aria-rowindex': 100 + index},
|
|
1522
|
+
};
|
|
1523
|
+
},
|
|
1524
|
+
};
|
|
1525
|
+
const {container} = render(
|
|
1526
|
+
<Table
|
|
1527
|
+
data={users}
|
|
1528
|
+
columns={columns}
|
|
1529
|
+
rowCount={users.length}
|
|
1530
|
+
plugins={{custom: plugin}}
|
|
1531
|
+
/>,
|
|
1532
|
+
);
|
|
1533
|
+
const indices = bodyRows(container).map(r =>
|
|
1534
|
+
r.getAttribute('aria-rowindex'),
|
|
1535
|
+
);
|
|
1536
|
+
expect(indices).toEqual(['100', '101', '102']);
|
|
1537
|
+
});
|
|
1538
|
+
});
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
fontWeightVars,
|
|
21
21
|
} from '../../../theme/tokens.stylex';
|
|
22
22
|
import {Icon} from '../../../Icon';
|
|
23
|
+
import {rtlStyles} from '../../../utils';
|
|
23
24
|
import type {TablePlugin} from '../../types';
|
|
24
25
|
import {useTranslator} from '../../../i18n';
|
|
25
26
|
|
|
@@ -333,12 +334,14 @@ export function useTableGroupedRows<T extends Record<string, unknown>>(
|
|
|
333
334
|
})
|
|
334
335
|
}
|
|
335
336
|
aria-expanded={!collapsed}>
|
|
336
|
-
<span
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
337
|
+
<span {...stylex.props(rtlStyles.mirror)}>
|
|
338
|
+
<span
|
|
339
|
+
{...stylex.props(
|
|
340
|
+
styles.chevronIcon,
|
|
341
|
+
!collapsed && styles.chevronExpanded,
|
|
342
|
+
)}>
|
|
343
|
+
<Icon icon="chevronRight" size="xsm" />
|
|
344
|
+
</span>
|
|
342
345
|
</span>
|
|
343
346
|
</button>
|
|
344
347
|
{content}
|
|
@@ -16,6 +16,7 @@ import {useCallback, useMemo, useRef, type ReactNode} from 'react';
|
|
|
16
16
|
import * as stylex from '@stylexjs/stylex';
|
|
17
17
|
import {spacingVars, colorVars, radiusVars} from '../../../theme/tokens.stylex';
|
|
18
18
|
import {Icon} from '../../../Icon';
|
|
19
|
+
import {rtlStyles} from '../../../utils';
|
|
19
20
|
import {resolveContextActions} from '../../tableContextMenu';
|
|
20
21
|
import {useTranslator} from '../../../i18n';
|
|
21
22
|
import type {
|
|
@@ -361,12 +362,14 @@ function ExpansionChevron({
|
|
|
361
362
|
}}
|
|
362
363
|
aria-label={ariaLabel}
|
|
363
364
|
aria-expanded={isExpanded}>
|
|
364
|
-
<span
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
365
|
+
<span {...stylex.props(rtlStyles.mirror)}>
|
|
366
|
+
<span
|
|
367
|
+
{...stylex.props(
|
|
368
|
+
expansionStyles.chevronIcon,
|
|
369
|
+
isExpanded && expansionStyles.chevronExpanded,
|
|
370
|
+
)}>
|
|
371
|
+
<Icon icon="chevronRight" size="xsm" />
|
|
372
|
+
</span>
|
|
370
373
|
</span>
|
|
371
374
|
</button>
|
|
372
375
|
);
|
|
@@ -533,12 +536,14 @@ export function useTableRowExpansion<T extends Record<string, unknown>>(
|
|
|
533
536
|
? t('@astryx.tableRowExpansion.collapseAllRows')
|
|
534
537
|
: t('@astryx.tableRowExpansion.expandAllRows')
|
|
535
538
|
}>
|
|
536
|
-
<span
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
539
|
+
<span {...stylex.props(rtlStyles.mirror)}>
|
|
540
|
+
<span
|
|
541
|
+
{...stylex.props(
|
|
542
|
+
expansionStyles.chevronIcon,
|
|
543
|
+
allExpanded && expansionStyles.chevronExpanded,
|
|
544
|
+
)}>
|
|
545
|
+
<Icon icon="chevronRight" size="xsm" />
|
|
546
|
+
</span>
|
|
542
547
|
</span>
|
|
543
548
|
</button>
|
|
544
549
|
),
|
|
@@ -573,11 +578,13 @@ export function useTableRowExpansion<T extends Record<string, unknown>>(
|
|
|
573
578
|
group: 'row-expansion',
|
|
574
579
|
label: isExpanded ? 'Collapse row' : 'Expand row',
|
|
575
580
|
icon: (
|
|
576
|
-
<
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
+
<span {...stylex.props(rtlStyles.mirror)}>
|
|
582
|
+
<Icon
|
|
583
|
+
icon={isExpanded ? 'chevronDown' : 'chevronRight'}
|
|
584
|
+
size="xsm"
|
|
585
|
+
aria-hidden
|
|
586
|
+
/>
|
|
587
|
+
</span>
|
|
581
588
|
),
|
|
582
589
|
onSelect: () => onToggle(key),
|
|
583
590
|
},
|