@astryxdesign/core 0.1.9 → 0.2.0-canary.0e01213
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 +107 -0
- package/dist/Avatar/Avatar.d.ts +42 -3
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +190 -59
- package/dist/Avatar/AvatarStatusDot.d.ts +6 -4
- package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts +7 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +58 -6
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +7 -2
- package/dist/Banner/Banner.js +2 -2
- 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/Button/Button.d.ts +1 -1
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +6 -4
- 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/Center/Center.d.ts +20 -3
- package/dist/Center/Center.d.ts.map +1 -1
- package/dist/Center/Center.js +10 -2
- package/dist/Chat/ChatComposerInput.js +1 -1
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +3 -1
- package/dist/Chat/ChatLayout.d.ts +7 -0
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +16 -5
- 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/Chat/useTriggerMenu.js +2 -2
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +6 -6
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +19 -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 +16 -10
- 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/CommandPalette/CommandPaletteItem.js +1 -1
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +23 -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 +10 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +33 -19
- package/dist/DateRangeInput/DateRangeInput.d.ts +10 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +23 -20
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +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 +18 -12
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +42 -64
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +5 -2
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +8 -11
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +3 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +10 -3
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +104 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +435 -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 +24 -0
- package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -0
- package/dist/DropdownMenu/menuItemHover.js +34 -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 +27 -10
- 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/FieldLabel.d.ts +2 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +9 -5
- 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 +10 -0
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +51 -5
- package/dist/FileInput/FileInput.d.ts +10 -2
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +93 -65
- package/dist/Heading/Heading.d.ts.map +1 -1
- package/dist/Heading/Heading.js +3 -2
- 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/Item/Item.d.ts +16 -3
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +31 -6
- package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
- package/dist/Layer/layerAnimations.stylex.js +10 -2
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +34 -15
- package/dist/List/List.d.ts.map +1 -1
- package/dist/List/List.js +6 -3
- package/dist/List/ListItem.d.ts +11 -1
- package/dist/List/ListItem.d.ts.map +1 -1
- package/dist/List/ListItem.js +2 -0
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +7 -0
- package/dist/MetadataList/MetadataList.d.ts +1 -1
- package/dist/MetadataList/MetadataList.d.ts.map +1 -1
- package/dist/MetadataList/MetadataList.js +4 -2
- package/dist/MultiSelector/MultiSelector.d.ts +9 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +87 -45
- package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
- package/dist/NumberInput/NumberInput.d.ts +10 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +22 -17
- package/dist/Outline/Outline.js +2 -2
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +11 -3
- package/dist/PowerSearch/PowerSearch.d.ts +9 -2
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +2 -0
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +6 -1
- package/dist/RadioList/RadioList.d.ts +2 -2
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +5 -5
- 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 +5 -3
- package/dist/Selector/Selector.d.ts +8 -0
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +72 -19
- 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/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/Skeleton/Skeleton.js +2 -2
- 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 +171 -91
- package/dist/TabList/Tab.js +2 -2
- 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/TabList/TabMenu.js +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +30 -4
- package/dist/Table/TableCell.js +3 -3
- package/dist/Table/TableHeaderCell.js +3 -3
- 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 +18 -3
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +58 -30
- 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 +15 -7
- package/dist/Table/plugins/tree/useTableTreeData.d.ts +11 -0
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.js +65 -25
- package/dist/Table/types.d.ts +32 -0
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Text/Text.d.ts +10 -1
- package/dist/Text/Text.d.ts.map +1 -1
- package/dist/Text/Text.js +25 -2
- package/dist/Text/index.d.ts +2 -2
- package/dist/Text/index.d.ts.map +1 -1
- package/dist/TextArea/TextArea.d.ts +10 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +119 -52
- package/dist/TextInput/TextInput.d.ts +10 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +20 -17
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +51 -45
- package/dist/TimeInput/TimeInput.d.ts +10 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +17 -17
- package/dist/Timestamp/Timestamp.d.ts +31 -3
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +48 -77
- 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/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +61 -9
- package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButton.js +3 -1
- package/dist/Token/Token.d.ts +34 -4
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +85 -45
- package/dist/Token/TokenLink.d.ts +62 -0
- package/dist/Token/TokenLink.d.ts.map +1 -0
- package/dist/Token/TokenLink.js +76 -0
- package/dist/Token/index.d.ts +1 -1
- package/dist/Token/index.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.d.ts +9 -2
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +4 -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/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +9 -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 +9 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +22 -11
- package/dist/Typeahead/Typeahead.d.ts +9 -2
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +11 -2
- 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 +115 -35
- package/dist/astryx.umd.js +51 -51
- package/dist/astryx.umd.js.map +4 -4
- package/dist/hooks/containerReveal.pool.stylex.d.ts +281 -0
- package/dist/hooks/containerReveal.pool.stylex.d.ts.map +1 -0
- package/dist/hooks/containerReveal.pool.stylex.js +281 -0
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +3 -1
- package/dist/hooks/isRtlElement.d.ts +18 -0
- package/dist/hooks/isRtlElement.d.ts.map +1 -0
- package/dist/hooks/isRtlElement.js +27 -0
- package/dist/hooks/useAnnounce.d.ts +3 -0
- package/dist/hooks/useAnnounce.d.ts.map +1 -1
- package/dist/hooks/useAnnounce.js +39 -1
- package/dist/hooks/useContainerReveal.d.ts +83 -0
- package/dist/hooks/useContainerReveal.d.ts.map +1 -0
- package/dist/hooks/useContainerReveal.js +123 -0
- 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 +169 -0
- package/dist/hooks/useKeyboardHint.d.ts +1 -1
- package/dist/hooks/useKeyboardHint.d.ts.map +1 -1
- package/dist/hooks/useKeyboardHint.js +4 -2
- 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/i18n/InternationalizationContext.d.ts +1 -0
- package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
- package/dist/i18n/InternationalizationContext.js +3 -0
- package/dist/i18n/InternationalizationProvider.d.ts +8 -1
- package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
- package/dist/i18n/InternationalizationProvider.js +5 -1
- package/dist/i18n/getLocaleDirection.d.ts +18 -0
- package/dist/i18n/getLocaleDirection.d.ts.map +1 -0
- package/dist/i18n/getLocaleDirection.js +29 -0
- package/dist/i18n/index.d.ts +6 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +7 -1
- package/dist/i18n/useDirection.d.ts +2 -0
- package/dist/i18n/useDirection.d.ts.map +1 -0
- package/dist/i18n/useDirection.js +27 -0
- package/dist/theme/defineTheme.d.ts +6 -0
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +13 -0
- package/dist/theme/expandColorScale.d.ts +19 -2
- package/dist/theme/expandColorScale.d.ts.map +1 -1
- package/dist/theme/expandColorScale.js +38 -10
- package/dist/theme/index.d.ts +3 -3
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/types.d.ts +39 -2
- package/dist/theme/types.d.ts.map +1 -1
- 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 +120 -0
- package/locales/pseudo.json +90 -0
- package/package.json +8 -3
- package/src/Avatar/Avatar.doc.mjs +50 -3
- package/src/Avatar/Avatar.test.tsx +218 -0
- package/src/Avatar/Avatar.tsx +285 -79
- package/src/Avatar/AvatarStatusDot.doc.mjs +4 -4
- package/src/Avatar/AvatarStatusDot.tsx +6 -4
- package/src/AvatarGroup/AvatarGroup.doc.mjs +2 -0
- package/src/AvatarGroup/AvatarGroup.test.tsx +162 -2
- package/src/AvatarGroup/AvatarGroup.tsx +58 -3
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +5 -2
- package/src/Banner/Banner.tsx +6 -6
- package/src/Breadcrumbs/BreadcrumbItem.tsx +10 -10
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +52 -1
- package/src/Breadcrumbs/index.ts +4 -0
- package/src/Button/Button.doc.mjs +0 -4
- package/src/Button/Button.test.tsx +16 -0
- package/src/Button/Button.tsx +6 -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/Center/Center.doc.mjs +38 -0
- package/src/Center/Center.test.tsx +75 -0
- package/src/Center/Center.tsx +37 -2
- package/src/Chat/ChatComposer.doc.mjs +2 -2
- package/src/Chat/ChatComposerInput.doc.mjs +1 -1
- package/src/Chat/ChatComposerInput.tsx +2 -2
- package/src/Chat/ChatDictationButton.tsx +7 -1
- package/src/Chat/ChatLayout.test.tsx +57 -0
- package/src/Chat/ChatLayout.tsx +26 -5
- package/src/Chat/ChatMessageBubble.tsx +15 -10
- package/src/Chat/ChatSystemMessage.test.tsx +5 -0
- package/src/Chat/ChatToolCalls.tsx +9 -2
- package/src/Chat/useTriggerMenu.tsx +1 -1
- package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +23 -0
- package/src/CheckboxInput/CheckboxInput.tsx +21 -6
- package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
- package/src/CheckboxList/CheckboxList.test.tsx +94 -3
- package/src/CheckboxList/CheckboxListItem.tsx +17 -10
- 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.test.tsx +17 -0
- package/src/CodeBlock/CodeBlock.tsx +38 -11
- 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/CommandPalette/CommandPaletteItem.tsx +1 -1
- package/src/ContextMenu/ContextMenu.test.tsx +59 -2
- package/src/ContextMenu/ContextMenu.tsx +22 -11
- package/src/ContextMenu/index.ts +5 -0
- package/src/DateInput/DateInput.doc.mjs +25 -0
- package/src/DateInput/DateInput.test.tsx +230 -0
- package/src/DateInput/DateInput.tsx +51 -29
- package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
- package/src/DateRangeInput/DateRangeInput.test.tsx +140 -0
- package/src/DateRangeInput/DateRangeInput.tsx +42 -30
- package/src/DateTimeInput/DateTimeInput.doc.mjs +22 -1
- package/src/DateTimeInput/DateTimeInput.test.tsx +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.doc.mjs +5 -2
- package/src/DropdownMenu/DropdownMenu.test.tsx +95 -0
- package/src/DropdownMenu/DropdownMenu.tsx +31 -12
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +49 -66
- package/src/DropdownMenu/DropdownMenuItem.tsx +9 -3
- package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +4 -12
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +9 -10
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +19 -4
- package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +84 -2
- package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +88 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +680 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +569 -0
- package/src/DropdownMenu/index.ts +16 -0
- package/src/DropdownMenu/menuItemHover.ts +40 -0
- package/src/DropdownMenu/menuItemRoles.ts +9 -0
- package/src/DropdownMenu/renderDropdownItems.tsx +40 -14
- package/src/Field/Field.doc.mjs +4 -0
- package/src/Field/Field.tsx +14 -9
- package/src/Field/FieldLabel.test.tsx +25 -0
- package/src/Field/FieldLabel.tsx +12 -3
- package/src/Field/inputStyles.stylex.ts +2 -0
- package/src/FieldStatus/FieldStatus.doc.mjs +1 -0
- package/src/FieldStatus/FieldStatus.test.tsx +133 -0
- package/src/FieldStatus/FieldStatus.tsx +61 -4
- package/src/FileInput/FileInput.doc.mjs +23 -2
- package/src/FileInput/FileInput.test.tsx +104 -13
- package/src/FileInput/FileInput.tsx +106 -79
- package/src/Heading/Heading.tsx +2 -1
- 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/Item/Item.doc.mjs +5 -0
- package/src/Item/Item.test.tsx +88 -0
- package/src/Item/Item.tsx +57 -11
- package/src/Layer/layerAnimations.stylex.ts +23 -0
- package/src/Lightbox/Lightbox.test.tsx +33 -0
- package/src/Lightbox/Lightbox.tsx +30 -10
- package/src/List/List.test.tsx +17 -29
- package/src/List/List.tsx +6 -1
- package/src/List/ListItem.doc.mjs +12 -0
- package/src/List/ListItem.tsx +13 -0
- package/src/Markdown/Markdown.test.tsx +21 -0
- package/src/Markdown/Markdown.tsx +4 -0
- package/src/MetadataList/MetadataList.test.tsx +24 -0
- package/src/MetadataList/MetadataList.tsx +6 -2
- package/src/MultiSelector/MultiSelector.doc.mjs +20 -0
- package/src/MultiSelector/MultiSelector.test.tsx +436 -0
- package/src/MultiSelector/MultiSelector.tsx +133 -67
- package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
- package/src/NumberInput/NumberInput.doc.mjs +21 -0
- package/src/NumberInput/NumberInput.test.tsx +71 -0
- package/src/NumberInput/NumberInput.tsx +35 -26
- package/src/Outline/Outline.test.tsx +12 -12
- package/src/Outline/Outline.tsx +2 -2
- package/src/Pagination/Pagination.tsx +11 -3
- package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
- package/src/PowerSearch/PowerSearch.test.tsx +23 -0
- package/src/PowerSearch/PowerSearch.tsx +10 -1
- package/src/ProgressBar/ProgressBar.test.tsx +34 -0
- package/src/ProgressBar/ProgressBar.tsx +16 -1
- package/src/RadioList/RadioList.doc.mjs +6 -0
- package/src/RadioList/RadioList.test.tsx +26 -4
- package/src/RadioList/RadioList.tsx +2 -2
- package/src/RadioList/RadioListItem.tsx +12 -5
- package/src/Resizable/ResizeHandle.test.tsx +94 -0
- package/src/Resizable/ResizeHandle.tsx +70 -20
- package/src/SegmentedControl/SegmentedControl.test.tsx +28 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +22 -2
- package/src/Selector/Selector.doc.mjs +15 -0
- package/src/Selector/Selector.test.tsx +400 -0
- package/src/Selector/Selector.tsx +95 -23
- package/src/SideNav/SideNav.tsx +1 -8
- package/src/SideNav/SideNavCollapseButton.tsx +9 -7
- package/src/SideNav/SideNavItem.tsx +5 -3
- package/src/Skeleton/Skeleton.test.tsx +16 -0
- package/src/Skeleton/Skeleton.tsx +13 -1
- 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 +111 -0
- package/src/Switch/Switch.tsx +149 -32
- package/src/TabList/Tab.tsx +2 -2
- 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/TabList/TabMenu.tsx +2 -2
- 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/TableCell.tsx +3 -3
- package/src/Table/TableHeaderCell.tsx +3 -3
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +9 -6
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +19 -0
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +48 -21
- 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 +38 -9
- package/src/Table/plugins/tree/useTableTreeData.test.tsx +161 -2
- package/src/Table/plugins/tree/useTableTreeData.tsx +71 -14
- package/src/Table/types.ts +33 -0
- package/src/Table/useTableRowExpansion.doc.mjs +55 -2
- package/src/Table/useTableRowStatus.doc.mjs +1 -1
- package/src/Table/useTableTreeData.doc.mjs +9 -0
- package/src/Text/Heading.doc.mjs +3 -3
- package/src/Text/Text.doc.mjs +1 -1
- package/src/Text/Text.test.tsx +42 -0
- package/src/Text/Text.tsx +25 -1
- package/src/Text/index.ts +2 -6
- package/src/TextArea/TextArea.doc.mjs +23 -2
- package/src/TextArea/TextArea.test.tsx +132 -4
- package/src/TextArea/TextArea.tsx +161 -67
- package/src/TextInput/TextInput.doc.mjs +21 -0
- package/src/TextInput/TextInput.test.tsx +150 -0
- package/src/TextInput/TextInput.tsx +28 -25
- package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
- package/src/Thumbnail/Thumbnail.test.tsx +24 -1
- package/src/Thumbnail/Thumbnail.tsx +28 -35
- package/src/TimeInput/TimeInput.doc.mjs +21 -0
- package/src/TimeInput/TimeInput.test.tsx +23 -0
- package/src/TimeInput/TimeInput.tsx +24 -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/Toast/ToastViewport.test.tsx +218 -8
- package/src/Toast/ToastViewport.tsx +71 -12
- package/src/ToggleButton/ToggleButton.test.tsx +24 -0
- package/src/ToggleButton/ToggleButton.tsx +19 -1
- package/src/Token/Token.test.tsx +166 -15
- package/src/Token/Token.tsx +104 -47
- package/src/Token/TokenLink.tsx +107 -0
- package/src/Token/index.ts +1 -1
- package/src/Tokenizer/Tokenizer.doc.mjs +23 -1
- package/src/Tokenizer/Tokenizer.test.tsx +23 -0
- package/src/Tokenizer/Tokenizer.tsx +14 -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/TopNavMegaMenu.tsx +26 -2
- 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 +42 -15
- package/src/Typeahead/Typeahead.doc.mjs +13 -0
- package/src/Typeahead/Typeahead.test.tsx +112 -0
- package/src/Typeahead/Typeahead.tsx +17 -1
- package/src/Typeahead/TypeaheadItem.tsx +2 -1
- package/src/__tests__/babelPluginAddExtensions.test.ts +190 -0
- package/src/__tests__/forcedColors.ts +60 -0
- package/src/__tests__/inputWidthContract.test.tsx +62 -0
- package/src/doc-mjs.d.ts +19 -0
- package/src/hooks/containerReveal.pool.stylex.ts +464 -0
- package/src/hooks/index.ts +13 -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/useContainerReveal.test.tsx +116 -0
- package/src/hooks/useContainerReveal.ts +180 -0
- 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 +221 -0
- package/src/hooks/useInputStatusIcon.tsx +235 -0
- package/src/hooks/useKeyboardHint.test.tsx +22 -0
- package/src/hooks/useKeyboardHint.tsx +6 -2
- 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/i18n/InternationalizationContext.ts +4 -0
- package/src/i18n/InternationalizationProvider.tsx +12 -2
- package/src/i18n/__tests__/getLocaleDirection.test.ts +40 -0
- package/src/i18n/__tests__/useDirection.test.tsx +66 -0
- package/src/i18n/getLocaleDirection.ts +29 -0
- package/src/i18n/index.ts +6 -0
- package/src/i18n/useDirection.ts +29 -0
- package/src/reset.css +0 -26
- package/src/reset.test.ts +60 -0
- package/src/theme/defineTheme.ts +6 -0
- package/src/theme/derivedVarRegistry.test.ts +1 -0
- package/src/theme/derivedVarRegistry.ts +6 -0
- package/src/theme/expandColorScale.test.ts +144 -0
- package/src/theme/expandColorScale.ts +53 -15
- package/src/theme/generateThemeRules.test.ts +42 -0
- package/src/theme/index.ts +4 -8
- package/src/theme/types.ts +43 -13
- 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
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts +0 -9
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts.map +0 -1
- package/dist/Thumbnail/thumbnail.markers.stylex.js +0 -14
- package/src/Thumbnail/thumbnail.markers.stylex.ts +0 -12
|
@@ -158,14 +158,29 @@ const styles = stylex.create({
|
|
|
158
158
|
},
|
|
159
159
|
checkmark: {
|
|
160
160
|
display: 'none',
|
|
161
|
-
color:
|
|
161
|
+
color: {
|
|
162
|
+
default: colorVars['--color-on-accent'],
|
|
163
|
+
// Forced colors (Windows High Contrast) does not reliably force an SVG
|
|
164
|
+
// stroke painted with currentColor, so the check stays the same white as
|
|
165
|
+
// the flattened (Canvas) box fill — a white check on a white box.
|
|
166
|
+
// CanvasText keeps it perceivable on the Canvas box, matching the
|
|
167
|
+
// indeterminate mark (WCAG 1.4.11).
|
|
168
|
+
'@media (forced-colors: active)': 'CanvasText',
|
|
169
|
+
},
|
|
162
170
|
},
|
|
163
171
|
checkmarkVisible: {
|
|
164
172
|
display: 'block',
|
|
165
173
|
},
|
|
166
174
|
indeterminateMark: {
|
|
167
175
|
display: 'none',
|
|
168
|
-
backgroundColor:
|
|
176
|
+
backgroundColor: {
|
|
177
|
+
default: colorVars['--color-on-accent'],
|
|
178
|
+
// Forced colors (Windows High Contrast) strips painted backgrounds,
|
|
179
|
+
// which would make the indeterminate bar invisible; CanvasText keeps it
|
|
180
|
+
// perceivable on the Canvas box fill (WCAG 1.4.11). The checkmark carries
|
|
181
|
+
// the matching CanvasText treatment on its own style.
|
|
182
|
+
'@media (forced-colors: active)': 'CanvasText',
|
|
183
|
+
},
|
|
169
184
|
borderRadius: radiusVars['--radius-full'],
|
|
170
185
|
},
|
|
171
186
|
indeterminateMarkVisible: {
|
|
@@ -198,12 +213,12 @@ const wrapperSizeStyles = stylex.create({
|
|
|
198
213
|
|
|
199
214
|
const checkboxSizeStyles = stylex.create({
|
|
200
215
|
sm: {
|
|
201
|
-
width:
|
|
202
|
-
height:
|
|
216
|
+
width: 20,
|
|
217
|
+
height: 20,
|
|
203
218
|
},
|
|
204
219
|
md: {
|
|
205
|
-
width:
|
|
206
|
-
height:
|
|
220
|
+
width: 24,
|
|
221
|
+
height: 24,
|
|
207
222
|
},
|
|
208
223
|
});
|
|
209
224
|
|
|
@@ -88,6 +88,12 @@ export const docs = {
|
|
|
88
88
|
type: "{type: 'warning' | 'error' | 'success', message?: string}",
|
|
89
89
|
description: 'Status indicator ({ type, message }).',
|
|
90
90
|
},
|
|
91
|
+
{
|
|
92
|
+
name: 'width',
|
|
93
|
+
type: 'SizeValue',
|
|
94
|
+
description:
|
|
95
|
+
'Width of the field (number = pixels, string used as-is, e.g. "100%"). Sizes the whole field (label, control, and status) so they stay aligned.',
|
|
96
|
+
},
|
|
91
97
|
{
|
|
92
98
|
name: 'xstyle',
|
|
93
99
|
type: 'StyleXStyles',
|
|
@@ -154,14 +154,105 @@ describe('CheckboxList', () => {
|
|
|
154
154
|
</CheckboxList>,
|
|
155
155
|
);
|
|
156
156
|
|
|
157
|
-
//
|
|
158
|
-
//
|
|
159
|
-
|
|
157
|
+
// The row is a pointer-only click surface (no invisible row button — the
|
|
158
|
+
// checkbox is the option's only tab stop). Click the row's label area,
|
|
159
|
+
// where the composed onClick fires — not the inner checkbox.
|
|
160
|
+
expect(
|
|
161
|
+
screen.queryByRole('button', {name: 'Option B'}),
|
|
162
|
+
).not.toBeInTheDocument();
|
|
163
|
+
// The text also exists in the checkbox's visually hidden <label>; target
|
|
164
|
+
// the row's label <span> to click the row surface.
|
|
165
|
+
await user.click(screen.getByText('Option B', {selector: 'span'}));
|
|
160
166
|
|
|
161
167
|
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
162
168
|
expect(handleChange).toHaveBeenCalledWith(['a', 'b']);
|
|
163
169
|
});
|
|
164
170
|
|
|
171
|
+
describe('single tab stop per option (WCAG 4.1.2 / APG checkbox pattern)', () => {
|
|
172
|
+
it('renders exactly one focusable control per option — the checkbox, no row button', () => {
|
|
173
|
+
render(
|
|
174
|
+
<CheckboxList label="Preferences" value={['a']} onChange={() => {}}>
|
|
175
|
+
<CheckboxListItem label="Option A" value="a" />
|
|
176
|
+
<CheckboxListItem label="Option B" value="b" />
|
|
177
|
+
</CheckboxList>,
|
|
178
|
+
);
|
|
179
|
+
// No invisible whole-row button duplicating the checkbox's action.
|
|
180
|
+
expect(screen.queryByRole('button')).not.toBeInTheDocument();
|
|
181
|
+
for (const item of screen.getAllByRole('listitem')) {
|
|
182
|
+
const focusables = item.querySelectorAll(
|
|
183
|
+
'button, a[href], input, select, textarea, [tabindex]:not([tabindex="-1"])',
|
|
184
|
+
);
|
|
185
|
+
expect(focusables).toHaveLength(1);
|
|
186
|
+
expect(focusables[0]).toBe(within(item).getByRole('checkbox'));
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('Tab moves directly from one option checkbox to the next', async () => {
|
|
191
|
+
const user = userEvent.setup();
|
|
192
|
+
render(
|
|
193
|
+
<CheckboxList label="Preferences" value={[]} onChange={() => {}}>
|
|
194
|
+
<CheckboxListItem label="Option A" value="a" />
|
|
195
|
+
<CheckboxListItem label="Option B" value="b" />
|
|
196
|
+
</CheckboxList>,
|
|
197
|
+
);
|
|
198
|
+
await user.tab();
|
|
199
|
+
expect(screen.getByRole('checkbox', {name: 'Option A'})).toHaveFocus();
|
|
200
|
+
await user.tab();
|
|
201
|
+
expect(screen.getByRole('checkbox', {name: 'Option B'})).toHaveFocus();
|
|
202
|
+
// No further tab stop inside the list (the row itself is not focusable).
|
|
203
|
+
await user.tab();
|
|
204
|
+
expect(document.body).toHaveFocus();
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('clicking the row surface (outside the checkbox) still toggles', async () => {
|
|
208
|
+
const user = userEvent.setup();
|
|
209
|
+
const handleChange = vi.fn();
|
|
210
|
+
render(
|
|
211
|
+
<CheckboxList label="Preferences" value={['a']} onChange={handleChange}>
|
|
212
|
+
<CheckboxListItem label="Option A" value="a" />
|
|
213
|
+
<CheckboxListItem label="Option B" value="b" />
|
|
214
|
+
</CheckboxList>,
|
|
215
|
+
);
|
|
216
|
+
// The text also exists in the checkbox's visually hidden <label>;
|
|
217
|
+
// target the row's label <span> to click the row surface.
|
|
218
|
+
await user.click(screen.getByText('Option B', {selector: 'span'}));
|
|
219
|
+
expect(handleChange).toHaveBeenCalledTimes(1);
|
|
220
|
+
expect(handleChange).toHaveBeenCalledWith(['a', 'b']);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it('toggles with Space on the focused checkbox, which reports checked state', async () => {
|
|
224
|
+
const user = userEvent.setup();
|
|
225
|
+
const handleChange = vi.fn();
|
|
226
|
+
render(
|
|
227
|
+
<CheckboxList label="Preferences" value={['a']} onChange={handleChange}>
|
|
228
|
+
<CheckboxListItem label="Option A" value="a" />
|
|
229
|
+
<CheckboxListItem label="Option B" value="b" />
|
|
230
|
+
</CheckboxList>,
|
|
231
|
+
);
|
|
232
|
+
await user.tab();
|
|
233
|
+
// The focused control is the checkbox itself, so its accessible name
|
|
234
|
+
// and checked state are what assistive tech announces on focus.
|
|
235
|
+
const checkboxA = screen.getByRole('checkbox', {name: 'Option A'});
|
|
236
|
+
expect(checkboxA).toHaveFocus();
|
|
237
|
+
expect(checkboxA).toBeChecked();
|
|
238
|
+
await user.keyboard(' ');
|
|
239
|
+
expect(handleChange).toHaveBeenCalledTimes(1);
|
|
240
|
+
expect(handleChange).toHaveBeenCalledWith([]);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('the row itself is not focusable', () => {
|
|
244
|
+
render(
|
|
245
|
+
<CheckboxList label="Preferences" value={[]} onChange={() => {}}>
|
|
246
|
+
<CheckboxListItem label="Option A" value="a" />
|
|
247
|
+
</CheckboxList>,
|
|
248
|
+
);
|
|
249
|
+
const item = screen.getByRole('listitem');
|
|
250
|
+
expect(item).not.toHaveAttribute('tabindex');
|
|
251
|
+
item.focus();
|
|
252
|
+
expect(item).not.toHaveFocus();
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
|
|
165
256
|
it('disables all checkboxes when group isDisabled is true', () => {
|
|
166
257
|
render(
|
|
167
258
|
<CheckboxList
|
|
@@ -16,12 +16,11 @@
|
|
|
16
16
|
* - /packages/cli/templates/blocks/components/CheckboxList/ (showcase blocks)
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {use,
|
|
19
|
+
import {use, useRef, type ReactNode} from 'react';
|
|
20
20
|
import * as stylex from '@stylexjs/stylex';
|
|
21
21
|
import type {StyleXStyles} from '@stylexjs/stylex';
|
|
22
22
|
import {colorVars} from '../theme/tokens.stylex';
|
|
23
23
|
import type {BaseProps} from '../BaseProps';
|
|
24
|
-
import {composeEventHandlers} from '../utils';
|
|
25
24
|
import {useDevWarning} from '../hooks/useDevWarning';
|
|
26
25
|
import {CheckboxInput} from '../CheckboxInput/CheckboxInput';
|
|
27
26
|
import {ListItem} from '../List/ListItem';
|
|
@@ -212,6 +211,14 @@ export function CheckboxListItem({
|
|
|
212
211
|
// Whether this item is interactive (has a toggle handler)
|
|
213
212
|
const isInteractive = !effectiveReadOnly && (ctx != null || onCheck != null);
|
|
214
213
|
|
|
214
|
+
// The checkbox is the row's single keyboard control and action. The row is
|
|
215
|
+
// an enlarged click/tap target that delegates surface clicks to it via
|
|
216
|
+
// ListItem's `interactiveRef` (useClickableContainer), so each option is
|
|
217
|
+
// exactly one tab stop. Delegate whenever the row should respond to clicks:
|
|
218
|
+
// a toggleable item, or one carrying a consumer `onClick`.
|
|
219
|
+
const checkboxRef = useRef<HTMLInputElement | null>(null);
|
|
220
|
+
const hasRowInteraction = isInteractive || onClickProp != null;
|
|
221
|
+
|
|
215
222
|
const handleToggle = () => {
|
|
216
223
|
if (effectiveDisabled || effectiveReadOnly || isBusy) {
|
|
217
224
|
return;
|
|
@@ -244,14 +251,12 @@ export function CheckboxListItem({
|
|
|
244
251
|
description={description}
|
|
245
252
|
endContent={endContent}
|
|
246
253
|
isDisabled={effectiveDisabled}
|
|
247
|
-
onClick
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
: undefined
|
|
254
|
-
}
|
|
254
|
+
// Delegate row clicks to the checkbox instead of wiring onClick (which
|
|
255
|
+
// would add an invisible row button = a second tab stop). The checkbox
|
|
256
|
+
// stays the option's sole focusable control (WCAG 4.1.2 / APG checkbox
|
|
257
|
+
// pattern). A consumer onClick rides on the checkbox itself (below), so
|
|
258
|
+
// it still fires for both direct and delegated (row-surface) clicks.
|
|
259
|
+
interactiveRef={hasRowInteraction ? checkboxRef : undefined}
|
|
255
260
|
aria-busy={isBusy || undefined}
|
|
256
261
|
xstyle={
|
|
257
262
|
[
|
|
@@ -266,10 +271,12 @@ export function CheckboxListItem({
|
|
|
266
271
|
style={style}
|
|
267
272
|
startContent={
|
|
268
273
|
<CheckboxInput
|
|
274
|
+
ref={checkboxRef}
|
|
269
275
|
label={checkboxLabel}
|
|
270
276
|
isLabelHidden
|
|
271
277
|
value={resolvedChecked}
|
|
272
278
|
onChange={() => handleToggle()}
|
|
279
|
+
onClick={onClickProp}
|
|
273
280
|
isDisabled={effectiveDisabled}
|
|
274
281
|
isReadOnly={effectiveReadOnly}
|
|
275
282
|
isLoading={isBusy}
|
|
@@ -39,7 +39,7 @@ export const docs = {
|
|
|
39
39
|
name: 'Icon',
|
|
40
40
|
required: false,
|
|
41
41
|
description:
|
|
42
|
-
'An optional
|
|
42
|
+
'An optional source icon shown before the label text. Accepts a favicon/logo image URL (via source.src) or a React node such as an Astryx <Icon>. Only available in the label variant.',
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
name: 'Label text',
|
|
@@ -71,7 +71,7 @@ export const docs = {
|
|
|
71
71
|
name: 'source',
|
|
72
72
|
type: 'CitationSource',
|
|
73
73
|
description:
|
|
74
|
-
'The citation source object containing title, url, and optional icon.',
|
|
74
|
+
'The citation source object containing title, url, an optional image src, and an optional icon node.',
|
|
75
75
|
required: true,
|
|
76
76
|
},
|
|
77
77
|
{
|
|
@@ -121,7 +121,8 @@ export const docsDense = {
|
|
|
121
121
|
],
|
|
122
122
|
},
|
|
123
123
|
propDescriptions: {
|
|
124
|
-
source:
|
|
124
|
+
source:
|
|
125
|
+
'citation source object with title, url, optional image src, and optional icon node.',
|
|
125
126
|
number: 'display index for this citation.',
|
|
126
127
|
variant: 'display style: label chip with source title or compact numbered badge.',
|
|
127
128
|
},
|
|
@@ -169,4 +169,101 @@ describe('Citation', () => {
|
|
|
169
169
|
expect(el.classList.contains(cls)).toBe(true);
|
|
170
170
|
}
|
|
171
171
|
});
|
|
172
|
+
|
|
173
|
+
// --- Source icon: image URL (back-compat) vs ReactNode ---------------------
|
|
174
|
+
|
|
175
|
+
it('renders a legacy string icon as a decorative image (back-compat)', () => {
|
|
176
|
+
// Existing callers pass a favicon URL to `source.icon`. A bare string must
|
|
177
|
+
// still render as <img src>, unchanged from the original behavior.
|
|
178
|
+
const {container} = render(
|
|
179
|
+
<Citation
|
|
180
|
+
source={{
|
|
181
|
+
title: 'GitHub',
|
|
182
|
+
url: 'https://github.com',
|
|
183
|
+
icon: 'https://example.com/favicon.png',
|
|
184
|
+
}}
|
|
185
|
+
number={1}
|
|
186
|
+
data-testid="citation"
|
|
187
|
+
/>,
|
|
188
|
+
);
|
|
189
|
+
const img = container.querySelector('img');
|
|
190
|
+
expect(img).not.toBeNull();
|
|
191
|
+
expect(img).toHaveAttribute('src', 'https://example.com/favicon.png');
|
|
192
|
+
// Decorative: empty alt, and the wrapper is aria-hidden.
|
|
193
|
+
expect(img).toHaveAttribute('alt', '');
|
|
194
|
+
expect(container.querySelector('[aria-hidden="true"] img')).toBe(img);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('renders source.src as a decorative image', () => {
|
|
198
|
+
const {container} = render(
|
|
199
|
+
<Citation
|
|
200
|
+
source={{
|
|
201
|
+
title: 'GitHub',
|
|
202
|
+
url: 'https://github.com',
|
|
203
|
+
src: 'https://example.com/logo.png',
|
|
204
|
+
}}
|
|
205
|
+
number={1}
|
|
206
|
+
data-testid="citation"
|
|
207
|
+
/>,
|
|
208
|
+
);
|
|
209
|
+
const img = container.querySelector('img');
|
|
210
|
+
expect(img).toHaveAttribute('src', 'https://example.com/logo.png');
|
|
211
|
+
expect(img).toHaveAttribute('alt', '');
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('renders a ReactNode icon as-is (not an <img>)', () => {
|
|
215
|
+
const {container} = render(
|
|
216
|
+
<Citation
|
|
217
|
+
source={{
|
|
218
|
+
title: 'GitHub',
|
|
219
|
+
url: 'https://github.com',
|
|
220
|
+
icon: <svg data-testid="custom-icon" />,
|
|
221
|
+
}}
|
|
222
|
+
number={1}
|
|
223
|
+
data-testid="citation"
|
|
224
|
+
/>,
|
|
225
|
+
);
|
|
226
|
+
// The node renders directly; no <img> is produced for a node icon.
|
|
227
|
+
expect(container.querySelector('img')).toBeNull();
|
|
228
|
+
expect(screen.getByTestId('custom-icon')).toBeInTheDocument();
|
|
229
|
+
// Still decorative — wrapped in an aria-hidden container.
|
|
230
|
+
expect(
|
|
231
|
+
container.querySelector(
|
|
232
|
+
'[aria-hidden="true"] [data-testid="custom-icon"]',
|
|
233
|
+
),
|
|
234
|
+
).not.toBeNull();
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('prefers a node icon over src when both are provided', () => {
|
|
238
|
+
const {container} = render(
|
|
239
|
+
<Citation
|
|
240
|
+
source={{
|
|
241
|
+
title: 'GitHub',
|
|
242
|
+
url: 'https://github.com',
|
|
243
|
+
src: 'https://example.com/logo.png',
|
|
244
|
+
icon: <svg data-testid="custom-icon" />,
|
|
245
|
+
}}
|
|
246
|
+
number={1}
|
|
247
|
+
data-testid="citation"
|
|
248
|
+
/>,
|
|
249
|
+
);
|
|
250
|
+
expect(screen.getByTestId('custom-icon')).toBeInTheDocument();
|
|
251
|
+
expect(container.querySelector('img')).toBeNull();
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('keeps aria-label as the sole accessible name when an icon is present', () => {
|
|
255
|
+
render(
|
|
256
|
+
<Citation
|
|
257
|
+
source={{
|
|
258
|
+
title: 'GitHub',
|
|
259
|
+
url: 'https://github.com',
|
|
260
|
+
icon: 'https://example.com/favicon.png',
|
|
261
|
+
}}
|
|
262
|
+
number={2}
|
|
263
|
+
data-testid="citation"
|
|
264
|
+
/>,
|
|
265
|
+
);
|
|
266
|
+
const el = screen.getByTestId('citation');
|
|
267
|
+
expect(el).toHaveAttribute('aria-label', 'Citation 2: GitHub');
|
|
268
|
+
});
|
|
172
269
|
});
|
|
@@ -10,10 +10,14 @@
|
|
|
10
10
|
*
|
|
11
11
|
* SYNC: When modified, update these files to stay in sync:
|
|
12
12
|
* - /packages/core/src/Citation/index.ts (exports if types change)
|
|
13
|
+
* - /packages/core/src/Citation/Citation.doc.mjs (props table, features)
|
|
14
|
+
* - /packages/core/src/Citation/Citation.test.tsx (tests for new/changed behavior)
|
|
15
|
+
* - /apps/storybook/stories/Citation.stories.tsx (storybook stories)
|
|
13
16
|
* - /packages/cli/templates/blocks/components/Citation/ (showcase blocks)
|
|
14
17
|
*/
|
|
15
18
|
|
|
16
19
|
import type React from 'react';
|
|
20
|
+
import type {ReactNode} from 'react';
|
|
17
21
|
import * as stylex from '@stylexjs/stylex';
|
|
18
22
|
import {
|
|
19
23
|
colorVars,
|
|
@@ -29,11 +33,29 @@ import {mergeProps} from '../utils';
|
|
|
29
33
|
import type {BaseProps} from '../BaseProps';
|
|
30
34
|
import {themeProps} from '../utils/themeProps';
|
|
31
35
|
import {useTranslator} from '../i18n';
|
|
36
|
+
import {renderIconSlot} from '../Icon';
|
|
32
37
|
|
|
33
38
|
export interface CitationSource {
|
|
34
39
|
title?: string;
|
|
35
40
|
url?: string;
|
|
36
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Image URL for a favicon or source logo, rendered as `<img src>` inside the
|
|
43
|
+
* icon circle. This is the idiomatic field for image sources (mirrors
|
|
44
|
+
* `Avatar`/`Thumbnail` `src`). When both `src` and a non-string `icon` are
|
|
45
|
+
* provided, `icon` wins.
|
|
46
|
+
*/
|
|
47
|
+
src?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Source icon shown before the label text (label variant only). Accepts:
|
|
50
|
+
* - a React node / Astryx `<Icon>` / SVG element — rendered as-is, or
|
|
51
|
+
* - a string image URL — rendered as `<img src>` for backward compatibility
|
|
52
|
+
* with callers that passed a favicon URL here.
|
|
53
|
+
*
|
|
54
|
+
* Note: unlike icon slots elsewhere in the system, a bare string is treated
|
|
55
|
+
* as an image URL (not a semantic icon name) to preserve the original
|
|
56
|
+
* favicon behavior. Pass an Astryx `<Icon>` (or other node) for a real icon.
|
|
57
|
+
*/
|
|
58
|
+
icon?: ReactNode;
|
|
37
59
|
}
|
|
38
60
|
|
|
39
61
|
export interface CitationProps extends BaseProps<HTMLElement> {
|
|
@@ -162,7 +184,18 @@ export function Citation({
|
|
|
162
184
|
const t = useTranslator();
|
|
163
185
|
const title = source.title ?? String(number);
|
|
164
186
|
const href = source.url;
|
|
165
|
-
|
|
187
|
+
|
|
188
|
+
// Resolve the source icon. A non-string `icon` node renders as-is (an Astryx
|
|
189
|
+
// <Icon>, SVG, avatar, etc.). Otherwise fall back to an image URL: `src`, or
|
|
190
|
+
// a legacy string passed to `icon` (back-compat — favicon URLs still render
|
|
191
|
+
// as <img>). The icon is decorative; the accessible name comes solely from
|
|
192
|
+
// the element's aria-label, so nothing is double-announced.
|
|
193
|
+
const iconNode =
|
|
194
|
+
source.icon != null && typeof source.icon !== 'string' ? source.icon : null;
|
|
195
|
+
const imageSrc =
|
|
196
|
+
source.src ?? (typeof source.icon === 'string' ? source.icon : undefined);
|
|
197
|
+
const hasIcon = iconNode != null || imageSrc != null;
|
|
198
|
+
|
|
166
199
|
const Tag = href ? 'a' : 'span';
|
|
167
200
|
// `doc-noteref` is a reference role — only appropriate on the interactive
|
|
168
201
|
// link form. On a plain (unlinked) span it is not a permitted role
|
|
@@ -218,7 +251,7 @@ export function Citation({
|
|
|
218
251
|
themeProps('citation', {variant}),
|
|
219
252
|
stylex.props(
|
|
220
253
|
styles.label,
|
|
221
|
-
|
|
254
|
+
hasIcon && styles.labelWithIcon,
|
|
222
255
|
href != null && styles.labelHover,
|
|
223
256
|
href != null && styles.labelInteractive,
|
|
224
257
|
xstyle,
|
|
@@ -226,14 +259,13 @@ export function Citation({
|
|
|
226
259
|
className,
|
|
227
260
|
style,
|
|
228
261
|
)}>
|
|
229
|
-
{
|
|
230
|
-
<span {...stylex.props(styles.iconWrap)}>
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
/>
|
|
262
|
+
{hasIcon && (
|
|
263
|
+
<span aria-hidden="true" {...stylex.props(styles.iconWrap)}>
|
|
264
|
+
{iconNode != null ? (
|
|
265
|
+
renderIconSlot(iconNode, {size: 'sm'})
|
|
266
|
+
) : (
|
|
267
|
+
<img src={imageSrc} alt="" {...stylex.props(styles.icon)} />
|
|
268
|
+
)}
|
|
237
269
|
</span>
|
|
238
270
|
)}
|
|
239
271
|
<span {...stylex.props(styles.labelText)}>{title}</span>
|
|
@@ -14,6 +14,7 @@ import {act, render, screen, fireEvent, waitFor} from '@testing-library/react';
|
|
|
14
14
|
import {CodeBlock} from './CodeBlock';
|
|
15
15
|
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
16
16
|
import {dracula} from '../theme/syntax';
|
|
17
|
+
import {InternationalizationProvider} from '../i18n';
|
|
17
18
|
|
|
18
19
|
function politeRegion(): HTMLElement | null {
|
|
19
20
|
return document.querySelector('[data-astryx-live-region="polite"]');
|
|
@@ -72,6 +73,22 @@ describe('CodeBlock', () => {
|
|
|
72
73
|
});
|
|
73
74
|
});
|
|
74
75
|
|
|
76
|
+
it('localizes the copy announcement through the i18n catalog', async () => {
|
|
77
|
+
render(
|
|
78
|
+
<InternationalizationProvider
|
|
79
|
+
locale="fr"
|
|
80
|
+
overrides={{fr: {'@astryx.codeBlock.copied': 'Copié'}}}>
|
|
81
|
+
<CodeBlock code="const x = 1;" language="javascript" />
|
|
82
|
+
</InternationalizationProvider>,
|
|
83
|
+
);
|
|
84
|
+
// The button label and the live-region announcement share the same key.
|
|
85
|
+
fireEvent.click(screen.getByRole('button', {name: 'Copy code'}));
|
|
86
|
+
await waitFor(() => {
|
|
87
|
+
expect(politeRegion()).toHaveTextContent('Copié');
|
|
88
|
+
});
|
|
89
|
+
expect(screen.getByRole('button', {name: 'Copié'})).toBeInTheDocument();
|
|
90
|
+
});
|
|
91
|
+
|
|
75
92
|
it('keeps the copied indicator a full 2s after a rapid re-copy', async () => {
|
|
76
93
|
vi.useFakeTimers();
|
|
77
94
|
try {
|
|
@@ -88,6 +88,23 @@ const dynamicStyles = stylex.create({
|
|
|
88
88
|
}),
|
|
89
89
|
});
|
|
90
90
|
|
|
91
|
+
// Light reveal so the leading chevron eases into view instead of popping in.
|
|
92
|
+
// Growing the chevron's own footprint (width + inline margin) from zero slides
|
|
93
|
+
// the title into place instead of snapping it over, and clipping keeps the
|
|
94
|
+
// glyph from spilling while it's mid-reveal.
|
|
95
|
+
const chevronReveal = stylex.keyframes({
|
|
96
|
+
from: {
|
|
97
|
+
width: 0,
|
|
98
|
+
marginInlineEnd: 0,
|
|
99
|
+
opacity: 0,
|
|
100
|
+
},
|
|
101
|
+
to: {
|
|
102
|
+
width: '14px',
|
|
103
|
+
marginInlineEnd: spacingVars['--spacing-1'],
|
|
104
|
+
opacity: 1,
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
|
|
91
108
|
const styles = stylex.create({
|
|
92
109
|
root: {
|
|
93
110
|
position: 'relative',
|
|
@@ -133,7 +150,6 @@ const styles = stylex.create({
|
|
|
133
150
|
headerTitle: {
|
|
134
151
|
display: 'flex',
|
|
135
152
|
alignItems: 'center',
|
|
136
|
-
gap: spacingVars['--spacing-1'],
|
|
137
153
|
fontSize: typeScaleVars['--text-supporting-size'],
|
|
138
154
|
fontFamily: typographyVars['--font-family-code'],
|
|
139
155
|
fontWeight: fontWeightVars['--font-weight-medium'],
|
|
@@ -173,13 +189,24 @@ const styles = stylex.create({
|
|
|
173
189
|
flexShrink: 0,
|
|
174
190
|
width: '14px',
|
|
175
191
|
height: '14px',
|
|
192
|
+
marginInlineEnd: spacingVars['--spacing-1'],
|
|
193
|
+
overflow: 'hidden',
|
|
176
194
|
color: 'var(--color-syntax-comment)',
|
|
195
|
+
animationName: {
|
|
196
|
+
default: chevronReveal,
|
|
197
|
+
'@media (prefers-reduced-motion: reduce)': 'none',
|
|
198
|
+
},
|
|
199
|
+
animationDuration: durationVars['--duration-medium'],
|
|
200
|
+
animationTimingFunction: easeVars['--ease-standard'],
|
|
177
201
|
transitionProperty: 'transform',
|
|
178
202
|
transitionDuration: durationVars['--duration-fast'],
|
|
179
203
|
transitionTimingFunction: easeVars['--ease-standard'],
|
|
180
204
|
},
|
|
181
|
-
|
|
182
|
-
|
|
205
|
+
collapseChevronExpanded: {
|
|
206
|
+
// Leading disclosure convention (matches TreeList/Table): the resting
|
|
207
|
+
// chevronRight points right (>) when collapsed; rotate it down (v) when
|
|
208
|
+
// expanded.
|
|
209
|
+
transform: 'rotate(90deg)',
|
|
183
210
|
},
|
|
184
211
|
headerCollapsible: {
|
|
185
212
|
cursor: 'pointer',
|
|
@@ -296,7 +323,7 @@ const styles = stylex.create({
|
|
|
296
323
|
copyButtonAbsolute: {
|
|
297
324
|
position: 'absolute',
|
|
298
325
|
top: spacingVars['--spacing-2'],
|
|
299
|
-
|
|
326
|
+
insetInlineEnd: spacingVars['--spacing-2'],
|
|
300
327
|
},
|
|
301
328
|
});
|
|
302
329
|
|
|
@@ -759,7 +786,7 @@ export function CodeBlock({
|
|
|
759
786
|
setCopied(true);
|
|
760
787
|
// Swapping the button's aria-label alone isn't reliably announced by
|
|
761
788
|
// screen readers, so confirm the copy via a polite live region.
|
|
762
|
-
announce('
|
|
789
|
+
announce(t('@astryx.codeBlock.copied'));
|
|
763
790
|
onCopy?.();
|
|
764
791
|
// Restart the reset timer on every copy — otherwise a rapid re-copy
|
|
765
792
|
// is reverted early by the previous click's timer.
|
|
@@ -773,7 +800,7 @@ export function CodeBlock({
|
|
|
773
800
|
} catch {
|
|
774
801
|
// Clipboard failures leave the copied state unchanged.
|
|
775
802
|
}
|
|
776
|
-
}, [code, onCopy, announce]);
|
|
803
|
+
}, [code, onCopy, announce, t]);
|
|
777
804
|
|
|
778
805
|
const sizeStyle = size === 'sm' ? styles.sizeSm : styles.sizeMd;
|
|
779
806
|
// Digits in the largest line number — sizes the gutter column width.
|
|
@@ -845,18 +872,18 @@ export function CodeBlock({
|
|
|
845
872
|
canCollapse && styles.headerCollapsible,
|
|
846
873
|
)}>
|
|
847
874
|
<span {...stylex.props(styles.headerTitle)}>
|
|
848
|
-
{title}
|
|
849
|
-
{title && languageLabel ? ' — ' : ''}
|
|
850
|
-
{languageLabel}
|
|
851
875
|
{canCollapse && (
|
|
852
876
|
<span
|
|
853
877
|
{...stylex.props(
|
|
854
878
|
styles.collapseChevron,
|
|
855
|
-
isCollapsed && styles.
|
|
879
|
+
!isCollapsed && styles.collapseChevronExpanded,
|
|
856
880
|
)}>
|
|
857
|
-
<Icon icon="
|
|
881
|
+
<Icon icon="chevronRight" size="xsm" color="inherit" />
|
|
858
882
|
</span>
|
|
859
883
|
)}
|
|
884
|
+
{title}
|
|
885
|
+
{title && languageLabel ? ' — ' : ''}
|
|
886
|
+
{languageLabel}
|
|
860
887
|
</span>
|
|
861
888
|
</div>
|
|
862
889
|
{copyButtonEl}
|
|
@@ -17,6 +17,7 @@ export const docs = {
|
|
|
17
17
|
theming: {
|
|
18
18
|
targets: [
|
|
19
19
|
{className: 'astryx-collapsible', visualProps: ['density']},
|
|
20
|
+
{className: 'astryx-collapsible-trigger', visualProps: ['density']},
|
|
20
21
|
{className: 'astryx-collapsible-content', visualProps: ['density']},
|
|
21
22
|
{className: 'astryx-collapsible-group', visualProps: ['density']},
|
|
22
23
|
],
|
|
@@ -72,6 +72,13 @@ describe('Collapsible', () => {
|
|
|
72
72
|
expect(screen.getByTestId('root')).toHaveClass('astryx-collapsible');
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
+
it('renders the stable astryx-collapsible-trigger class on the trigger button', () => {
|
|
76
|
+
render(<Collapsible trigger="T">c</Collapsible>);
|
|
77
|
+
expect(screen.getByRole('button')).toHaveClass(
|
|
78
|
+
'astryx-collapsible-trigger',
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
|
|
75
82
|
it('renders the stable astryx-collapsible-content class on the content area', () => {
|
|
76
83
|
render(<Collapsible trigger="T">c</Collapsible>);
|
|
77
84
|
const content = contentFor(screen.getByRole('button'));
|
|
@@ -51,7 +51,12 @@ const styles = stylex.create({
|
|
|
51
51
|
root: {
|
|
52
52
|
width: '100%',
|
|
53
53
|
},
|
|
54
|
-
// Trigger button — full width, flex row, no browser button styling
|
|
54
|
+
// Trigger button — full width, flex row, no browser button styling.
|
|
55
|
+
// Anchors heading-adjacent typography (body family, large size, semibold)
|
|
56
|
+
// so the label reads as a section header regardless of where the
|
|
57
|
+
// Collapsible is placed. External themes retarget it independently from the
|
|
58
|
+
// content via the `astryx-collapsible-trigger` target — e.g. a heading font
|
|
59
|
+
// on the trigger while the content stays on the body font.
|
|
55
60
|
trigger: {
|
|
56
61
|
all: 'unset',
|
|
57
62
|
boxSizing: 'border-box',
|
|
@@ -113,7 +118,7 @@ const styles = stylex.create({
|
|
|
113
118
|
// Anchors body typography so revealed text renders at the system's body
|
|
114
119
|
// scale (family/size/weight/leading) instead of inheriting from wherever
|
|
115
120
|
// the Collapsible is placed. External themes override via the
|
|
116
|
-
// `astryx-collapsible-content` target.
|
|
121
|
+
// `astryx-collapsible-content` target, independently from the trigger.
|
|
117
122
|
content: {
|
|
118
123
|
paddingBlockStart: spacingVars['--spacing-1'],
|
|
119
124
|
fontFamily: typographyVars['--font-family-body'],
|
|
@@ -318,10 +323,15 @@ export function Collapsible({
|
|
|
318
323
|
// the system-wide disabled convention (never native `disabled`, which
|
|
319
324
|
// would swallow events like a wrapping tooltip's hover).
|
|
320
325
|
tabIndex={isDisabled ? -1 : undefined}
|
|
321
|
-
{...
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
326
|
+
{...mergeProps(
|
|
327
|
+
themeProps('collapsible-trigger', {
|
|
328
|
+
density: density ?? undefined,
|
|
329
|
+
}),
|
|
330
|
+
stylex.props(
|
|
331
|
+
styles.trigger,
|
|
332
|
+
density != null && triggerDensity[density],
|
|
333
|
+
isDisabled && styles.triggerDisabled,
|
|
334
|
+
),
|
|
325
335
|
)}>
|
|
326
336
|
<span {...stylex.props(styles.triggerLabel)}>{trigger}</span>
|
|
327
337
|
<span
|