@astryxdesign/core 0.1.8 → 0.1.9-canary.02ef052
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +100 -0
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +6 -2
- package/dist/AppShell/AppShellMobileContext.d.ts +8 -0
- package/dist/AppShell/AppShellMobileContext.d.ts.map +1 -1
- package/dist/Avatar/Avatar.d.ts +58 -3
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +240 -53
- package/dist/Avatar/AvatarStatusDot.d.ts +35 -5
- package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
- package/dist/Avatar/AvatarStatusDot.js +144 -19
- package/dist/AvatarGroup/AvatarGroup.d.ts +7 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +58 -6
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +1 -0
- package/dist/Banner/Banner.d.ts +9 -1
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +33 -4
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +31 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +215 -6
- package/dist/Breadcrumbs/index.d.ts +6 -0
- package/dist/Breadcrumbs/index.d.ts.map +1 -1
- package/dist/Breadcrumbs/index.js +10 -1
- package/dist/Button/Button.d.ts +8 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +33 -4
- package/dist/ButtonGroup/ButtonGroup.d.ts +9 -1
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +30 -1
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +80 -11
- package/dist/Calendar/dayCellUtils.d.ts +4 -4
- package/dist/Calendar/dayCellUtils.js +3 -3
- package/dist/Calendar/styles.d.ts +30 -31
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +30 -31
- package/dist/Card/Card.d.ts +8 -2
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +28 -2
- package/dist/Carousel/Carousel.d.ts +4 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +46 -16
- package/dist/Chat/ChatComposer.d.ts +8 -0
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +46 -7
- package/dist/Chat/ChatComposerDrawer.d.ts +2 -0
- package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
- package/dist/Chat/ChatComposerDrawer.js +11 -1
- package/dist/Chat/ChatComposerInput.d.ts +20 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +36 -4
- package/dist/Chat/ChatContext.d.ts +33 -0
- package/dist/Chat/ChatContext.d.ts.map +1 -1
- package/dist/Chat/ChatContext.js +16 -2
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +4 -2
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +4 -4
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +4 -4
- package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.js +7 -1
- package/dist/Chat/ChatToolCalls.d.ts +5 -1
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +27 -11
- package/dist/Chat/index.d.ts +2 -1
- package/dist/Chat/index.d.ts.map +1 -1
- package/dist/Chat/index.js +1 -1
- package/dist/Chat/useChatStreamScroll.d.ts +2 -1
- package/dist/Chat/useChatStreamScroll.d.ts.map +1 -1
- package/dist/Chat/useChatStreamScroll.js +22 -8
- package/dist/Chat/useSpeechRecognition.d.ts +0 -1
- package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
- package/dist/Chat/useSpeechRecognition.js +1 -1
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +2 -2
- package/dist/CheckboxInput/CheckboxInput.js +5 -5
- package/dist/CheckboxList/CheckboxListItem.d.ts +20 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +11 -1
- package/dist/Citation/Citation.d.ts +22 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +20 -6
- package/dist/ClickableCard/ClickableCard.d.ts +9 -2
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +5 -2
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +22 -9
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +3 -1
- package/dist/CommandPalette/CommandPalette.d.ts +2 -2
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +45 -4
- package/dist/CommandPalette/CommandPaletteGroup.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteGroup.js +9 -2
- package/dist/CommandPalette/CommandPaletteInput.d.ts +7 -1
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +6 -1
- package/dist/CommandPalette/CommandPaletteItem.js +1 -1
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +14 -5
- package/dist/ContextMenu/index.d.ts +1 -0
- package/dist/ContextMenu/index.d.ts.map +1 -1
- package/dist/ContextMenu/index.js +3 -1
- package/dist/DateInput/DateInput.d.ts +56 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +59 -21
- package/dist/DateInput/index.d.ts +1 -1
- package/dist/DateInput/index.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts +10 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +23 -20
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +33 -19
- package/dist/Dialog/Dialog.d.ts +3 -0
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +57 -6
- package/dist/Dialog/DialogContext.d.ts +7 -0
- package/dist/Dialog/DialogContext.d.ts.map +1 -1
- package/dist/Dialog/DialogContext.js +2 -2
- package/dist/Dialog/DialogHeader.d.ts +5 -2
- package/dist/Dialog/DialogHeader.d.ts.map +1 -1
- package/dist/Dialog/DialogHeader.js +6 -1
- package/dist/Divider/Divider.js +1 -1
- package/dist/DropdownMenu/DropdownMenu.d.ts +6 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +22 -5
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +1 -2
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +5 -3
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +5 -2
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +1 -2
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +1 -2
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +4 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +104 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +427 -0
- package/dist/DropdownMenu/index.d.ts +10 -0
- package/dist/DropdownMenu/index.d.ts.map +1 -1
- package/dist/DropdownMenu/index.js +13 -0
- package/dist/DropdownMenu/menuItemHover.d.ts +23 -0
- package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -0
- package/dist/DropdownMenu/menuItemHover.js +33 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts +8 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -1
- package/dist/DropdownMenu/menuItemRoles.js +10 -1
- package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
- package/dist/DropdownMenu/renderDropdownItems.js +21 -6
- package/dist/Field/Field.d.ts +3 -1
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +6 -4
- package/dist/Field/FieldLabel.d.ts +1 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +43 -16
- package/dist/Field/inputStyles.stylex.d.ts +1 -0
- package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
- package/dist/Field/inputStyles.stylex.js +1 -0
- package/dist/FieldStatus/FieldStatus.d.ts +18 -0
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +60 -6
- package/dist/FileInput/FileInput.d.ts +10 -2
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +54 -35
- package/dist/HoverCard/HoverCard.d.ts +9 -1
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +2 -0
- package/dist/HoverCard/useHoverCard.d.ts +8 -0
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +17 -6
- package/dist/Icon/Icon.d.ts +22 -3
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +19 -3
- package/dist/Item/Item.d.ts +6 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +22 -1
- package/dist/Layer/useLayer.d.ts +6 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +2 -0
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +19 -13
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +7 -0
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +6 -1
- package/dist/MobileNav/MobileNavToggle.d.ts.map +1 -1
- package/dist/MobileNav/MobileNavToggle.js +4 -0
- package/dist/MultiSelector/MultiSelector.d.ts +9 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +104 -50
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +16 -0
- package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
- package/dist/NumberInput/NumberInput.d.ts +10 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +22 -17
- package/dist/Outline/Outline.d.ts +0 -1
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +0 -1
- package/dist/OverflowList/OverflowList.d.ts +20 -3
- package/dist/OverflowList/OverflowList.d.ts.map +1 -1
- package/dist/OverflowList/OverflowList.js +29 -4
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +11 -3
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +3 -2
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +3 -9
- package/dist/PowerSearch/PowerSearch.d.ts +9 -2
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +2 -0
- package/dist/PowerSearch/PowerSearchEditPopover.js +1 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
- package/dist/RadioList/RadioList.d.ts +2 -2
- package/dist/RadioList/RadioListItem.js +4 -4
- package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +2 -1
- package/dist/SelectableCard/SelectableCard.d.ts +9 -2
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +16 -13
- package/dist/Selector/Selector.d.ts +8 -0
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +65 -19
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +16 -0
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +5 -5
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +13 -10
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +21 -8
- package/dist/SideNav/SideNavItem.d.ts +1 -1
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +12 -10
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +106 -36
- package/dist/Stack/stack.stylex.d.ts +9 -9
- package/dist/Switch/Switch.d.ts +8 -1
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +160 -91
- package/dist/TabList/Tab.js +2 -2
- package/dist/TabList/TabMenu.js +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +33 -6
- package/dist/Table/TableCell.js +3 -3
- package/dist/Table/TableHeaderCell.js +3 -3
- package/dist/Table/index.d.ts +2 -0
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +1 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +15 -11
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +36 -26
- package/dist/Table/plugins/rowStatus/index.d.ts +3 -0
- package/dist/Table/plugins/rowStatus/index.d.ts.map +1 -0
- package/dist/Table/plugins/rowStatus/index.js +3 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts +60 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.js +145 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts +13 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +7 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.d.ts +16 -0
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.js +105 -12
- package/dist/Table/plugins/tree/useTableTreeState.d.ts +6 -0
- package/dist/Table/plugins/tree/useTableTreeState.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeState.js +22 -1
- package/dist/Table/types.d.ts +32 -0
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +5 -3
- package/dist/TextArea/TextArea.d.ts +10 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +18 -19
- package/dist/TextInput/TextInput.d.ts +10 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +20 -17
- package/dist/Thumbnail/Thumbnail.d.ts +26 -5
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +97 -54
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts +9 -0
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts.map +1 -0
- package/dist/Thumbnail/thumbnail.markers.stylex.js +14 -0
- package/dist/TimeInput/TimeInput.d.ts +10 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +32 -21
- package/dist/Timestamp/Timestamp.d.ts +3 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +8 -6
- package/dist/Toast/useToast.d.ts.map +1 -1
- package/dist/Toast/useToast.js +2 -5
- package/dist/ToggleButton/ToggleButtonGroup.d.ts +0 -1
- package/dist/ToggleButton/ToggleButtonGroup.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButtonGroup.js +1 -1
- package/dist/Token/Token.d.ts +30 -3
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +17 -2
- package/dist/Token/index.d.ts +1 -1
- package/dist/Token/index.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.d.ts +10 -3
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +20 -6
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +17 -1
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +18 -8
- package/dist/TopNav/TopNavMegaMenu.js +10 -4
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts +9 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.js +8 -1
- package/dist/TopNav/TopNavMenu.d.ts +2 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +68 -6
- package/dist/TreeList/TreeList.d.ts +12 -3
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +3 -0
- package/dist/TreeList/TreeListBranches.d.ts +5 -0
- package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
- package/dist/TreeList/TreeListBranches.js +18 -10
- package/dist/TreeList/TreeListItem.d.ts +8 -2
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +59 -21
- package/dist/TreeList/TreeListTypes.d.ts +25 -1
- package/dist/TreeList/TreeListTypes.d.ts.map +1 -1
- package/dist/TreeList/index.d.ts +2 -2
- package/dist/TreeList/index.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +20 -11
- package/dist/Typeahead/Typeahead.d.ts +9 -2
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +3 -1
- package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
- package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
- package/dist/Typeahead/TypeaheadItem.js +20 -10
- package/dist/astryx.css +61 -39
- package/dist/astryx.umd.js +53 -53
- package/dist/astryx.umd.js.map +4 -4
- package/dist/authoring/doc.d.ts.map +1 -1
- package/dist/docs-types.d.ts +8 -0
- package/dist/docs-types.d.ts.map +1 -1
- package/dist/hooks/computeOverflow.d.ts +47 -0
- package/dist/hooks/computeOverflow.d.ts.map +1 -0
- package/dist/hooks/computeOverflow.js +213 -0
- package/dist/hooks/index.d.ts +3 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +3 -1
- package/dist/hooks/isRtlElement.d.ts +18 -0
- package/dist/hooks/isRtlElement.d.ts.map +1 -0
- package/dist/hooks/isRtlElement.js +27 -0
- package/dist/hooks/useDevWarning.d.ts +18 -0
- package/dist/hooks/useDevWarning.d.ts.map +1 -0
- package/dist/hooks/useDevWarning.js +49 -0
- package/dist/hooks/useGridFocus.d.ts +6 -1
- package/dist/hooks/useGridFocus.d.ts.map +1 -1
- package/dist/hooks/useGridFocus.js +12 -9
- package/dist/hooks/useInputStatusIcon.d.ts +38 -0
- package/dist/hooks/useInputStatusIcon.d.ts.map +1 -0
- package/dist/hooks/useInputStatusIcon.js +158 -0
- package/dist/hooks/useListFocus.d.ts +39 -1
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +54 -9
- package/dist/hooks/useOverflow.d.ts +19 -0
- package/dist/hooks/useOverflow.d.ts.map +1 -1
- package/dist/hooks/useOverflow.js +36 -25
- package/dist/i18n/InternationalizationContext.d.ts +1 -0
- package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
- package/dist/i18n/InternationalizationContext.js +3 -0
- package/dist/i18n/InternationalizationProvider.d.ts +8 -1
- package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
- package/dist/i18n/InternationalizationProvider.js +5 -1
- package/dist/i18n/getLocaleDirection.d.ts +18 -0
- package/dist/i18n/getLocaleDirection.d.ts.map +1 -0
- package/dist/i18n/getLocaleDirection.js +29 -0
- package/dist/i18n/index.d.ts +6 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +7 -1
- package/dist/i18n/resolve.d.ts.map +1 -1
- package/dist/i18n/resolve.js +7 -18
- package/dist/i18n/useDirection.d.ts +2 -0
- package/dist/i18n/useDirection.d.ts.map +1 -0
- package/dist/i18n/useDirection.js +27 -0
- package/dist/theme/Theme.d.ts.map +1 -1
- package/dist/theme/Theme.js +2 -7
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +13 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +51 -0
- package/dist/theme/hct.d.ts +0 -1
- package/dist/theme/hct.d.ts.map +1 -1
- package/dist/theme/hct.js +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.js +2 -1
- package/dist/utils/devWarning.d.ts +42 -0
- package/dist/utils/devWarning.d.ts.map +1 -0
- package/dist/utils/devWarning.js +88 -0
- package/dist/utils/index.d.ts +4 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -2
- package/dist/utils/plainDate.d.ts +30 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +65 -3
- package/dist/utils/rtlStyles.d.ts +24 -0
- package/dist/utils/rtlStyles.d.ts.map +1 -0
- package/dist/utils/rtlStyles.js +27 -0
- package/dist/utils/types.d.ts +13 -0
- package/dist/utils/types.d.ts.map +1 -1
- package/locales/en.json +104 -0
- package/locales/fr-FR.json +14 -0
- package/locales/pseudo.json +78 -0
- package/package.json +6 -1
- package/src/AppShell/AppShell.tsx +6 -0
- package/src/AppShell/AppShellMobileContext.tsx +8 -0
- package/src/AppShell/useAppShellMobile.doc.mjs +8 -0
- package/src/Avatar/Avatar.doc.mjs +64 -5
- package/src/Avatar/Avatar.test.tsx +374 -1
- package/src/Avatar/Avatar.tsx +367 -69
- package/src/Avatar/AvatarStatusDot.doc.mjs +23 -12
- package/src/Avatar/AvatarStatusDot.test.tsx +284 -0
- package/src/Avatar/AvatarStatusDot.tsx +180 -21
- package/src/AvatarGroup/AvatarGroup.doc.mjs +2 -0
- package/src/AvatarGroup/AvatarGroup.test.tsx +141 -1
- package/src/AvatarGroup/AvatarGroup.tsx +58 -3
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +1 -0
- package/src/Banner/Banner.doc.mjs +9 -0
- package/src/Banner/Banner.test.tsx +30 -0
- package/src/Banner/Banner.tsx +53 -9
- package/src/Breadcrumbs/BreadcrumbItem.doc.mjs +26 -0
- package/src/Breadcrumbs/BreadcrumbItem.tsx +333 -14
- package/src/Breadcrumbs/Breadcrumbs.doc.mjs +2 -0
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +335 -2
- package/src/Breadcrumbs/index.ts +31 -0
- package/src/Button/Button.doc.mjs +9 -4
- package/src/Button/Button.test.tsx +49 -0
- package/src/Button/Button.tsx +27 -3
- package/src/ButtonGroup/ButtonGroup.doc.mjs +3 -0
- package/src/ButtonGroup/ButtonGroup.test.tsx +37 -0
- package/src/ButtonGroup/ButtonGroup.tsx +32 -0
- package/src/Calendar/Calendar.doc.mjs +12 -1
- package/src/Calendar/Calendar.test.tsx +362 -19
- package/src/Calendar/Calendar.tsx +111 -32
- package/src/Calendar/dayCellUtils.test.ts +23 -18
- package/src/Calendar/dayCellUtils.ts +3 -3
- package/src/Calendar/styles.ts +33 -39
- package/src/Card/Card.doc.mjs +9 -0
- package/src/Card/Card.test.tsx +21 -3
- package/src/Card/Card.tsx +35 -2
- package/src/Carousel/Carousel.doc.mjs +1 -0
- package/src/Carousel/Carousel.test.tsx +53 -0
- package/src/Carousel/Carousel.tsx +59 -10
- package/src/Chat/ChatComposer.doc.mjs +12 -3
- package/src/Chat/ChatComposer.test.tsx +115 -0
- package/src/Chat/ChatComposer.tsx +73 -9
- package/src/Chat/ChatComposerDrawer.test.tsx +61 -0
- package/src/Chat/ChatComposerDrawer.tsx +11 -1
- package/src/Chat/ChatComposerInput.doc.mjs +7 -0
- package/src/Chat/ChatComposerInput.test.tsx +103 -0
- package/src/Chat/ChatComposerInput.tsx +51 -5
- package/src/Chat/ChatContext.tsx +37 -10
- package/src/Chat/ChatDictationButton.tsx +11 -2
- package/src/Chat/ChatLayout.tsx +7 -5
- package/src/Chat/ChatLayoutScrollButton.tsx +7 -2
- package/src/Chat/ChatMessageMetadata.tsx +1 -2
- package/src/Chat/ChatSendButton.tsx +11 -1
- package/src/Chat/ChatToolCalls.test.tsx +64 -0
- package/src/Chat/ChatToolCalls.tsx +33 -5
- package/src/Chat/index.ts +5 -1
- package/src/Chat/useChatStreamScroll.test.tsx +49 -0
- package/src/Chat/useChatStreamScroll.ts +27 -10
- package/src/Chat/useSpeechRecognition.ts +1 -1
- package/src/Chat/useTriggerMenu.tsx +4 -2
- package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +32 -1
- package/src/CheckboxInput/CheckboxInput.tsx +5 -5
- package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
- package/src/CheckboxList/CheckboxList.test.tsx +81 -3
- package/src/CheckboxList/CheckboxListItem.doc.mjs +33 -5
- package/src/CheckboxList/CheckboxListItem.tsx +41 -5
- package/src/Citation/Citation.doc.mjs +4 -3
- package/src/Citation/Citation.test.tsx +97 -0
- package/src/Citation/Citation.tsx +43 -11
- package/src/ClickableCard/ClickableCard.doc.mjs +2 -0
- package/src/ClickableCard/ClickableCard.test.tsx +34 -0
- package/src/ClickableCard/ClickableCard.tsx +13 -3
- package/src/CodeBlock/CodeBlock.test.tsx +56 -0
- package/src/CodeBlock/CodeBlock.tsx +45 -10
- package/src/Collapsible/Collapsible.doc.mjs +1 -0
- package/src/Collapsible/Collapsible.test.tsx +7 -0
- package/src/Collapsible/Collapsible.tsx +16 -6
- package/src/CommandPalette/CommandPalette.doc.mjs +1 -0
- package/src/CommandPalette/CommandPalette.test.tsx +95 -1
- package/src/CommandPalette/CommandPalette.tsx +44 -3
- package/src/CommandPalette/CommandPaletteGroup.test.tsx +71 -0
- package/src/CommandPalette/CommandPaletteGroup.tsx +12 -1
- package/src/CommandPalette/CommandPaletteInput.doc.mjs +26 -9
- package/src/CommandPalette/CommandPaletteInput.test.tsx +34 -0
- package/src/CommandPalette/CommandPaletteInput.tsx +11 -0
- package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
- package/src/ContextMenu/ContextMenu.test.tsx +235 -0
- package/src/ContextMenu/ContextMenu.tsx +13 -11
- package/src/ContextMenu/index.ts +5 -0
- package/src/DateInput/DateInput.doc.mjs +41 -0
- package/src/DateInput/DateInput.test.tsx +338 -0
- package/src/DateInput/DateInput.tsx +119 -32
- package/src/DateInput/index.ts +1 -0
- package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
- package/src/DateRangeInput/DateRangeInput.test.tsx +140 -0
- package/src/DateRangeInput/DateRangeInput.tsx +42 -30
- package/src/DateTimeInput/DateTimeInput.doc.mjs +22 -1
- package/src/DateTimeInput/DateTimeInput.test.tsx +147 -0
- package/src/DateTimeInput/DateTimeInput.tsx +58 -41
- package/src/Dialog/Dialog.doc.mjs +2 -2
- package/src/Dialog/Dialog.test.tsx +77 -4
- package/src/Dialog/Dialog.tsx +89 -5
- package/src/Dialog/DialogContext.ts +9 -2
- package/src/Dialog/DialogHeader.doc.mjs +2 -2
- package/src/Dialog/DialogHeader.tsx +9 -2
- package/src/Divider/Divider.tsx +2 -2
- package/src/DropdownMenu/DropdownMenu.test.tsx +229 -0
- package/src/DropdownMenu/DropdownMenu.tsx +31 -12
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +9 -4
- package/src/DropdownMenu/DropdownMenuItem.tsx +9 -3
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +1 -2
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +8 -2
- package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +88 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +635 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +553 -0
- package/src/DropdownMenu/index.ts +16 -0
- package/src/DropdownMenu/menuItemHover.ts +39 -0
- package/src/DropdownMenu/menuItemRoles.ts +9 -0
- package/src/DropdownMenu/renderDropdownItems.tsx +29 -15
- package/src/Field/Field.test.tsx +57 -12
- package/src/Field/Field.tsx +20 -14
- package/src/Field/FieldLabel.tsx +9 -1
- package/src/Field/inputStyles.stylex.ts +2 -0
- package/src/FieldStatus/FieldStatus.doc.mjs +17 -5
- package/src/FieldStatus/FieldStatus.test.tsx +150 -40
- package/src/FieldStatus/FieldStatus.tsx +69 -5
- package/src/FileInput/FileInput.doc.mjs +23 -2
- package/src/FileInput/FileInput.test.tsx +135 -12
- package/src/FileInput/FileInput.tsx +65 -51
- package/src/HoverCard/HoverCard.doc.mjs +13 -0
- package/src/HoverCard/HoverCard.test.tsx +21 -2
- package/src/HoverCard/HoverCard.tsx +11 -0
- package/src/HoverCard/useHoverCard.doc.mjs +2 -0
- package/src/HoverCard/useHoverCard.tsx +39 -5
- package/src/Icon/Icon.doc.mjs +16 -2
- package/src/Icon/Icon.test.tsx +89 -0
- package/src/Icon/Icon.tsx +58 -5
- package/src/IconButton/IconButton.doc.mjs +8 -0
- package/src/IconButton/IconButton.test.tsx +15 -18
- package/src/Item/Item.test.tsx +40 -18
- package/src/Item/Item.tsx +38 -2
- package/src/Layer/useLayer.tsx +8 -0
- package/src/Lightbox/Lightbox.tsx +15 -7
- package/src/List/List.test.tsx +9 -8
- package/src/Markdown/Markdown.test.tsx +21 -0
- package/src/Markdown/Markdown.tsx +4 -0
- package/src/MobileNav/MobileNav.tsx +12 -1
- package/src/MobileNav/MobileNavToggle.test.tsx +116 -0
- package/src/MobileNav/MobileNavToggle.tsx +9 -1
- package/src/MultiSelector/MultiSelector.doc.mjs +24 -2
- package/src/MultiSelector/MultiSelector.test.tsx +498 -3
- package/src/MultiSelector/MultiSelector.tsx +149 -65
- package/src/MultiSelector/hooks.ts +17 -0
- package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
- package/src/NumberInput/NumberInput.doc.mjs +21 -0
- package/src/NumberInput/NumberInput.test.tsx +82 -7
- package/src/NumberInput/NumberInput.tsx +36 -28
- package/src/Outline/Outline.tsx +0 -1
- package/src/OverflowList/OverflowList.doc.mjs +39 -6
- package/src/OverflowList/OverflowList.test.tsx +111 -0
- package/src/OverflowList/OverflowList.tsx +48 -8
- package/src/Pagination/Pagination.tsx +11 -3
- package/src/Popover/Popover.tsx +7 -4
- package/src/Popover/usePopover.tsx +9 -13
- package/src/PowerSearch/PowerSearch.doc.mjs +29 -0
- package/src/PowerSearch/PowerSearch.test.tsx +43 -0
- package/src/PowerSearch/PowerSearch.tsx +10 -1
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +67 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +1 -1
- package/src/PowerSearch/usePowerSearchSource.ts +1 -2
- package/src/RadioList/RadioList.doc.mjs +6 -0
- package/src/RadioList/RadioList.tsx +2 -2
- package/src/RadioList/RadioListItem.tsx +4 -4
- package/src/SegmentedControl/SegmentedControlItem.tsx +2 -0
- package/src/SelectableCard/SelectableCard.doc.mjs +2 -0
- package/src/SelectableCard/SelectableCard.test.tsx +46 -4
- package/src/SelectableCard/SelectableCard.tsx +29 -16
- package/src/Selector/Selector.doc.mjs +15 -0
- package/src/Selector/Selector.test.tsx +417 -0
- package/src/Selector/Selector.tsx +86 -21
- package/src/Selector/hooks.ts +17 -0
- package/src/SideNav/SideNav.test.tsx +119 -3
- package/src/SideNav/SideNav.tsx +1 -8
- package/src/SideNav/SideNavCollapseButton.tsx +15 -8
- package/src/SideNav/SideNavHeading.tsx +24 -8
- package/src/SideNav/SideNavItem.tsx +10 -4
- package/src/Slider/Slider.doc.mjs +6 -0
- package/src/Slider/Slider.test.tsx +314 -13
- package/src/Slider/Slider.tsx +117 -28
- package/src/Switch/Switch.doc.mjs +142 -42
- package/src/Switch/Switch.test.tsx +54 -1
- package/src/Switch/Switch.tsx +90 -33
- package/src/TabList/Tab.tsx +2 -2
- package/src/TabList/TabMenu.tsx +2 -2
- package/src/Table/BaseTable.tsx +37 -7
- package/src/Table/Table.doc.mjs +11 -0
- package/src/Table/Table.test.tsx +85 -0
- package/src/Table/TableCell.tsx +3 -3
- package/src/Table/TableHeaderCell.tsx +3 -3
- package/src/Table/index.ts +5 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +15 -8
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +24 -17
- package/src/Table/plugins/rowStatus/index.ts +7 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +138 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +189 -0
- package/src/Table/plugins/selection/useTableSelection.test.tsx +77 -3
- package/src/Table/plugins/selection/useTableSelection.tsx +22 -1
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -1
- package/src/Table/plugins/tree/useTableTreeData.test.tsx +135 -3
- package/src/Table/plugins/tree/useTableTreeData.tsx +139 -8
- package/src/Table/plugins/tree/useTableTreeState.test.tsx +104 -0
- package/src/Table/plugins/tree/useTableTreeState.tsx +46 -2
- package/src/Table/types.ts +33 -0
- package/src/Table/useBaseTablePlugins.ts +10 -6
- package/src/Table/useTableRowStatus.doc.mjs +30 -0
- package/src/Table/useTableSelection.doc.mjs +65 -14
- package/src/Table/useTableTreeData.doc.mjs +29 -0
- package/src/Table/useTableTreeState.doc.mjs +2 -2
- package/src/TextArea/TextArea.doc.mjs +21 -0
- package/src/TextArea/TextArea.test.tsx +32 -1
- package/src/TextArea/TextArea.tsx +27 -26
- package/src/TextInput/TextInput.doc.mjs +21 -0
- package/src/TextInput/TextInput.test.tsx +150 -0
- package/src/TextInput/TextInput.tsx +28 -25
- package/src/Thumbnail/Thumbnail.doc.mjs +19 -10
- package/src/Thumbnail/Thumbnail.test.tsx +98 -7
- package/src/Thumbnail/Thumbnail.tsx +142 -42
- package/src/Thumbnail/thumbnail.markers.stylex.ts +12 -0
- package/src/TimeInput/TimeInput.doc.mjs +21 -0
- package/src/TimeInput/TimeInput.test.tsx +99 -1
- package/src/TimeInput/TimeInput.tsx +43 -31
- package/src/Timestamp/Timestamp.doc.mjs +4 -4
- package/src/Timestamp/Timestamp.test.tsx +32 -0
- package/src/Timestamp/Timestamp.tsx +28 -8
- package/src/Toast/useToast.tsx +7 -8
- package/src/ToggleButton/ToggleButtonGroup.tsx +1 -1
- package/src/Token/Token.test.tsx +21 -15
- package/src/Token/Token.tsx +31 -14
- package/src/Token/index.ts +1 -1
- package/src/Tokenizer/Tokenizer.doc.mjs +38 -2
- package/src/Tokenizer/Tokenizer.test.tsx +206 -2
- package/src/Tokenizer/Tokenizer.tsx +30 -6
- package/src/Tooltip/Tooltip.test.tsx +46 -0
- package/src/Tooltip/useTooltip.tsx +20 -0
- package/src/TopNav/TopNav.test.tsx +125 -1
- package/src/TopNav/TopNavHeading.tsx +24 -8
- package/src/TopNav/TopNavMegaMenu.test.tsx +149 -1
- package/src/TopNav/TopNavMegaMenu.tsx +10 -4
- package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +3 -3
- package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +19 -2
- package/src/TopNav/TopNavMenu.test.tsx +118 -4
- package/src/TopNav/TopNavMenu.tsx +83 -5
- package/src/TreeList/TreeList.doc.mjs +28 -0
- package/src/TreeList/TreeList.test.tsx +272 -0
- package/src/TreeList/TreeList.tsx +23 -2
- package/src/TreeList/TreeListBranches.tsx +24 -8
- package/src/TreeList/TreeListItem.tsx +84 -22
- package/src/TreeList/TreeListTypes.ts +27 -1
- package/src/TreeList/index.ts +2 -2
- package/src/Typeahead/BaseTypeahead.tsx +30 -15
- package/src/Typeahead/Typeahead.doc.mjs +13 -0
- package/src/Typeahead/Typeahead.test.tsx +50 -0
- package/src/Typeahead/Typeahead.tsx +11 -1
- package/src/Typeahead/TypeaheadItem.tsx +2 -1
- package/src/__tests__/inputWidthContract.test.tsx +62 -0
- package/src/authoring/doc.ts +1 -3
- package/src/doc-mjs.d.ts +19 -0
- package/src/docs-types.ts +5 -0
- package/src/hooks/computeOverflow.test.ts +422 -0
- package/src/hooks/computeOverflow.ts +290 -0
- package/src/hooks/index.ts +8 -0
- package/src/hooks/isRtlElement.ts +27 -0
- package/src/hooks/useDevWarning.test.tsx +45 -0
- package/src/hooks/useDevWarning.ts +54 -0
- package/src/hooks/useGridFocus.doc.mjs +3 -3
- package/src/hooks/useGridFocus.test.tsx +41 -0
- package/src/hooks/useGridFocus.ts +21 -10
- package/src/hooks/useInputStatusIcon.test.tsx +162 -0
- package/src/hooks/useInputStatusIcon.tsx +224 -0
- package/src/hooks/useListFocus.doc.mjs +25 -3
- package/src/hooks/useListFocus.test.tsx +153 -1
- package/src/hooks/useListFocus.ts +102 -9
- package/src/hooks/useOverflow.test.ts +96 -4
- package/src/hooks/useOverflow.ts +74 -33
- package/src/i18n/InternationalizationContext.ts +4 -0
- package/src/i18n/InternationalizationProvider.doc.mjs +99 -2
- package/src/i18n/InternationalizationProvider.tsx +12 -2
- package/src/i18n/__tests__/getLocaleDirection.test.ts +40 -0
- package/src/i18n/__tests__/useDirection.test.tsx +66 -0
- package/src/i18n/getLocaleDirection.ts +29 -0
- package/src/i18n/index.ts +6 -0
- package/src/i18n/resolve.ts +9 -21
- package/src/i18n/useDirection.ts +29 -0
- package/src/reset.css +0 -26
- package/src/reset.test.ts +60 -0
- package/src/theme/Theme.tsx +11 -14
- package/src/theme/derivedVarRegistry.test.ts +1 -0
- package/src/theme/derivedVarRegistry.ts +6 -0
- package/src/theme/generateThemeRules.test.ts +107 -0
- package/src/theme/generateThemeRules.ts +56 -0
- package/src/theme/hct.ts +1 -1
- package/src/theme/syntax/defineSyntaxTheme.ts +5 -6
- package/src/utils/devWarning.test.ts +56 -0
- package/src/utils/devWarning.ts +102 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/plainDate.test.ts +46 -6
- package/src/utils/plainDate.ts +69 -3
- package/src/utils/rtlStyles.ts +27 -0
- package/src/utils/types.ts +14 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
import {describe, it, expect} from 'vitest';
|
|
4
|
+
import {render, screen} from '@testing-library/react';
|
|
5
|
+
import * as stylex from '@stylexjs/stylex';
|
|
6
|
+
import {colorVars} from '../theme/tokens.stylex';
|
|
7
|
+
import {Avatar} from './Avatar';
|
|
8
|
+
import {AvatarStatusDot, type AvatarStatusDotVariant} from './AvatarStatusDot';
|
|
9
|
+
|
|
10
|
+
const GLYPH_SELECTOR = '.astryx-avatar-status-dot-glyph';
|
|
11
|
+
const DOT_SELECTOR = '.astryx-avatar-status-dot';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Renders an AvatarStatusDot inside an Avatar of the given numeric size and
|
|
15
|
+
* returns the dot root element. Size tiers: <=36 -> 10px dot (no icons),
|
|
16
|
+
* 40-72 -> 20px dot, >=96 -> 32px dot.
|
|
17
|
+
*/
|
|
18
|
+
function renderDot(
|
|
19
|
+
dotProps: React.ComponentProps<typeof AvatarStatusDot>,
|
|
20
|
+
avatarSize: 36 | 48 | 128 = 48,
|
|
21
|
+
) {
|
|
22
|
+
const {container} = render(
|
|
23
|
+
<Avatar
|
|
24
|
+
name="Ada Lovelace"
|
|
25
|
+
size={avatarSize}
|
|
26
|
+
status={<AvatarStatusDot {...dotProps} />}
|
|
27
|
+
/>,
|
|
28
|
+
);
|
|
29
|
+
const dot = container.querySelector(DOT_SELECTOR);
|
|
30
|
+
expect(dot).not.toBeNull();
|
|
31
|
+
return dot as HTMLElement;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
describe('AvatarStatusDot', () => {
|
|
35
|
+
describe('shape glyphs (WCAG 1.4.1 — colour is not the only signal)', () => {
|
|
36
|
+
it('renders no glyph for success: the plain filled dot is the reference shape', () => {
|
|
37
|
+
const dot = renderDot({variant: 'success'});
|
|
38
|
+
expect(dot.querySelector(GLYPH_SELECTOR)).toBeNull();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('renders a ring glyph for neutral', () => {
|
|
42
|
+
const dot = renderDot({variant: 'neutral'});
|
|
43
|
+
const glyph = dot.querySelector(GLYPH_SELECTOR);
|
|
44
|
+
expect(glyph).not.toBeNull();
|
|
45
|
+
expect(glyph).toHaveAttribute('data-shape', 'ring');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('renders a minus glyph for error', () => {
|
|
49
|
+
const dot = renderDot({variant: 'error'});
|
|
50
|
+
const glyph = dot.querySelector(GLYPH_SELECTOR);
|
|
51
|
+
expect(glyph).not.toBeNull();
|
|
52
|
+
expect(glyph).toHaveAttribute('data-shape', 'minus');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('hides the glyph from assistive tech: it is a visual redundancy of the status', () => {
|
|
56
|
+
const dot = renderDot({variant: 'error'});
|
|
57
|
+
expect(dot.querySelector(GLYPH_SELECTOR)).toHaveAttribute(
|
|
58
|
+
'aria-hidden',
|
|
59
|
+
'true',
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('renders glyphs at every size tier', () => {
|
|
64
|
+
for (const size of [36, 48, 128] as const) {
|
|
65
|
+
const dot = renderDot({variant: 'neutral'}, size);
|
|
66
|
+
expect(dot.querySelector(GLYPH_SELECTOR)).not.toBeNull();
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('draws the glyph as an inline svg sized to the dot inner field', () => {
|
|
71
|
+
// The glyph is a stroked <svg>, matching how the rest of the system
|
|
72
|
+
// draws marks (Icon's defaultIcons, the CheckboxInput checkmark).
|
|
73
|
+
// Its viewBox is 1 user unit per px of the dot's inner field
|
|
74
|
+
// (dot minus both borders), so stroke widths below are literal px.
|
|
75
|
+
const cases = [
|
|
76
|
+
[36, 8],
|
|
77
|
+
[48, 16],
|
|
78
|
+
[128, 24],
|
|
79
|
+
] as const;
|
|
80
|
+
for (const [avatarSize, field] of cases) {
|
|
81
|
+
const glyph = renderDot({variant: 'neutral'}, avatarSize).querySelector(
|
|
82
|
+
GLYPH_SELECTOR,
|
|
83
|
+
) as SVGElement;
|
|
84
|
+
expect(glyph.tagName.toLowerCase(), `avatar ${avatarSize}`).toBe('svg');
|
|
85
|
+
expect(glyph.getAttribute('viewBox'), `avatar ${avatarSize}`).toBe(
|
|
86
|
+
`0 0 ${field} ${field}`,
|
|
87
|
+
);
|
|
88
|
+
expect(glyph.getAttribute('width'), `avatar ${avatarSize}`).toBe(
|
|
89
|
+
String(field),
|
|
90
|
+
);
|
|
91
|
+
expect(glyph.getAttribute('height'), `avatar ${avatarSize}`).toBe(
|
|
92
|
+
String(field),
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('strokes the ring at the system glyph weight, not a quarter of the field', () => {
|
|
98
|
+
// stroke ~= field / 12, floored at 1px for the smallest tier, which
|
|
99
|
+
// puts these on the icon family's 1 / 1.5 / 2 ladder (~6-12% of the
|
|
100
|
+
// field) instead of the 25% band a CSS box cutout produced.
|
|
101
|
+
const cases = [
|
|
102
|
+
// avatar size, field, stroke, radius = (field - stroke) / 2
|
|
103
|
+
[36, 8, 1, 3.5],
|
|
104
|
+
[48, 16, 1.5, 7.25],
|
|
105
|
+
[128, 24, 2, 11],
|
|
106
|
+
] as const;
|
|
107
|
+
for (const [avatarSize, field, stroke, radius] of cases) {
|
|
108
|
+
const circle = renderDot(
|
|
109
|
+
{variant: 'neutral'},
|
|
110
|
+
avatarSize,
|
|
111
|
+
).querySelector(`${GLYPH_SELECTOR} circle`) as SVGCircleElement;
|
|
112
|
+
expect(circle, `avatar ${avatarSize}`).not.toBeNull();
|
|
113
|
+
expect(
|
|
114
|
+
circle.getAttribute('stroke-width'),
|
|
115
|
+
`avatar ${avatarSize}`,
|
|
116
|
+
).toBe(String(stroke));
|
|
117
|
+
// Radius is to the stroke centreline, so the ring's outer edge lands
|
|
118
|
+
// exactly on the inner field and never clips against the border.
|
|
119
|
+
expect(circle.getAttribute('r'), `avatar ${avatarSize}`).toBe(
|
|
120
|
+
String(radius),
|
|
121
|
+
);
|
|
122
|
+
expect(circle.getAttribute('cx'), `avatar ${avatarSize}`).toBe(
|
|
123
|
+
String(field / 2),
|
|
124
|
+
);
|
|
125
|
+
expect(circle.getAttribute('cy'), `avatar ${avatarSize}`).toBe(
|
|
126
|
+
String(field / 2),
|
|
127
|
+
);
|
|
128
|
+
expect(circle.getAttribute('fill'), `avatar ${avatarSize}`).toBe(
|
|
129
|
+
'none',
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('strokes the minus bar at the same weight, spanning 75% of the field with round caps', () => {
|
|
135
|
+
// Ends are inset by half the stroke so the round caps land inside the
|
|
136
|
+
// 75% span rather than overhanging it.
|
|
137
|
+
const cases = [
|
|
138
|
+
// avatar size, field, stroke, x1, x2
|
|
139
|
+
[36, 8, 1, 1.5, 6.5],
|
|
140
|
+
[48, 16, 1.5, 2.75, 13.25],
|
|
141
|
+
[128, 24, 2, 4, 20],
|
|
142
|
+
] as const;
|
|
143
|
+
for (const [avatarSize, field, stroke, x1, x2] of cases) {
|
|
144
|
+
const line = renderDot({variant: 'error'}, avatarSize).querySelector(
|
|
145
|
+
`${GLYPH_SELECTOR} line`,
|
|
146
|
+
) as SVGLineElement;
|
|
147
|
+
expect(line, `avatar ${avatarSize}`).not.toBeNull();
|
|
148
|
+
expect(line.getAttribute('stroke-width'), `avatar ${avatarSize}`).toBe(
|
|
149
|
+
String(stroke),
|
|
150
|
+
);
|
|
151
|
+
expect(line.getAttribute('x1'), `avatar ${avatarSize}`).toBe(
|
|
152
|
+
String(x1),
|
|
153
|
+
);
|
|
154
|
+
expect(line.getAttribute('x2'), `avatar ${avatarSize}`).toBe(
|
|
155
|
+
String(x2),
|
|
156
|
+
);
|
|
157
|
+
expect(line.getAttribute('y1'), `avatar ${avatarSize}`).toBe(
|
|
158
|
+
String(field / 2),
|
|
159
|
+
);
|
|
160
|
+
expect(line.getAttribute('y2'), `avatar ${avatarSize}`).toBe(
|
|
161
|
+
String(field / 2),
|
|
162
|
+
);
|
|
163
|
+
expect(
|
|
164
|
+
line.getAttribute('stroke-linecap'),
|
|
165
|
+
`avatar ${avatarSize}`,
|
|
166
|
+
).toBe('round');
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('paints both glyphs from currentColor so the dot owns the ink colour', () => {
|
|
171
|
+
for (const variant of ['neutral', 'error'] as const) {
|
|
172
|
+
const mark = renderDot({variant}, 48).querySelector(
|
|
173
|
+
`${GLYPH_SELECTOR} circle, ${GLYPH_SELECTOR} line`,
|
|
174
|
+
) as SVGElement;
|
|
175
|
+
expect(mark.getAttribute('stroke'), variant).toBe('currentColor');
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('fills the ring variant with surface and inks it with the variant colour', () => {
|
|
180
|
+
// A ring only reads as hollow if its interior is not the variant
|
|
181
|
+
// colour, so `neutral` inverts: surface fill, coloured stroke.
|
|
182
|
+
// StyleX atomic classes are deterministic, so a local probe pins it.
|
|
183
|
+
const probe = stylex.create({
|
|
184
|
+
ring: {
|
|
185
|
+
backgroundColor: colorVars['--color-background-surface'],
|
|
186
|
+
color: colorVars['--color-text-secondary'],
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
const dot = renderDot({variant: 'neutral'}, 48);
|
|
190
|
+
const atomicClasses = (stylex.props(probe.ring).className ?? '')
|
|
191
|
+
.split(' ')
|
|
192
|
+
// Dev mode prepends a per-file `File__style.key` debug class that
|
|
193
|
+
// legitimately differs between the probe and the component.
|
|
194
|
+
.filter(cls => !cls.includes('__'));
|
|
195
|
+
expect(atomicClasses.length).toBeGreaterThan(0);
|
|
196
|
+
for (const cls of atomicClasses) {
|
|
197
|
+
expect(dot.className).toContain(cls);
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('lets a user icon inherit the dot ink instead of hard-coding surface', () => {
|
|
202
|
+
// Surface ink on the surface-filled ring variant would be invisible.
|
|
203
|
+
const probe = stylex.create({
|
|
204
|
+
surfaceInk: {color: colorVars['--color-background-surface']},
|
|
205
|
+
});
|
|
206
|
+
renderDot(
|
|
207
|
+
{variant: 'neutral', icon: <svg data-testid="user-icon" />},
|
|
208
|
+
48,
|
|
209
|
+
);
|
|
210
|
+
const iconWrapper = screen.getByTestId('user-icon')
|
|
211
|
+
.parentElement as HTMLElement;
|
|
212
|
+
const surfaceInkClasses = (stylex.props(probe.surfaceInk).className ?? '')
|
|
213
|
+
.split(' ')
|
|
214
|
+
.filter(cls => !cls.includes('__'));
|
|
215
|
+
expect(surfaceInkClasses.length).toBeGreaterThan(0);
|
|
216
|
+
for (const cls of surfaceInkClasses) {
|
|
217
|
+
expect(iconWrapper.className).not.toContain(cls);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('renders no glyph for custom augmented variants (documented: they must bring their own non-colour mark)', () => {
|
|
222
|
+
const dot = renderDot({variant: 'away' as AvatarStatusDotVariant});
|
|
223
|
+
expect(dot.querySelector(GLYPH_SELECTOR)).toBeNull();
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
describe('glyph and icon interplay', () => {
|
|
228
|
+
it('suppresses the glyph when a user icon renders: the icon is the non-colour mark', () => {
|
|
229
|
+
const dot = renderDot(
|
|
230
|
+
{variant: 'error', icon: <svg data-testid="user-icon" />},
|
|
231
|
+
48,
|
|
232
|
+
);
|
|
233
|
+
expect(screen.getByTestId('user-icon')).toBeInTheDocument();
|
|
234
|
+
expect(dot.querySelector(GLYPH_SELECTOR)).toBeNull();
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('keeps the glyph at the smallest tier where icons never render', () => {
|
|
238
|
+
const dot = renderDot(
|
|
239
|
+
{variant: 'error', icon: <svg data-testid="user-icon" />},
|
|
240
|
+
36,
|
|
241
|
+
);
|
|
242
|
+
expect(screen.queryByTestId('user-icon')).not.toBeInTheDocument();
|
|
243
|
+
expect(dot.querySelector(GLYPH_SELECTOR)).not.toBeNull();
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('keeps the glyph for non-renderable icons: booleans from `cond && <Icon />` render nothing', () => {
|
|
247
|
+
for (const nonRenderable of [true, false, ''] as const) {
|
|
248
|
+
const dot = renderDot({variant: 'error', icon: nonRenderable}, 48);
|
|
249
|
+
expect(
|
|
250
|
+
dot.querySelector(GLYPH_SELECTOR),
|
|
251
|
+
`icon={${JSON.stringify(nonRenderable)}}`,
|
|
252
|
+
).not.toBeNull();
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
describe('existing contract', () => {
|
|
258
|
+
it('exposes role="img" with the label as accessible name when label is provided', () => {
|
|
259
|
+
const dot = renderDot({variant: 'success', label: 'Online'});
|
|
260
|
+
expect(dot).toHaveAttribute('role', 'img');
|
|
261
|
+
expect(dot).toHaveAttribute('aria-label', 'Online');
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('has no img role without a label', () => {
|
|
265
|
+
const dot = renderDot({variant: 'success'});
|
|
266
|
+
expect(dot).not.toHaveAttribute('role');
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
it('reflects the variant as a data attribute for theming', () => {
|
|
270
|
+
const dot = renderDot({variant: 'neutral'});
|
|
271
|
+
expect(dot).toHaveAttribute('data-variant', 'neutral');
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('renders the user icon at tiers with room for it, hidden from assistive tech', () => {
|
|
275
|
+
renderDot(
|
|
276
|
+
{variant: 'success', icon: <svg data-testid="user-icon" />},
|
|
277
|
+
128,
|
|
278
|
+
);
|
|
279
|
+
const icon = screen.getByTestId('user-icon');
|
|
280
|
+
expect(icon).toBeInTheDocument();
|
|
281
|
+
expect(icon.parentElement).toHaveAttribute('aria-hidden', 'true');
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
});
|
|
@@ -20,37 +20,49 @@ import type {BaseProps} from '../BaseProps';
|
|
|
20
20
|
import * as stylex from '@stylexjs/stylex';
|
|
21
21
|
import {colorVars, radiusVars} from '../theme/tokens.stylex';
|
|
22
22
|
import {AvatarSizeContext} from './AvatarSizeContext';
|
|
23
|
-
import {mergeProps} from '../utils';
|
|
23
|
+
import {isRenderable, mergeProps} from '../utils';
|
|
24
24
|
import {themeProps} from '../utils/themeProps';
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
27
|
+
* Discrete size tier of the status dot, derived from the avatar size.
|
|
28
|
+
* Keys the built-in shape glyph's stroke weight — see `GLYPH_STROKE_WIDTH`.
|
|
29
|
+
*/
|
|
30
|
+
type StatusDotSizeTier = 'small' | 'medium' | 'large';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Resolves the status dot size, border width, icon size, and size tier
|
|
34
|
+
* based on the avatar size.
|
|
29
35
|
*
|
|
30
36
|
* Uses discrete size tiers rather than a continuous ratio so the dot
|
|
31
37
|
* looks intentional at every avatar size:
|
|
32
38
|
*
|
|
33
|
-
* | Avatar size | Dot | Border | Icon |
|
|
34
|
-
*
|
|
35
|
-
* | ≤ 36px | 10px | 1px | — |
|
|
36
|
-
* | 40–72px | 20px | 2px | 12px |
|
|
37
|
-
* | ≥ 96px | 32px | 4px | 18px |
|
|
39
|
+
* | Avatar size | Tier | Dot | Border | Icon | Field | Glyph stroke |
|
|
40
|
+
* |--------------|--------|------|--------|------|-------|--------------|
|
|
41
|
+
* | ≤ 36px | small | 10px | 1px | — | 8px | 1px |
|
|
42
|
+
* | 40–72px | medium | 20px | 2px | 12px | 16px | 1.5px |
|
|
43
|
+
* | ≥ 96px | large | 32px | 4px | 18px | 24px | 2px |
|
|
44
|
+
*
|
|
45
|
+
* "Field" is the dot's inner field — the dot minus both borders — that the
|
|
46
|
+
* shape glyph is drawn into; see `GLYPH_STROKE_WIDTH` for the stroke ladder.
|
|
38
47
|
*
|
|
39
48
|
* Icons are not rendered at the smallest tier — there isn't enough
|
|
40
|
-
* room for them to be legible.
|
|
49
|
+
* room for them to be legible. The built-in shape glyphs (see
|
|
50
|
+
* `glyphShapeMap`) do render there, so status stays distinguishable
|
|
51
|
+
* without colour at every size.
|
|
41
52
|
*/
|
|
42
53
|
function resolveStatusDotSize(avatarSize: number): {
|
|
43
54
|
dotSize: number;
|
|
44
55
|
borderWidth: number;
|
|
45
56
|
iconSize: number;
|
|
57
|
+
tier: StatusDotSizeTier;
|
|
46
58
|
} {
|
|
47
59
|
if (avatarSize <= 36) {
|
|
48
|
-
return {dotSize: 10, borderWidth: 1, iconSize: 0};
|
|
60
|
+
return {dotSize: 10, borderWidth: 1, iconSize: 0, tier: 'small'};
|
|
49
61
|
}
|
|
50
62
|
if (avatarSize <= 72) {
|
|
51
|
-
return {dotSize: 20, borderWidth: 2, iconSize: 12};
|
|
63
|
+
return {dotSize: 20, borderWidth: 2, iconSize: 12, tier: 'medium'};
|
|
52
64
|
}
|
|
53
|
-
return {dotSize: 32, borderWidth: 4, iconSize: 18};
|
|
65
|
+
return {dotSize: 32, borderWidth: 4, iconSize: 18, tier: 'large'};
|
|
54
66
|
}
|
|
55
67
|
|
|
56
68
|
/**
|
|
@@ -65,6 +77,13 @@ function resolveStatusDotSize(avatarSize: number): {
|
|
|
65
77
|
* }
|
|
66
78
|
* }
|
|
67
79
|
* ```
|
|
80
|
+
*
|
|
81
|
+
* Custom variants render no background fill, no ink colour, and no built-in
|
|
82
|
+
* shape glyph — the theme must supply the fill and, if it passes an `icon`,
|
|
83
|
+
* a `color` for it to paint with. It should also supply a non-colour mark
|
|
84
|
+
* so the status is not distinguishable by colour alone (a WCAG 1.4.1
|
|
85
|
+
* failure): pass `icon`, or theme a glyph onto the dot via
|
|
86
|
+
* `.astryx-avatar-status-dot[data-variant="..."]` (e.g. a `::before` mark).
|
|
68
87
|
*/
|
|
69
88
|
export interface AvatarStatusDotVariantMap {
|
|
70
89
|
success: true;
|
|
@@ -80,12 +99,14 @@ export type AvatarStatusDotVariant = keyof AvatarStatusDotVariantMap;
|
|
|
80
99
|
export interface AvatarStatusDotProps extends BaseProps<HTMLDivElement> {
|
|
81
100
|
ref?: React.Ref<HTMLDivElement>;
|
|
82
101
|
/**
|
|
83
|
-
* The semantic
|
|
84
|
-
* -
|
|
85
|
-
*
|
|
86
|
-
* - `
|
|
102
|
+
* The semantic variant of the dot. Each variant pairs a colour with a
|
|
103
|
+
* distinct built-in shape so status is never conveyed by colour alone
|
|
104
|
+
* (WCAG 2.1 SC 1.4.1):
|
|
105
|
+
* - `success` — filled green dot (e.g. online, accepted)
|
|
106
|
+
* - `neutral` — grey ring (e.g. away, offline, pending)
|
|
107
|
+
* - `error` — red dot with a minus bar (e.g. busy, do not disturb)
|
|
87
108
|
*
|
|
88
|
-
* Matches the `variant` convention from `StatusDot`.
|
|
109
|
+
* Matches the `variant` naming convention from `StatusDot`.
|
|
89
110
|
* @default 'success'
|
|
90
111
|
*/
|
|
91
112
|
variant?: AvatarStatusDotVariant;
|
|
@@ -93,6 +114,13 @@ export interface AvatarStatusDotProps extends BaseProps<HTMLDivElement> {
|
|
|
93
114
|
* Accessible label for the status dot.
|
|
94
115
|
* Describes the meaning of the indicator for screen readers
|
|
95
116
|
* (e.g. "Online", "Accepted", "John Doe is busy").
|
|
117
|
+
*
|
|
118
|
+
* Note: inside an Avatar the dot sits in the avatar's `role="img"`
|
|
119
|
+
* subtree, where descendant semantics are pruned — the dot is never its
|
|
120
|
+
* own stop there. Instead, Avatar reads this `label` and composes it into
|
|
121
|
+
* its own accessible name (e.g. "Jane Doe, Online"), which is how the
|
|
122
|
+
* status reaches assistive tech (WCAG 4.1.2). Standalone dots (outside an
|
|
123
|
+
* Avatar) expose `role="img"` with this label directly.
|
|
96
124
|
*/
|
|
97
125
|
label?: string;
|
|
98
126
|
/**
|
|
@@ -101,6 +129,14 @@ export interface AvatarStatusDotProps extends BaseProps<HTMLDivElement> {
|
|
|
101
129
|
* The icon is automatically sized to fit the dot and hidden
|
|
102
130
|
* at the smallest avatar sizes where there isn't enough room.
|
|
103
131
|
*
|
|
132
|
+
* A rendered icon replaces the variant's built-in shape glyph, so use a
|
|
133
|
+
* different icon per status — the same icon on every variant leaves the
|
|
134
|
+
* statuses distinguishable by colour alone (WCAG 1.4.1). At the smallest
|
|
135
|
+
* avatar sizes the built-in glyph still shows instead of the icon.
|
|
136
|
+
* Booleans and empty strings are ignored (safe for `cond && <Icon />`),
|
|
137
|
+
* but a component that renders nothing still counts as an icon and
|
|
138
|
+
* suppresses the glyph.
|
|
139
|
+
*
|
|
104
140
|
* @example
|
|
105
141
|
* ```
|
|
106
142
|
* <AvatarStatusDot variant="success" label="Verified" icon={<CheckIcon />} />
|
|
@@ -119,20 +155,29 @@ const styles = stylex.create({
|
|
|
119
155
|
alignItems: 'center',
|
|
120
156
|
justifyContent: 'center',
|
|
121
157
|
},
|
|
158
|
+
// Each variant sets both the plate colour and the ink colour. Everything
|
|
159
|
+
// drawn on the dot — the shape glyph and any user `icon` — paints from
|
|
160
|
+
// `currentColor`, so the two can never drift out of contrast.
|
|
122
161
|
success: {
|
|
123
162
|
backgroundColor: colorVars['--color-success'],
|
|
163
|
+
color: colorVars['--color-background-surface'],
|
|
124
164
|
},
|
|
165
|
+
// The ring variant inverts: a hollow shape only reads as hollow if its
|
|
166
|
+
// interior is not the variant colour, so the plate is surface and the
|
|
167
|
+
// colour moves to the stroke. This also keeps a user `icon` legible on
|
|
168
|
+
// it — surface ink on a surface plate would be invisible.
|
|
125
169
|
neutral: {
|
|
126
|
-
backgroundColor: colorVars['--color-
|
|
170
|
+
backgroundColor: colorVars['--color-background-surface'],
|
|
171
|
+
color: colorVars['--color-text-secondary'],
|
|
127
172
|
},
|
|
128
173
|
error: {
|
|
129
174
|
backgroundColor: colorVars['--color-error'],
|
|
175
|
+
color: colorVars['--color-background-surface'],
|
|
130
176
|
},
|
|
131
177
|
icon: {
|
|
132
178
|
display: 'flex',
|
|
133
179
|
alignItems: 'center',
|
|
134
180
|
justifyContent: 'center',
|
|
135
|
-
color: colorVars['--color-background-surface'],
|
|
136
181
|
lineHeight: 0,
|
|
137
182
|
},
|
|
138
183
|
});
|
|
@@ -157,10 +202,112 @@ const variantStyleMap: Partial<
|
|
|
157
202
|
error: styles.error,
|
|
158
203
|
};
|
|
159
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Built-in shape glyph per variant, so each status differs by shape and not
|
|
207
|
+
* only by colour (WCAG 2.1 SC 1.4.1). The glyph is a stroked inline SVG
|
|
208
|
+
* painted in `currentColor`:
|
|
209
|
+
* - `ring` — a stroked circle on a surface plate; the dot reads as hollow
|
|
210
|
+
* (away/offline).
|
|
211
|
+
* - `minus` — a round-capped bar across the filled dot; the dot reads as
|
|
212
|
+
* "do not disturb" (busy).
|
|
213
|
+
*
|
|
214
|
+
* `success` stays the plain filled dot — filled, hollow, and barred are the
|
|
215
|
+
* three distinct fill topologies. Custom augmented variants have no entry
|
|
216
|
+
* and render no glyph; see the `AvatarStatusDotVariantMap` docs.
|
|
217
|
+
*/
|
|
218
|
+
type AvatarStatusDotGlyphShape = 'ring' | 'minus';
|
|
219
|
+
|
|
220
|
+
const glyphShapeMap: Partial<
|
|
221
|
+
Record<AvatarStatusDotVariant, AvatarStatusDotGlyphShape>
|
|
222
|
+
> = {
|
|
223
|
+
neutral: 'ring',
|
|
224
|
+
error: 'minus',
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Glyph stroke weight per tier, in px of the dot's inner field.
|
|
229
|
+
*
|
|
230
|
+
* Roughly `field / 12`, floored at 1px so the smallest tier stays visible.
|
|
231
|
+
* That lands on the 1 / 1.5 / 2 ladder the rest of the system draws with —
|
|
232
|
+
* `Icon`'s default set strokes at 1.5 in a 24 viewBox, as does the
|
|
233
|
+
* `CheckboxInput` checkmark — rather than the 25% band a CSS box cutout
|
|
234
|
+
* produced, which was several times heavier than any other glyph we ship.
|
|
235
|
+
*/
|
|
236
|
+
const GLYPH_STROKE_WIDTH: Record<StatusDotSizeTier, number> = {
|
|
237
|
+
small: 1,
|
|
238
|
+
medium: 1.5,
|
|
239
|
+
large: 2,
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
/** Fraction of the inner field the minus bar spans, cap to cap. */
|
|
243
|
+
const MINUS_BAR_SPAN = 0.75;
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* The built-in shape glyph, drawn as a stroked inline SVG in `currentColor`.
|
|
247
|
+
*
|
|
248
|
+
* Stroking (rather than a CSS box) is what buys sub-pixel control and round
|
|
249
|
+
* line caps, so the mark stays intentional at every tier — including the
|
|
250
|
+
* 10px dot, where a box cutout can only land on whole pixels.
|
|
251
|
+
*
|
|
252
|
+
* `viewBox` is one user unit per px of the inner field, so every value here
|
|
253
|
+
* is literal px.
|
|
254
|
+
*/
|
|
255
|
+
function StatusDotGlyph({
|
|
256
|
+
shape,
|
|
257
|
+
field,
|
|
258
|
+
stroke,
|
|
259
|
+
}: {
|
|
260
|
+
shape: AvatarStatusDotGlyphShape;
|
|
261
|
+
field: number;
|
|
262
|
+
stroke: number;
|
|
263
|
+
}) {
|
|
264
|
+
const center = field / 2;
|
|
265
|
+
return (
|
|
266
|
+
<svg
|
|
267
|
+
aria-hidden="true"
|
|
268
|
+
viewBox={`0 0 ${field} ${field}`}
|
|
269
|
+
width={field}
|
|
270
|
+
height={field}
|
|
271
|
+
fill="none"
|
|
272
|
+
{...themeProps('avatar-status-dot-glyph', {shape})}>
|
|
273
|
+
{shape === 'ring' ? (
|
|
274
|
+
// Radius is to the stroke centreline, so the ring's outer edge lands
|
|
275
|
+
// exactly on the inner field and never clips against the border.
|
|
276
|
+
<circle
|
|
277
|
+
cx={center}
|
|
278
|
+
cy={center}
|
|
279
|
+
r={(field - stroke) / 2}
|
|
280
|
+
fill="none"
|
|
281
|
+
stroke="currentColor"
|
|
282
|
+
strokeWidth={stroke}
|
|
283
|
+
/>
|
|
284
|
+
) : (
|
|
285
|
+
// Ends inset by half the stroke so the round caps land inside the
|
|
286
|
+
// span rather than overhanging it.
|
|
287
|
+
<line
|
|
288
|
+
x1={(field * (1 - MINUS_BAR_SPAN)) / 2 + stroke / 2}
|
|
289
|
+
y1={center}
|
|
290
|
+
x2={(field * (1 + MINUS_BAR_SPAN)) / 2 - stroke / 2}
|
|
291
|
+
y2={center}
|
|
292
|
+
stroke="currentColor"
|
|
293
|
+
strokeWidth={stroke}
|
|
294
|
+
strokeLinecap="round"
|
|
295
|
+
/>
|
|
296
|
+
)}
|
|
297
|
+
</svg>
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
160
301
|
/**
|
|
161
302
|
* A status indicator dot that automatically scales to match the parent
|
|
162
303
|
* Avatar's size.
|
|
163
304
|
*
|
|
305
|
+
* Each variant pairs a colour with a distinct built-in shape (filled dot,
|
|
306
|
+
* ring, minus bar) so status stays distinguishable without colour
|
|
307
|
+
* perception (WCAG 2.1 SC 1.4.1). Themes can target the shape glyph via
|
|
308
|
+
* the `astryx-avatar-status-dot-glyph` class and its `data-shape`
|
|
309
|
+
* attribute.
|
|
310
|
+
*
|
|
164
311
|
* Must be used inside an Avatar's `status` prop so it can read
|
|
165
312
|
* the avatar size from context.
|
|
166
313
|
*
|
|
@@ -189,7 +336,12 @@ export function AvatarStatusDot({
|
|
|
189
336
|
...props
|
|
190
337
|
}: AvatarStatusDotProps) {
|
|
191
338
|
const avatarSize = use(AvatarSizeContext);
|
|
192
|
-
const {dotSize, borderWidth, iconSize} =
|
|
339
|
+
const {dotSize, borderWidth, iconSize, tier} =
|
|
340
|
+
resolveStatusDotSize(avatarSize);
|
|
341
|
+
const showsIcon = isRenderable(icon) && iconSize > 0;
|
|
342
|
+
// A rendered icon is itself a non-colour mark; overlaying both cutouts in
|
|
343
|
+
// the dot's small inner field would make each illegible.
|
|
344
|
+
const glyphShape = showsIcon ? undefined : glyphShapeMap[variant];
|
|
193
345
|
|
|
194
346
|
return (
|
|
195
347
|
<div
|
|
@@ -207,13 +359,20 @@ export function AvatarStatusDot({
|
|
|
207
359
|
className,
|
|
208
360
|
style,
|
|
209
361
|
)}>
|
|
210
|
-
{
|
|
362
|
+
{showsIcon && (
|
|
211
363
|
<span
|
|
212
364
|
aria-hidden="true"
|
|
213
365
|
{...stylex.props(styles.icon, dynamicStyles.iconSize(iconSize))}>
|
|
214
366
|
{icon}
|
|
215
367
|
</span>
|
|
216
368
|
)}
|
|
369
|
+
{glyphShape && (
|
|
370
|
+
<StatusDotGlyph
|
|
371
|
+
shape={glyphShape}
|
|
372
|
+
field={dotSize - borderWidth * 2}
|
|
373
|
+
stroke={GLYPH_STROKE_WIDTH[tier]}
|
|
374
|
+
/>
|
|
375
|
+
)}
|
|
217
376
|
</div>
|
|
218
377
|
);
|
|
219
378
|
}
|
|
@@ -14,6 +14,7 @@ export const docs = {
|
|
|
14
14
|
{guidance: true, description: 'Set max to limit visible avatars when the list is long; 3-5 is typical.'},
|
|
15
15
|
{guidance: true, description: 'Use AvatarGroupOverflow for custom overflow content like a popover trigger or "add member" button.'},
|
|
16
16
|
{guidance: true, description: 'Pass status dots, click handlers, or tooltips directly on each Avatar child.'},
|
|
17
|
+
{guidance: true, description: 'Make avatars interactive with href or onClick to link to profiles. Interactive avatars share a single Tab stop; arrow keys move between them, and the group announces a keyboard hint to assistive tech.'},
|
|
17
18
|
{guidance: false, description: "Don't nest AvatarGroups; use a single group with all avatars."},
|
|
18
19
|
],
|
|
19
20
|
anatomy: [
|
|
@@ -94,6 +95,7 @@ export const docsDense = {
|
|
|
94
95
|
{guidance: true, description: 'Set max to limit visible avatars (3-5 typical).'},
|
|
95
96
|
{guidance: true, description: 'Use AvatarGroupOverflow for custom overflow (popover, add button).'},
|
|
96
97
|
{guidance: true, description: 'Pass status dots / click handlers directly on each Avatar.'},
|
|
98
|
+
{guidance: true, description: 'Interactive avatars (href/onClick) share one Tab stop; arrows rove between them + the overflow button.'},
|
|
97
99
|
{guidance: false, description: "Don't nest AvatarGroups."},
|
|
98
100
|
],
|
|
99
101
|
},
|