@astryxdesign/core 0.4.7 → 0.5.0-canary.07f6c33
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 +161 -1
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +3 -2
- package/dist/AspectRatio/AspectRatio.d.ts +24 -0
- package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
- package/dist/AspectRatio/AspectRatio.js +23 -4
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +15 -10
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +3 -2
- package/dist/Banner/Banner.d.ts +40 -15
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +51 -18
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +17 -4
- package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetSwitcher.js +3 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +11 -10
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +5 -4
- package/dist/ButtonGroup/ButtonGroup.d.ts +5 -1
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +26 -7
- package/dist/Calendar/Calendar.d.ts +3 -1
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +13 -14
- package/dist/Calendar/getInitialFocusDate.d.ts +46 -0
- package/dist/Calendar/getInitialFocusDate.d.ts.map +1 -0
- package/dist/Calendar/getInitialFocusDate.js +62 -0
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +3 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +2 -3
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +3 -3
- package/dist/Chat/ChatMessageList.d.ts +22 -3
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +6 -3
- package/dist/Chat/ChatTokenizedText.d.ts +2 -0
- package/dist/Chat/ChatTokenizedText.d.ts.map +1 -1
- package/dist/Chat/ChatTokenizedText.js +11 -6
- package/dist/Chat/useChatComposerTokens.js +1 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +3 -2
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +3 -3
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +3 -2
- package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteItem.js +3 -2
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +4 -3
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +3 -2
- package/dist/DateInput/TouchDateField.d.ts.map +1 -1
- package/dist/DateInput/TouchDateField.js +38 -4
- package/dist/DateTimeInput/DateTimeInput.d.ts +21 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +406 -12
- package/dist/DateTimeInput/index.d.ts +1 -1
- package/dist/DateTimeInput/index.d.ts.map +1 -1
- package/dist/Dialog/Dialog.d.ts +7 -1
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +89 -58
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +6 -5
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +3 -2
- package/dist/Heading/Heading.d.ts.map +1 -1
- package/dist/Heading/Heading.js +6 -2
- package/dist/HoverCard/HoverCard.d.ts +6 -0
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.d.ts +5 -0
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +67 -25
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +4 -2
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +10 -3
- package/dist/Layer/LayerDepthContext.d.ts +52 -0
- package/dist/Layer/LayerDepthContext.d.ts.map +1 -0
- package/dist/Layer/LayerDepthContext.js +66 -0
- package/dist/Layer/index.d.ts +3 -0
- package/dist/Layer/index.d.ts.map +1 -1
- package/dist/Layer/index.js +4 -0
- package/dist/Layer/layerStack.d.ts +98 -0
- package/dist/Layer/layerStack.d.ts.map +1 -0
- package/dist/Layer/layerStack.js +306 -0
- package/dist/Layer/useLayerDismissal.d.ts +93 -0
- package/dist/Layer/useLayerDismissal.d.ts.map +1 -0
- package/dist/Layer/useLayerDismissal.js +91 -0
- package/dist/Lightbox/Lightbox.d.ts +1 -0
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +103 -81
- package/dist/Markdown/index.d.ts +1 -1
- package/dist/Markdown/index.d.ts.map +1 -1
- package/dist/Markdown/parser.d.ts +38 -1
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +177 -29
- package/dist/MobileNav/MobileNav.d.ts +6 -1
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +61 -36
- package/dist/MultiSelector/MultiSelector.d.ts +15 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +17 -6
- package/dist/MultiSelector/index.d.ts +1 -1
- package/dist/MultiSelector/index.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.js +3 -2
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +3 -2
- package/dist/OverflowList/OverflowList.d.ts.map +1 -1
- package/dist/OverflowList/OverflowList.js +3 -2
- package/dist/Overlay/Overlay.d.ts.map +1 -1
- package/dist/Overlay/Overlay.js +3 -2
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +20 -17
- package/dist/PowerSearch/PowerSearch.d.ts +8 -2
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +19 -6
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts +3 -1
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +28 -6
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts +3 -1
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +19 -9
- package/dist/PowerSearch/types.d.ts +2 -0
- package/dist/PowerSearch/types.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts +6 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchSource.js +14 -5
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +3 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +3 -2
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +3 -3
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +5 -0
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +4 -3
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +6 -5
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +4 -3
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +3 -3
- package/dist/Spinner/Spinner.d.ts +3 -3
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +130 -78
- package/dist/Stepper/Step.d.ts +140 -0
- package/dist/Stepper/Step.d.ts.map +1 -0
- package/dist/Stepper/Step.js +1045 -0
- package/dist/Stepper/StepStatus.d.ts +24 -0
- package/dist/Stepper/StepStatus.d.ts.map +1 -0
- package/dist/Stepper/StepStatus.js +1 -0
- package/dist/Stepper/Stepper.d.ts +93 -0
- package/dist/Stepper/Stepper.d.ts.map +1 -0
- package/dist/Stepper/Stepper.js +184 -0
- package/dist/Stepper/StepperContext.d.ts +41 -0
- package/dist/Stepper/StepperContext.d.ts.map +1 -0
- package/dist/Stepper/StepperContext.js +34 -0
- package/dist/Stepper/index.d.ts +8 -0
- package/dist/Stepper/index.d.ts.map +1 -0
- package/dist/Stepper/index.js +7 -0
- package/dist/Stepper/stepper.stylex.d.ts +15 -0
- package/dist/Stepper/stepper.stylex.d.ts.map +1 -0
- package/dist/Stepper/stepper.stylex.js +20 -0
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +3 -2
- package/dist/TabList/Tab.d.ts +15 -2
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +32 -7
- package/dist/TabList/TabList.d.ts +46 -7
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +353 -23
- package/dist/TabList/TabListContext.d.ts +11 -1
- package/dist/TabList/TabListContext.d.ts.map +1 -1
- package/dist/TabList/TabListContext.js +11 -2
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +3 -2
- package/dist/TabList/index.d.ts +2 -2
- package/dist/TabList/index.d.ts.map +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +4 -1
- package/dist/Table/TableRow.d.ts +16 -5
- package/dist/Table/TableRow.d.ts.map +1 -1
- package/dist/Table/TableRow.js +16 -5
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +20 -8
- package/dist/Table/plugins/pagination/useTablePagination.d.ts +3 -0
- package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +21 -4
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
- package/dist/Table/plugins/rowStatus/useTableRowStatus.js +10 -3
- package/dist/Table/plugins/selection/useTableSelection.d.ts +16 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +19 -5
- package/dist/Table/types.d.ts +22 -4
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +5 -0
- package/dist/Text/Text.d.ts.map +1 -1
- package/dist/Text/Text.js +6 -2
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +3 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +3 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +3 -2
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +5 -3
- package/dist/Token/TokenLink.d.ts.map +1 -1
- package/dist/Token/TokenLink.js +2 -2
- package/dist/Tokenizer/Tokenizer.d.ts +3 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +2 -0
- package/dist/Tooltip/Tooltip.d.ts +5 -0
- package/dist/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.d.ts +5 -0
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +39 -24
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +3 -2
- package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +3 -3
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +4 -3
- package/dist/Typeahead/BaseTypeahead.d.ts +2 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +68 -29
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +3 -2
- package/dist/astryx.css +68 -2
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useFocusTrap.d.ts +7 -4
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +60 -95
- package/dist/hooks/useHotkeys.d.ts.map +1 -1
- package/dist/hooks/useHotkeys.js +10 -3
- package/dist/hooks/useMergedRefs.d.ts +18 -0
- package/dist/hooks/useMergedRefs.d.ts.map +1 -0
- package/dist/hooks/useMergedRefs.js +25 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/utils/groupItems.d.ts +5 -1
- package/dist/utils/groupItems.d.ts.map +1 -1
- package/dist/utils/groupItems.js +9 -9
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/sharedResizeObserver.d.ts.map +1 -1
- package/dist/utils/sharedResizeObserver.js +10 -1
- package/dist/utils/timeParser.d.ts +1 -1
- package/dist/utils/timeParser.d.ts.map +1 -1
- package/dist/utils/timeParser.js +26 -12
- package/locales/en.json +31 -7
- package/locales/pseudo.json +18 -0
- package/package.json +8 -3
- package/src/AppShell/AppShell.tsx +3 -2
- package/src/AspectRatio/AspectRatio.doc.mjs +6 -3
- package/src/AspectRatio/AspectRatio.test.tsx +57 -10
- package/src/AspectRatio/AspectRatio.tsx +40 -1
- package/src/Avatar/Avatar.doc.mjs +2 -1
- package/src/Avatar/Avatar.test.tsx +17 -0
- package/src/Avatar/Avatar.tsx +61 -38
- package/src/AvatarGroup/AvatarGroup.tsx +3 -2
- package/src/Banner/Banner.doc.mjs +13 -11
- package/src/Banner/Banner.test.tsx +102 -15
- package/src/Banner/Banner.tsx +72 -25
- package/src/BottomSheet/BottomSheet.test.tsx +123 -0
- package/src/BottomSheet/BottomSheet.tsx +17 -4
- package/src/BottomSheet/BottomSheetSwitcher.tsx +3 -2
- package/src/Breadcrumbs/BreadcrumbItem.tsx +9 -5
- package/src/Button/Button.doc.mjs +22 -0
- package/src/Button/Button.test.tsx +13 -0
- package/src/Button/Button.tsx +5 -4
- package/src/ButtonGroup/ButtonGroup.doc.mjs +10 -1
- package/src/ButtonGroup/ButtonGroup.test.tsx +391 -1
- package/src/ButtonGroup/ButtonGroup.tsx +23 -5
- package/src/Calendar/Calendar.doc.mjs +4 -3
- package/src/Calendar/Calendar.test.tsx +52 -0
- package/src/Calendar/Calendar.tsx +18 -15
- package/src/Calendar/getInitialFocusDate.test.ts +94 -0
- package/src/Calendar/getInitialFocusDate.ts +93 -0
- package/src/Carousel/Carousel.tsx +3 -2
- package/src/Chat/ChatComposerInput.tsx +5 -1
- package/src/Chat/ChatLayout.tsx +3 -2
- package/src/Chat/ChatMessageList.doc.mjs +9 -1
- package/src/Chat/ChatMessageList.test.tsx +46 -0
- package/src/Chat/ChatMessageList.tsx +28 -4
- package/src/Chat/ChatTokenizedText.tsx +17 -10
- package/src/Chat/useChatComposerTokens.ts +1 -1
- package/src/CheckboxInput/CheckboxInput.tsx +3 -2
- package/src/ClickableCard/ClickableCard.tsx +3 -2
- package/src/CodeBlock/CodeBlock.doc.mjs +6 -0
- package/src/CommandPalette/CommandPaletteInput.tsx +3 -2
- package/src/CommandPalette/CommandPaletteItem.tsx +3 -2
- package/src/ContextMenu/ContextMenu.doc.mjs +5 -0
- package/src/ContextMenu/ContextMenu.tsx +4 -3
- package/src/DateInput/DateInput.tsx +3 -2
- package/src/DateInput/DateInputTouch.test.tsx +36 -0
- package/src/DateInput/TouchDateField.tsx +38 -4
- package/src/DateTimeInput/DateTimeInput.doc.mjs +18 -0
- package/src/DateTimeInput/DateTimeInput.test.tsx +1088 -0
- package/src/DateTimeInput/DateTimeInput.tsx +556 -24
- package/src/DateTimeInput/index.ts +1 -0
- package/src/Dialog/Dialog.doc.mjs +8 -3
- package/src/Dialog/Dialog.test.tsx +261 -1
- package/src/Dialog/Dialog.tsx +109 -58
- package/src/DropdownMenu/DropdownMenu.doc.mjs +6 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +8 -5
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +8 -11
- package/src/Field/Field.doc.mjs +13 -2
- package/src/FileInput/FileInput.tsx +3 -2
- package/src/Heading/Heading.test.tsx +23 -1
- package/src/Heading/Heading.tsx +6 -2
- package/src/HoverCard/HoverCard.doc.mjs +5 -0
- package/src/HoverCard/HoverCard.tsx +6 -0
- package/src/HoverCard/useHoverCard.tsx +81 -30
- package/src/Item/Item.tsx +5 -4
- package/src/Kbd/Kbd.test.tsx +17 -0
- package/src/Kbd/Kbd.tsx +10 -3
- package/src/Layer/LayerDepthContext.tsx +62 -0
- package/src/Layer/index.ts +9 -0
- package/src/Layer/layerDismissalFamilies.test.tsx +359 -0
- package/src/Layer/layerDismissalInvariants.test.tsx +417 -0
- package/src/Layer/layerStack.ts +362 -0
- package/src/Layer/useLayerDismissal.test.tsx +469 -0
- package/src/Layer/useLayerDismissal.ts +173 -0
- package/src/Layout/Layout.doc.mjs +2 -2
- package/src/Lightbox/Lightbox.doc.mjs +12 -0
- package/src/Lightbox/Lightbox.tsx +124 -102
- package/src/Link/Link.doc.mjs +39 -0
- package/src/Markdown/Markdown.doc.mjs +5 -0
- package/src/Markdown/incremental.test.ts +16 -2
- package/src/Markdown/index.ts +1 -0
- package/src/Markdown/parser.perf.test.ts +96 -1
- package/src/Markdown/parser.test.ts +145 -2
- package/src/Markdown/parser.ts +244 -29
- package/src/MobileNav/MobileNav.tsx +62 -36
- package/src/MoreMenu/MoreMenu.doc.mjs +7 -1
- package/src/MultiSelector/MultiSelector.doc.mjs +27 -0
- package/src/MultiSelector/MultiSelector.test.tsx +106 -0
- package/src/MultiSelector/MultiSelector.tsx +50 -6
- package/src/MultiSelector/index.ts +1 -0
- package/src/NavMenu/NavHeadingMenu.tsx +3 -2
- package/src/NumberInput/NumberInput.doc.mjs +5 -0
- package/src/Outline/Outline.tsx +3 -2
- package/src/OverflowList/OverflowList.tsx +3 -2
- package/src/Overlay/Overlay.tsx +3 -2
- package/src/Popover/usePopover.tsx +31 -28
- package/src/PowerSearch/PowerSearch.doc.mjs +160 -28
- package/src/PowerSearch/PowerSearch.test.tsx +240 -1
- package/src/PowerSearch/PowerSearch.tsx +34 -5
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +201 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +29 -2
- package/src/PowerSearch/PowerSearchValueEditor.test.tsx +47 -1
- package/src/PowerSearch/PowerSearchValueEditor.tsx +15 -0
- package/src/PowerSearch/types.ts +2 -0
- package/src/PowerSearch/usePowerSearchSource.test.ts +82 -2
- package/src/PowerSearch/usePowerSearchSource.ts +13 -3
- package/src/Resizable/ResizeHandle.tsx +3 -2
- package/src/SegmentedControl/SegmentedControl.tsx +3 -2
- package/src/SelectableCard/SelectableCard.tsx +3 -2
- package/src/Selector/Selector.doc.mjs +12 -1
- package/src/Selector/Selector.test.tsx +45 -1
- package/src/Selector/Selector.tsx +11 -1
- package/src/SideNav/SideNav.doc.mjs +6 -6
- package/src/SideNav/SideNav.tsx +4 -2
- package/src/SideNav/SideNavHeading.tsx +10 -10
- package/src/SideNav/SideNavItem.tsx +4 -2
- package/src/Slider/Slider.tsx +3 -2
- package/src/Spinner/Spinner.test.tsx +147 -1
- package/src/Spinner/Spinner.tsx +120 -101
- package/src/Stepper/Step.doc.mjs +98 -0
- package/src/Stepper/Step.tsx +1638 -0
- package/src/Stepper/StepStatus.ts +26 -0
- package/src/Stepper/Stepper.doc.mjs +370 -0
- package/src/Stepper/Stepper.test.tsx +1024 -0
- package/src/Stepper/Stepper.tsx +258 -0
- package/src/Stepper/StepperContext.ts +71 -0
- package/src/Stepper/index.ts +18 -0
- package/src/Stepper/stepper.stylex.ts +19 -0
- package/src/Switch/Switch.tsx +3 -2
- package/src/TabList/Tab.doc.mjs +13 -1
- package/src/TabList/Tab.tsx +67 -7
- package/src/TabList/TabList.doc.mjs +22 -6
- package/src/TabList/TabList.test.tsx +559 -0
- package/src/TabList/TabList.tsx +490 -22
- package/src/TabList/TabListContext.ts +13 -2
- package/src/TabList/TabMenu.tsx +3 -2
- package/src/TabList/index.ts +6 -2
- package/src/Table/BaseTable.tsx +6 -3
- package/src/Table/Table.doc.mjs +6 -1
- package/src/Table/Table.test.tsx +132 -14
- package/src/Table/TableBody.doc.mjs +40 -0
- package/src/Table/TableFooter.doc.mjs +40 -0
- package/src/Table/TableHeader.doc.mjs +40 -0
- package/src/Table/TableRow.tsx +16 -5
- package/src/Table/plugins/groupedRows/useTableGroupedRows-perf.test.tsx +112 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +100 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +17 -8
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +34 -4
- package/src/Table/plugins/pagination/useTablePagination.tsx +35 -3
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +9 -2
- package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +13 -7
- package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +12 -3
- package/src/Table/plugins/selection/useTableSelection.test.tsx +76 -0
- package/src/Table/plugins/selection/useTableSelection.tsx +40 -7
- package/src/Table/types.ts +22 -4
- package/src/Table/useBaseTablePlugins.ts +5 -0
- package/src/Table/useTableGroupedRows.doc.mjs +5 -4
- package/src/Table/useTablePagination.doc.mjs +7 -0
- package/src/Table/useTableRowStatus.doc.mjs +1 -1
- package/src/Table/useTableSelection.doc.mjs +31 -0
- package/src/Text/Text.test.tsx +23 -1
- package/src/Text/Text.tsx +6 -2
- package/src/TextArea/TextArea.tsx +3 -2
- package/src/TextInput/TextInput.doc.mjs +10 -0
- package/src/TextInput/TextInput.tsx +3 -2
- package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
- package/src/TimeInput/TimeInput.tsx +2 -2
- package/src/Timestamp/Timestamp.tsx +4 -2
- package/src/Toast/Toast.doc.mjs +6 -0
- package/src/Token/TokenLink.tsx +2 -2
- package/src/Tokenizer/Tokenizer.doc.mjs +27 -0
- package/src/Tokenizer/Tokenizer.tsx +4 -0
- package/src/Toolbar/Toolbar.doc.mjs +5 -0
- package/src/Tooltip/Tooltip.doc.mjs +5 -0
- package/src/Tooltip/Tooltip.test.tsx +32 -0
- package/src/Tooltip/Tooltip.tsx +5 -0
- package/src/Tooltip/useTooltip.tsx +47 -24
- package/src/TopNav/TopNavHeading.tsx +3 -2
- package/src/TopNav/TopNavMegaMenu.tsx +3 -2
- package/src/TopNav/TopNavMenu.tsx +4 -3
- package/src/Typeahead/BaseTypeahead.doc.mjs +11 -0
- package/src/Typeahead/BaseTypeahead.tsx +85 -33
- package/src/Typeahead/Typeahead.doc.mjs +5 -0
- package/src/Typeahead/Typeahead.test.tsx +49 -0
- package/src/Typeahead/Typeahead.tsx +3 -2
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useContainerReveal.doc.mjs +2 -2
- package/src/hooks/useFocusTrap.test.tsx +14 -0
- package/src/hooks/useFocusTrap.ts +62 -111
- package/src/hooks/useFocusTrapEscapeShim.test.tsx +165 -0
- package/src/hooks/useHotkeys.test.ts +18 -0
- package/src/hooks/useHotkeys.ts +10 -3
- package/src/hooks/useMergedRefs.doc.mjs +79 -0
- package/src/hooks/useMergedRefs.test.tsx +62 -0
- package/src/hooks/useMergedRefs.ts +36 -0
- package/src/index.ts +1 -0
- package/src/theme/MediaTheme.doc.mjs +5 -5
- package/src/utils/groupItems.ts +12 -6
- package/src/utils/index.ts +1 -1
- package/src/utils/sharedResizeObserver.ts +10 -2
- package/src/utils/timeParser.test.ts +6 -1
- package/src/utils/timeParser.ts +35 -13
- package/src/__tests__/inputWidthContract.test.tsx +0 -69
package/locales/pseudo.json
CHANGED
|
@@ -422,6 +422,9 @@
|
|
|
422
422
|
"@astryx.table.filter.apply": {
|
|
423
423
|
"defaultMessage": "⟦Àþþłý⟧"
|
|
424
424
|
},
|
|
425
|
+
"@astryx.table.rowStatus.columnHeader": {
|
|
426
|
+
"defaultMessage": "⟦Řóŵ šţàţúš⟧"
|
|
427
|
+
},
|
|
425
428
|
"@astryx.table.selection.selectAllRows": {
|
|
426
429
|
"defaultMessage": "⟦Šéłéçţ àłł řóŵš⟧"
|
|
427
430
|
},
|
|
@@ -560,6 +563,9 @@
|
|
|
560
563
|
"@astryx.dateTimeInput.timeSuffix": {
|
|
561
564
|
"defaultMessage": "⟦{label} ţíɱé⟧"
|
|
562
565
|
},
|
|
566
|
+
"@astryx.dateTimeInput.timeOptionsLabel": {
|
|
567
|
+
"defaultMessage": "⟦{label} óþţíóñš⟧"
|
|
568
|
+
},
|
|
563
569
|
"@astryx.dateRangeInput.placeholder": {
|
|
564
570
|
"defaultMessage": "⟦Šéłéçţ ðàţé řàñĝé⟧"
|
|
565
571
|
},
|
|
@@ -608,6 +614,12 @@
|
|
|
608
614
|
"@astryx.table.pagination.label": {
|
|
609
615
|
"defaultMessage": "⟦Ţàƀłé þàĝíñàţíóñ⟧"
|
|
610
616
|
},
|
|
617
|
+
"@astryx.table.pagination.labelAbove": {
|
|
618
|
+
"defaultMessage": "⟦{label} (ţóþ)⟧"
|
|
619
|
+
},
|
|
620
|
+
"@astryx.table.pagination.labelBelow": {
|
|
621
|
+
"defaultMessage": "⟦{label} (ƀóţţóɱ)⟧"
|
|
622
|
+
},
|
|
611
623
|
"@astryx.timeInput.placeholder": {
|
|
612
624
|
"defaultMessage": "⟦Šéłéçţ à ţíɱé⟧"
|
|
613
625
|
},
|
|
@@ -794,12 +806,18 @@
|
|
|
794
806
|
"@astryx.tableRowExpansion.expandRow": {
|
|
795
807
|
"defaultMessage": "⟦Éẋþàñð řóŵ⟧"
|
|
796
808
|
},
|
|
809
|
+
"@astryx.tableRowExpansion.columnHeader": {
|
|
810
|
+
"defaultMessage": "⟦Řóŵ éẋþàñšíóñ⟧"
|
|
811
|
+
},
|
|
797
812
|
"@astryx.tableRowExpansion.collapseAllRows": {
|
|
798
813
|
"defaultMessage": "⟦Çółłàþšé àłł řóŵš⟧"
|
|
799
814
|
},
|
|
800
815
|
"@astryx.tableRowExpansion.expandAllRows": {
|
|
801
816
|
"defaultMessage": "⟦Éẋþàñð àłł řóŵš⟧"
|
|
802
817
|
},
|
|
818
|
+
"@astryx.stepper.label": {
|
|
819
|
+
"defaultMessage": "⟦Þřóĝřéšš⟧"
|
|
820
|
+
},
|
|
803
821
|
"@astryx.step.goToStep": {
|
|
804
822
|
"defaultMessage": "⟦Ĝó ţó šţéþ {stepNumber, number}: {label}⟧"
|
|
805
823
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0-canary.07f6c33",
|
|
4
4
|
"displayName": "Astryx Core",
|
|
5
5
|
"description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -489,6 +489,11 @@
|
|
|
489
489
|
"types": "./dist/StatusDot/index.d.ts",
|
|
490
490
|
"default": "./dist/StatusDot/index.js"
|
|
491
491
|
},
|
|
492
|
+
"./Stepper": {
|
|
493
|
+
"source": "./src/Stepper/index.ts",
|
|
494
|
+
"types": "./dist/Stepper/index.d.ts",
|
|
495
|
+
"default": "./dist/Stepper/index.js"
|
|
496
|
+
},
|
|
492
497
|
"./Switch": {
|
|
493
498
|
"source": "./src/Switch/index.ts",
|
|
494
499
|
"types": "./dist/Switch/index.d.ts",
|
|
@@ -656,6 +661,7 @@
|
|
|
656
661
|
"react-dom": ">=19.0.0"
|
|
657
662
|
},
|
|
658
663
|
"devDependencies": {
|
|
664
|
+
"@astryxdesign/cli": "0.5.0-canary.07f6c33",
|
|
659
665
|
"@babel/cli": "^8.0.4",
|
|
660
666
|
"@babel/core": "^7.29.7",
|
|
661
667
|
"@babel/preset-react": "^8.0.1",
|
|
@@ -664,8 +670,7 @@
|
|
|
664
670
|
"@testing-library/dom": "^10.0.0",
|
|
665
671
|
"@testing-library/jest-dom": "^6.6.0",
|
|
666
672
|
"@testing-library/react": "^16.3.2",
|
|
667
|
-
"rimraf": "^6.0.1"
|
|
668
|
-
"@astryxdesign/cli": "0.4.7"
|
|
673
|
+
"rimraf": "^6.0.1"
|
|
669
674
|
},
|
|
670
675
|
"dependencies": {
|
|
671
676
|
"intl-messageformat": "^11.2.9"
|
|
@@ -50,7 +50,7 @@ import {AppShellMobileContext} from './AppShellMobileContext';
|
|
|
50
50
|
import type {AppShellMobileContextValue} from './AppShellMobileContext';
|
|
51
51
|
import type {SpacingStep} from '../utils/types';
|
|
52
52
|
import type {BaseProps} from '../BaseProps';
|
|
53
|
-
import {mergeProps,
|
|
53
|
+
import {mergeProps, isRenderable} from '../utils';
|
|
54
54
|
import {focusOutlineProps} from '../utils/focusOutline.stylex';
|
|
55
55
|
import {useMediaQuery} from '../hooks/useMediaQuery';
|
|
56
56
|
import {observeResize, unobserveResize} from '../utils/sharedResizeObserver';
|
|
@@ -58,6 +58,7 @@ import {themeProps} from '../utils/themeProps';
|
|
|
58
58
|
import {useTranslator} from '../i18n';
|
|
59
59
|
import type {AppShellVariantMap} from './index';
|
|
60
60
|
|
|
61
|
+
import {useMergedRefs} from '../hooks/useMergedRefs';
|
|
61
62
|
const HasActivity = typeof React.Activity !== 'undefined';
|
|
62
63
|
const ActivityWrapper = HasActivity
|
|
63
64
|
? ({
|
|
@@ -792,7 +793,7 @@ export function AppShell({
|
|
|
792
793
|
<AppShellMobileContext value={mobileContextValue}>
|
|
793
794
|
<div
|
|
794
795
|
{...rest}
|
|
795
|
-
ref={
|
|
796
|
+
ref={useMergedRefs(ref, shellRef)}
|
|
796
797
|
data-testid={dataTestId}
|
|
797
798
|
{...mergeProps(
|
|
798
799
|
themeProps('app-shell', {variant}),
|
|
@@ -16,6 +16,7 @@ export const docs = {
|
|
|
16
16
|
{guidance: true, description: 'Use `fit="cover"` for images and video so the component sizes the child; the child should not repeat `width`/`height`/`objectFit` styles.'},
|
|
17
17
|
{guidance: true, description: 'Pass one child. With `fit` set, every direct child is stretched to fill the box, so put an overlay or caption inside a single wrapper child rather than passing it as a second child.'},
|
|
18
18
|
{guidance: true, description: 'Describe media children with `alt`, or `alt=""` when the image is decorative. AspectRatio adds no role and no accessible name of its own, so the child carries the whole accessible description.'},
|
|
19
|
+
{guidance: true, description: 'For a breakpoint-dependent ratio, override the ratio responsively: pass an `aspectRatio` rule via `xstyle` (StyleX), or override `aspect-ratio` from your own unlayered CSS under a `@media`/`@container` rule — component styles live in the `astryx-base` cascade layer, so unlayered consumer CSS wins. Give an `xstyle` rule a `default` branch alongside the conditional one (`{default: 3, \'@container ...\': \'3 / 2\'}`) — with only the conditional branch the ratio is unset outside the query and the box collapses.'},
|
|
19
20
|
{guidance: false, description: 'Use for general layout containers; use standard layout components instead.'},
|
|
20
21
|
{guidance: false, description: 'Nest AspectRatio containers; one level is sufficient.'},
|
|
21
22
|
{guidance: false, description: 'Constrain the height on its own. The width comes from the container, so a `height` or `maxHeight` by itself clamps the box off ratio; pair it with `width: "auto"` to size from the height instead.'},
|
|
@@ -30,7 +31,7 @@ export const docs = {
|
|
|
30
31
|
{
|
|
31
32
|
name: 'ratio',
|
|
32
33
|
type: 'number',
|
|
33
|
-
description: 'Aspect ratio as width/height (e.g. 16/9, 1).',
|
|
34
|
+
description: 'Aspect ratio as width/height (e.g. 16/9, 1). Emitted as a class-level declaration (never inline), so `xstyle` rules or unlayered consumer CSS can override it responsively.',
|
|
34
35
|
required: true,
|
|
35
36
|
},
|
|
36
37
|
{
|
|
@@ -83,6 +84,7 @@ export const docsZh = {
|
|
|
83
84
|
{guidance: true, description: 'Use `fit="cover"` for images and video so the component sizes the child; the child should not repeat `width`/`height`/`objectFit` styles.'},
|
|
84
85
|
{guidance: true, description: 'Pass one child. With `fit` set, every direct child is stretched to fill the box, so put an overlay or caption inside a single wrapper child rather than passing it as a second child.'},
|
|
85
86
|
{guidance: true, description: 'Describe media children with `alt`, or `alt=""` when the image is decorative. AspectRatio adds no role and no accessible name of its own, so the child carries the whole accessible description.'},
|
|
87
|
+
{guidance: true, description: 'For a breakpoint-dependent ratio, override the ratio responsively: pass an `aspectRatio` rule via `xstyle` (StyleX), or override `aspect-ratio` from your own unlayered CSS under a `@media`/`@container` rule — component styles live in the `astryx-base` cascade layer, so unlayered consumer CSS wins. Give an `xstyle` rule a `default` branch alongside the conditional one (`{default: 3, \'@container ...\': \'3 / 2\'}`) — with only the conditional branch the ratio is unset outside the query and the box collapses.'},
|
|
86
88
|
{guidance: false, description: 'Use for general layout containers; use standard layout components instead.'},
|
|
87
89
|
{guidance: false, description: 'Nest AspectRatio containers; one level is sufficient.'},
|
|
88
90
|
{guidance: false, description: 'Constrain the height on its own. The width comes from the container, so a `height` or `maxHeight` by itself clamps the box off ratio; pair it with `width: "auto"` to size from the height instead.'},
|
|
@@ -94,7 +96,7 @@ export const docsZh = {
|
|
|
94
96
|
],
|
|
95
97
|
},
|
|
96
98
|
props: [
|
|
97
|
-
{name: 'ratio', type: 'number', description: '宽高比,以宽/高表示(例如 16/9、1
|
|
99
|
+
{name: 'ratio', type: 'number', description: '宽高比,以宽/高表示(例如 16/9、1)。以类级声明输出(非内联样式),可通过 `xstyle` 规则或未分层的(unlayered)消费者 CSS 做响应式覆盖。', required: true},
|
|
98
100
|
{
|
|
99
101
|
name: 'shape',
|
|
100
102
|
type: "'rectangle' | 'ellipse'",
|
|
@@ -133,6 +135,7 @@ export const docsDense = {
|
|
|
133
135
|
{guidance: true, description: 'Use `fit="cover"` for images and video so the component sizes the child; the child should not repeat `width`/`height`/`objectFit` styles.'},
|
|
134
136
|
{guidance: true, description: 'Pass one child. With `fit` set, every direct child is stretched to fill the box, so put an overlay or caption inside a single wrapper child rather than passing it as a second child.'},
|
|
135
137
|
{guidance: true, description: 'Describe media children with `alt`, or `alt=""` when the image is decorative. AspectRatio adds no role and no accessible name of its own, so the child carries the whole accessible description.'},
|
|
138
|
+
{guidance: true, description: 'For a breakpoint-dependent ratio, override the ratio responsively: pass an `aspectRatio` rule via `xstyle` (StyleX), or override `aspect-ratio` from your own unlayered CSS under a `@media`/`@container` rule — component styles live in the `astryx-base` cascade layer, so unlayered consumer CSS wins. Give an `xstyle` rule a `default` branch alongside the conditional one (`{default: 3, \'@container ...\': \'3 / 2\'}`) — with only the conditional branch the ratio is unset outside the query and the box collapses.'},
|
|
136
139
|
{guidance: false, description: 'Use for general layout containers; use standard layout components instead.'},
|
|
137
140
|
{guidance: false, description: 'Nest AspectRatio containers; one level is sufficient.'},
|
|
138
141
|
{guidance: false, description: 'Constrain the height on its own. The width comes from the container, so a `height` or `maxHeight` by itself clamps the box off ratio; pair it with `width: "auto"` to size from the height instead.'},
|
|
@@ -144,7 +147,7 @@ export const docsDense = {
|
|
|
144
147
|
],
|
|
145
148
|
},
|
|
146
149
|
propDescriptions: {
|
|
147
|
-
ratio: 'width/height ratio (e.g. 16/9, 1)',
|
|
150
|
+
ratio: 'width/height ratio (e.g. 16/9, 1); class-level declaration (never inline) so xstyle/unlayered-CSS @container overrides win',
|
|
148
151
|
shape: "container shape: 'rectangle' (default) | 'ellipse' (circle at ratio 1)",
|
|
149
152
|
fit: "child layout: 'cover' fill+crop | 'contain' fill+letterbox | 'center' natural size; omitted = child styles itself",
|
|
150
153
|
children: 'content positioned absolutely to fill container',
|
|
@@ -13,6 +13,20 @@ import {describe, it, expect, vi, beforeAll} from 'vitest';
|
|
|
13
13
|
import {render, screen} from '@testing-library/react';
|
|
14
14
|
import {AspectRatio} from './AspectRatio';
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* The ratio compiles to a class-level `aspect-ratio: var(--x-aspectRatio)`
|
|
18
|
+
* declaration with the value carried by a CSS variable (so xstyle/@media
|
|
19
|
+
* and unlayered consumer CSS overrides can win). `--x-aspectRatio` is the
|
|
20
|
+
* debug-mode variable name emitted for the `aspectRatio` property.
|
|
21
|
+
*/
|
|
22
|
+
function ratioVar(el: HTMLElement): string {
|
|
23
|
+
return el.style.getPropertyValue('--x-aspectRatio');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function ratioValue(ratio: number): string {
|
|
27
|
+
return String(ratio);
|
|
28
|
+
}
|
|
29
|
+
|
|
16
30
|
describe('AspectRatio', () => {
|
|
17
31
|
it('renders with correct aspect ratio', () => {
|
|
18
32
|
render(
|
|
@@ -22,7 +36,7 @@ describe('AspectRatio', () => {
|
|
|
22
36
|
);
|
|
23
37
|
const element = screen.getByTestId('aspect-ratio');
|
|
24
38
|
expect(element).toBeInTheDocument();
|
|
25
|
-
expect(element
|
|
39
|
+
expect(ratioVar(element)).toBe(ratioValue(16 / 9));
|
|
26
40
|
});
|
|
27
41
|
|
|
28
42
|
it('children fill the container', () => {
|
|
@@ -47,7 +61,7 @@ describe('AspectRatio', () => {
|
|
|
47
61
|
</AspectRatio>,
|
|
48
62
|
);
|
|
49
63
|
const element = screen.getByTestId('aspect-ratio');
|
|
50
|
-
expect(element
|
|
64
|
+
expect(ratioVar(element)).toBe(ratioValue(ratio));
|
|
51
65
|
});
|
|
52
66
|
|
|
53
67
|
it('renders with 4:3 ratio', () => {
|
|
@@ -58,7 +72,7 @@ describe('AspectRatio', () => {
|
|
|
58
72
|
</AspectRatio>,
|
|
59
73
|
);
|
|
60
74
|
const element = screen.getByTestId('aspect-ratio');
|
|
61
|
-
expect(element
|
|
75
|
+
expect(ratioVar(element)).toBe(ratioValue(ratio));
|
|
62
76
|
});
|
|
63
77
|
|
|
64
78
|
it('renders with 1:1 square ratio', () => {
|
|
@@ -68,7 +82,7 @@ describe('AspectRatio', () => {
|
|
|
68
82
|
</AspectRatio>,
|
|
69
83
|
);
|
|
70
84
|
const element = screen.getByTestId('aspect-ratio');
|
|
71
|
-
expect(element
|
|
85
|
+
expect(ratioVar(element)).toBe(ratioValue(1));
|
|
72
86
|
});
|
|
73
87
|
|
|
74
88
|
it('renders with 21:9 ultrawide ratio', () => {
|
|
@@ -79,7 +93,7 @@ describe('AspectRatio', () => {
|
|
|
79
93
|
</AspectRatio>,
|
|
80
94
|
);
|
|
81
95
|
const element = screen.getByTestId('aspect-ratio');
|
|
82
|
-
expect(element
|
|
96
|
+
expect(ratioVar(element)).toBe(ratioValue(ratio));
|
|
83
97
|
});
|
|
84
98
|
|
|
85
99
|
it('renders an ellipse that respects the ratio (circle at 1:1)', () => {
|
|
@@ -89,7 +103,7 @@ describe('AspectRatio', () => {
|
|
|
89
103
|
</AspectRatio>,
|
|
90
104
|
);
|
|
91
105
|
const element = screen.getByTestId('aspect-ratio');
|
|
92
|
-
expect(element
|
|
106
|
+
expect(ratioVar(element)).toBe(ratioValue(1));
|
|
93
107
|
expect(element.className).toContain('ellipse');
|
|
94
108
|
});
|
|
95
109
|
|
|
@@ -101,7 +115,7 @@ describe('AspectRatio', () => {
|
|
|
101
115
|
);
|
|
102
116
|
const element = screen.getByTestId('aspect-ratio');
|
|
103
117
|
// Ratio is preserved — the ellipse does not force 1:1.
|
|
104
|
-
expect(element
|
|
118
|
+
expect(ratioVar(element)).toBe(ratioValue(16 / 9));
|
|
105
119
|
expect(element.className).toContain('ellipse');
|
|
106
120
|
});
|
|
107
121
|
|
|
@@ -112,7 +126,7 @@ describe('AspectRatio', () => {
|
|
|
112
126
|
</AspectRatio>,
|
|
113
127
|
);
|
|
114
128
|
const element = screen.getByTestId('aspect-ratio');
|
|
115
|
-
expect(element
|
|
129
|
+
expect(ratioVar(element)).toBe(ratioValue(1));
|
|
116
130
|
expect(element.className).toContain('rectangle');
|
|
117
131
|
// No ellipse border-radius when shape is the default rectangle
|
|
118
132
|
expect(element.style.borderRadius).toBe('');
|
|
@@ -177,6 +191,38 @@ describe('AspectRatio', () => {
|
|
|
177
191
|
expect(video).toBeInTheDocument();
|
|
178
192
|
});
|
|
179
193
|
|
|
194
|
+
describe('responsive ratio', () => {
|
|
195
|
+
it('emits the ratio as a class-level declaration, not an inline style', () => {
|
|
196
|
+
render(
|
|
197
|
+
<AspectRatio ratio={3 / 1} data-testid="aspect-ratio">
|
|
198
|
+
<div>Hero</div>
|
|
199
|
+
</AspectRatio>,
|
|
200
|
+
);
|
|
201
|
+
const element = screen.getByTestId('aspect-ratio');
|
|
202
|
+
// No inline aspect-ratio — the declaration lives in a class reading a
|
|
203
|
+
// CSS variable, so @media/@container rules (via xstyle, or via
|
|
204
|
+
// unlayered consumer CSS beating the astryx-base layer) can override
|
|
205
|
+
// it.
|
|
206
|
+
expect(element.style.aspectRatio).toBe('');
|
|
207
|
+
expect(ratioVar(element)).toBe(ratioValue(3 / 1));
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('lets a consumer inline style win over the class-level ratio', () => {
|
|
211
|
+
render(
|
|
212
|
+
<AspectRatio
|
|
213
|
+
ratio={3 / 1}
|
|
214
|
+
style={{aspectRatio: '3 / 2'}}
|
|
215
|
+
data-testid="aspect-ratio">
|
|
216
|
+
<div>Hero</div>
|
|
217
|
+
</AspectRatio>,
|
|
218
|
+
);
|
|
219
|
+
const element = screen.getByTestId('aspect-ratio');
|
|
220
|
+
// The consumer's style prop passes through untouched (it is no longer
|
|
221
|
+
// merged with a component-owned inline aspect-ratio).
|
|
222
|
+
expect(element.style.aspectRatio).toBe('3 / 2');
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
|
|
180
226
|
describe('fit', () => {
|
|
181
227
|
it('marks the child\'s direct parent with data-astryx-aspect-ratio-override for fit="cover"', () => {
|
|
182
228
|
render(
|
|
@@ -277,7 +323,7 @@ describe('AspectRatio', () => {
|
|
|
277
323
|
});
|
|
278
324
|
|
|
279
325
|
describe('style merging', () => {
|
|
280
|
-
it('keeps the consumer style and
|
|
326
|
+
it('keeps the consumer style and lets an inline ratio win', () => {
|
|
281
327
|
render(
|
|
282
328
|
<AspectRatio
|
|
283
329
|
ratio={16 / 9}
|
|
@@ -288,7 +334,8 @@ describe('AspectRatio', () => {
|
|
|
288
334
|
);
|
|
289
335
|
const element = screen.getByTestId('aspect-ratio');
|
|
290
336
|
expect(element.style.opacity).toBe('0.5');
|
|
291
|
-
expect(element.style.aspectRatio).toBe(
|
|
337
|
+
expect(element.style.aspectRatio).toBe('3 / 1');
|
|
338
|
+
expect(ratioVar(element)).toBe(ratioValue(16 / 9));
|
|
292
339
|
});
|
|
293
340
|
|
|
294
341
|
it('keeps a consumer className beside the theme target', () => {
|
|
@@ -43,6 +43,25 @@ export interface AspectRatioProps extends BaseProps<HTMLDivElement> {
|
|
|
43
43
|
ref?: React.Ref<HTMLDivElement>;
|
|
44
44
|
/**
|
|
45
45
|
* The aspect ratio as width/height (e.g., 16/9 = 1.777..., 4/3 = 1.333..., 1 for square).
|
|
46
|
+
*
|
|
47
|
+
* The ratio is emitted as a class-level declaration — never an inline
|
|
48
|
+
* style — so it can be made responsive:
|
|
49
|
+
* - StyleX consumers pass an `aspect-ratio` rule via `xstyle`, including
|
|
50
|
+
* under `@media`/`@container` conditions.
|
|
51
|
+
* - Plain-CSS/Tailwind consumers override `aspect-ratio` from their own
|
|
52
|
+
* (unlayered) rules: the compiled component styles live in the
|
|
53
|
+
* `astryx-base` cascade layer, and unlayered CSS wins over layered
|
|
54
|
+
* rules regardless of specificity.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```
|
|
58
|
+
* // 3:1 hero that becomes 3:2 when its container stacks
|
|
59
|
+
* <AspectRatio ratio={3 / 1} className="gallery-hero">…</AspectRatio>
|
|
60
|
+
*
|
|
61
|
+
* // CSS: @container gallery (max-width: 720px) {
|
|
62
|
+
* // .gallery-hero { aspect-ratio: 3 / 2; }
|
|
63
|
+
* // }
|
|
64
|
+
* ```
|
|
46
65
|
*/
|
|
47
66
|
ratio: number;
|
|
48
67
|
|
|
@@ -132,6 +151,20 @@ const styles = stylex.create({
|
|
|
132
151
|
},
|
|
133
152
|
});
|
|
134
153
|
|
|
154
|
+
// The ratio compiles to a CSS variable + a class-level declaration
|
|
155
|
+
// (aspect-ratio: var(--x)) instead of a raw inline style, so consumer
|
|
156
|
+
// overrides — `xstyle` rules, including ones inside @media/@container
|
|
157
|
+
// queries — can still win. A raw inline `aspect-ratio` would beat any class
|
|
158
|
+
// (same rationale as Grid's dynamic track values). Non-StyleX consumers
|
|
159
|
+
// don't need a dedicated hook: the compiled declaration sits in the
|
|
160
|
+
// `astryx-base` cascade layer, so any unlayered consumer rule wins
|
|
161
|
+
// regardless of specificity.
|
|
162
|
+
const dynamicStyles = stylex.create({
|
|
163
|
+
ratio: (ratio: number) => ({
|
|
164
|
+
aspectRatio: ratio,
|
|
165
|
+
}),
|
|
166
|
+
});
|
|
167
|
+
|
|
135
168
|
/**
|
|
136
169
|
* AspectRatio component for maintaining a specific aspect ratio for its children.
|
|
137
170
|
*
|
|
@@ -147,6 +180,11 @@ const styles = stylex.create({
|
|
|
147
180
|
* `ratio={1}` or an oval at other ratios. Both shapes respect the provided
|
|
148
181
|
* `ratio`.
|
|
149
182
|
*
|
|
183
|
+
* The ratio is a class-level declaration (not an inline style), so it can be
|
|
184
|
+
* overridden responsively — via `xstyle` for StyleX consumers, or with a
|
|
185
|
+
* plain unlayered `aspect-ratio` rule for plain-CSS consumers (component
|
|
186
|
+
* styles live in the `astryx-base` cascade layer, which unlayered CSS beats).
|
|
187
|
+
*
|
|
150
188
|
* Sizing: the box takes its width from its container and derives its height
|
|
151
189
|
* from the ratio, so it needs an ancestor with a definite width. Two
|
|
152
190
|
* consequences are worth knowing. Constraining only the height (`height` or
|
|
@@ -188,11 +226,12 @@ export function AspectRatio({
|
|
|
188
226
|
themeProps('aspect-ratio', {shape}),
|
|
189
227
|
stylex.props(
|
|
190
228
|
styles.container,
|
|
229
|
+
dynamicStyles.ratio(ratio),
|
|
191
230
|
shape === 'ellipse' && styles.ellipse,
|
|
192
231
|
xstyle,
|
|
193
232
|
),
|
|
194
233
|
className,
|
|
195
|
-
|
|
234
|
+
style,
|
|
196
235
|
)}
|
|
197
236
|
{...props}>
|
|
198
237
|
{/* The marker attribute carries the fit value so the reset.css child
|
|
@@ -148,7 +148,8 @@ export const docsDense = {
|
|
|
148
148
|
{guidance: true, description: 'Match size to context: xsm/sm inline, md/lg in lists, xl for profiles.'},
|
|
149
149
|
{guidance: true, description: 'Add a status dot in chat or team views where availability matters.'},
|
|
150
150
|
{guidance: true, description: 'When wrapping Avatar in your own Tooltip or HoverCard, set tooltip={false} so the built-in name tooltip does not overlap yours.'},
|
|
151
|
-
{guidance: true, description: 'Interactive avatars (href/onClick) need name or alt; without one they warn in development.
|
|
151
|
+
{guidance: true, description: 'Interactive avatars (href/onClick) need name or alt; without one they warn in development.'},
|
|
152
|
+
{guidance: false, description: 'Rely on a status label to name an interactive avatar. "Online" says nothing about where the link goes.'},
|
|
152
153
|
{guidance: false, description: 'Use for logos or product images. Use an image or icon instead.'},
|
|
153
154
|
{guidance: false, description: 'Force a square or custom shape. Avatars are always circular.'},
|
|
154
155
|
],
|
|
@@ -569,6 +569,23 @@ describe('Avatar', () => {
|
|
|
569
569
|
render(<Avatar name="Ada Lovelace" ref={ref} data-testid="a" />);
|
|
570
570
|
expect(ref.current).toBe(screen.getByTestId('a'));
|
|
571
571
|
});
|
|
572
|
+
|
|
573
|
+
it('keeps its merged ref attached across unrelated rerenders', () => {
|
|
574
|
+
const ref = vi.fn();
|
|
575
|
+
const {rerender} = render(
|
|
576
|
+
<Avatar name="Ada Lovelace" size="sm" tooltip={false} ref={ref} />,
|
|
577
|
+
);
|
|
578
|
+
const avatar = screen.getByRole('img', {name: 'Ada Lovelace'});
|
|
579
|
+
expect(ref).toHaveBeenLastCalledWith(avatar);
|
|
580
|
+
ref.mockClear();
|
|
581
|
+
|
|
582
|
+
rerender(
|
|
583
|
+
<Avatar name="Ada Lovelace" size="lg" tooltip={false} ref={ref} />,
|
|
584
|
+
);
|
|
585
|
+
|
|
586
|
+
expect(ref).not.toHaveBeenCalled();
|
|
587
|
+
expect(screen.getByRole('img', {name: 'Ada Lovelace'})).toBe(avatar);
|
|
588
|
+
});
|
|
572
589
|
});
|
|
573
590
|
});
|
|
574
591
|
|
package/src/Avatar/Avatar.tsx
CHANGED
|
@@ -19,7 +19,14 @@
|
|
|
19
19
|
* Last synced props: alt, fallbackSrc, name, size, src, status, href, as, target, rel, onClick
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
isValidElement,
|
|
24
|
+
useCallback,
|
|
25
|
+
useMemo,
|
|
26
|
+
useRef,
|
|
27
|
+
useState,
|
|
28
|
+
type ReactNode,
|
|
29
|
+
} from 'react';
|
|
23
30
|
import type {BaseProps} from '../BaseProps';
|
|
24
31
|
import * as stylex from '@stylexjs/stylex';
|
|
25
32
|
import {
|
|
@@ -34,7 +41,8 @@ import {
|
|
|
34
41
|
type AvatarStatusLabelTarget,
|
|
35
42
|
} from './AvatarStatusLabelContext';
|
|
36
43
|
import {useAvatarGroup} from '../AvatarGroup/AvatarGroupContext';
|
|
37
|
-
import {mergeProps
|
|
44
|
+
import {mergeProps} from '../utils';
|
|
45
|
+
import {useMergedRefs} from '../hooks/useMergedRefs';
|
|
38
46
|
import {themeProps} from '../utils/themeProps';
|
|
39
47
|
import {firstCharacter} from '../utils/characters';
|
|
40
48
|
import {focusOutlineProps} from '../utils/focusOutline.stylex';
|
|
@@ -608,47 +616,62 @@ export function Avatar({
|
|
|
608
616
|
label: undefined,
|
|
609
617
|
update: null,
|
|
610
618
|
});
|
|
611
|
-
|
|
612
|
-
|
|
619
|
+
const {
|
|
620
|
+
'aria-hidden': consumerAriaHidden,
|
|
621
|
+
'aria-label': consumerAriaLabel,
|
|
622
|
+
role: consumerRole,
|
|
623
|
+
} = props;
|
|
624
|
+
// Recompose the name after React has written any relevant prop changes.
|
|
613
625
|
// `update` covers the other direction: a label that changes while the avatar
|
|
614
626
|
// itself does not re-render.
|
|
615
|
-
const nameRef = (
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
const target = statusLabelRef.current;
|
|
620
|
-
target.update = () => {
|
|
621
|
-
const composed = composeAccessibleName(
|
|
622
|
-
t,
|
|
623
|
-
nameLabel,
|
|
624
|
-
meaningful(target.label) ?? getStatusLabel(status),
|
|
625
|
-
);
|
|
626
|
-
// A consumer's own ARIA wins here exactly as it does in render, where
|
|
627
|
-
// the derived props spread before `{...props}`.
|
|
628
|
-
if (props['aria-label'] == null) {
|
|
629
|
-
setAttributeOrRemove(element, 'aria-label', composed);
|
|
627
|
+
const nameRef = useCallback(
|
|
628
|
+
(element: HTMLElement | null) => {
|
|
629
|
+
if (element == null) {
|
|
630
|
+
return;
|
|
630
631
|
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
632
|
+
const target = statusLabelRef.current;
|
|
633
|
+
target.update = () => {
|
|
634
|
+
const composed = composeAccessibleName(
|
|
635
|
+
t,
|
|
636
|
+
nameLabel,
|
|
637
|
+
meaningful(target.label) ?? getStatusLabel(status),
|
|
638
|
+
);
|
|
639
|
+
// A consumer's own ARIA wins here exactly as it does in render, where
|
|
640
|
+
// the derived props spread before `{...props}`.
|
|
641
|
+
if (consumerAriaLabel == null) {
|
|
642
|
+
setAttributeOrRemove(element, 'aria-label', composed);
|
|
636
643
|
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
composed ?
|
|
642
|
-
|
|
644
|
+
// An `<a>`/`<button>` root carries its own role and must not be hidden,
|
|
645
|
+
// so only the name transfers there.
|
|
646
|
+
if (!isInteractive) {
|
|
647
|
+
if (consumerRole == null) {
|
|
648
|
+
element.setAttribute('role', composed ? 'img' : 'presentation');
|
|
649
|
+
}
|
|
650
|
+
if (consumerAriaHidden == null) {
|
|
651
|
+
setAttributeOrRemove(
|
|
652
|
+
element,
|
|
653
|
+
'aria-hidden',
|
|
654
|
+
composed ? undefined : 'true',
|
|
655
|
+
);
|
|
656
|
+
}
|
|
643
657
|
}
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
|
|
658
|
+
};
|
|
659
|
+
target.update();
|
|
660
|
+
return () => {
|
|
661
|
+
target.update = null;
|
|
662
|
+
};
|
|
663
|
+
},
|
|
664
|
+
[
|
|
665
|
+
consumerAriaHidden,
|
|
666
|
+
consumerAriaLabel,
|
|
667
|
+
consumerRole,
|
|
668
|
+
isInteractive,
|
|
669
|
+
nameLabel,
|
|
670
|
+
status,
|
|
671
|
+
t,
|
|
672
|
+
],
|
|
673
|
+
);
|
|
674
|
+
const rootRef = useMergedRefs(
|
|
652
675
|
ref,
|
|
653
676
|
showTooltip ? tooltipHook.ref : undefined,
|
|
654
677
|
nameRef,
|
|
@@ -28,7 +28,7 @@ import {useId, useMemo, useState, type ReactNode} from 'react';
|
|
|
28
28
|
import type {BaseProps} from '../BaseProps';
|
|
29
29
|
import {resolveSize, type AvatarSize} from '../Avatar';
|
|
30
30
|
import * as stylex from '@stylexjs/stylex';
|
|
31
|
-
import {mergeProps
|
|
31
|
+
import {mergeProps} from '../utils';
|
|
32
32
|
import {composeEventHandlers} from '../utils/composeEventHandlers';
|
|
33
33
|
import {AvatarGroupContext} from './AvatarGroupContext';
|
|
34
34
|
import {themeProps} from '../utils/themeProps';
|
|
@@ -37,6 +37,7 @@ import {useListFocus} from '../hooks/useListFocus';
|
|
|
37
37
|
import {useIsomorphicLayoutEffect} from '../hooks/useIsomorphicLayoutEffect';
|
|
38
38
|
import {VisuallyHidden} from '../VisuallyHidden';
|
|
39
39
|
|
|
40
|
+
import {useMergedRefs} from '../hooks/useMergedRefs';
|
|
40
41
|
const OVERLAP_RATIO = 0.25;
|
|
41
42
|
|
|
42
43
|
export interface AvatarGroupProps extends BaseProps<HTMLDivElement> {
|
|
@@ -143,7 +144,7 @@ export function AvatarGroup({
|
|
|
143
144
|
<AvatarGroupContext value={contextValue}>
|
|
144
145
|
<div
|
|
145
146
|
{...props}
|
|
146
|
-
ref={
|
|
147
|
+
ref={useMergedRefs(ref, listRef)}
|
|
147
148
|
role="group"
|
|
148
149
|
aria-label={ariaLabel}
|
|
149
150
|
aria-describedby={describedBy}
|
|
@@ -17,6 +17,7 @@ export const docs = {
|
|
|
17
17
|
{guidance: true, description: 'Keep titles short and scannable: "Payment failed" not "There was a problem processing your most recent payment."'},
|
|
18
18
|
{guidance: false, description: 'Use Banner for short-lived messages that disappear on their own; use Toast instead.'},
|
|
19
19
|
{guidance: false, description: 'Stack multiple banners with the same status; combine related messages into one banner.'},
|
|
20
|
+
{guidance: true, description: 'Set collapsible={false} when the user needs the content to act on the message, like the list of fields that failed validation. Keep the default toggle when the detail is long enough to bury the banner\u2019s own message.'},
|
|
20
21
|
{guidance: true, description: 'Error and warning banners render as role="alert"; info and success render as role="status". Mount an alert banner in response to an event rather than on first paint, so assistive tech has a change to report.'},
|
|
21
22
|
{guidance: false, description: 'Rely on the status color or icon alone to carry meaning; say which status it is in the title text, because the icon is decorative to a screen reader.'},
|
|
22
23
|
],
|
|
@@ -26,7 +27,7 @@ export const docs = {
|
|
|
26
27
|
{name: 'Description', required: false, description: 'Additional detail below the title.'},
|
|
27
28
|
{name: 'Action button', required: false, description: 'A button for the user to act on the message, like "Review" or "Retry".'},
|
|
28
29
|
{name: 'Dismiss button', required: false, description: 'Lets the user close the banner. Enabled by setting isDismissable.'},
|
|
29
|
-
{name: '
|
|
30
|
+
{name: 'Content', required: false, description: 'Extra detail below the banner header, like a list of errors. Sits behind an expand/collapse toggle by default; set collapsible={false} to keep it visible.'},
|
|
30
31
|
],
|
|
31
32
|
},
|
|
32
33
|
|
|
@@ -94,14 +95,14 @@ export const docs = {
|
|
|
94
95
|
name: 'children',
|
|
95
96
|
type: 'ReactNode',
|
|
96
97
|
description:
|
|
97
|
-
'Content rendered in the card-background area below the colored header.',
|
|
98
|
+
'Content rendered in the card-background area below the colored header. Sits behind an expand/collapse toggle unless `collapsible={false}`.',
|
|
98
99
|
},
|
|
99
100
|
{
|
|
100
|
-
name: '
|
|
101
|
-
type: 'boolean',
|
|
101
|
+
name: 'collapsible',
|
|
102
|
+
type: 'boolean | {defaultIsOpen?: boolean; isOpen?: boolean; onOpenChange?: (isOpen: boolean) => void}',
|
|
102
103
|
description:
|
|
103
|
-
'Whether the content area (children)
|
|
104
|
-
default: '
|
|
104
|
+
'Whether the content area (children) sits behind an expand/collapse toggle in the header. On by default, starting collapsed. `false` opts out: children are always visible with no toggle. `{defaultIsOpen: true}` starts open; `{isOpen, onOpenChange}` is controlled. Takes the same CollapsibleConfig as Collapsible.',
|
|
105
|
+
default: 'true',
|
|
105
106
|
},
|
|
106
107
|
{
|
|
107
108
|
name: 'xstyle',
|
|
@@ -154,7 +155,7 @@ export const docsZh = {
|
|
|
154
155
|
{name: 'Description', required: false, description: 'Additional detail below the title.'},
|
|
155
156
|
{name: 'Action button', required: false, description: 'A button for the user to act on the message, like "Review" or "Retry".'},
|
|
156
157
|
{name: 'Dismiss button', required: false, description: 'Lets the user close the banner. Enabled by setting isDismissable.'},
|
|
157
|
-
{name: '
|
|
158
|
+
{name: 'Content', required: false, description: 'Extra detail below the banner header, like a list of errors. Sits behind an expand/collapse toggle by default; set collapsible={false} to keep it visible.'},
|
|
158
159
|
],
|
|
159
160
|
},
|
|
160
161
|
props: [
|
|
@@ -167,8 +168,8 @@ export const docsZh = {
|
|
|
167
168
|
{name: 'endContent', type: 'ReactNode', description: '渲染在头部区域末端对齐的操作内容,通常是按钮或链接。头部过窄时会整体换行到文本下方,自成一行。'},
|
|
168
169
|
{name: 'container', type: "'card' | 'section'", description: '视觉变体:card 带圆角;section 无圆角全宽,适用于页面级场景。', default: "'card'"},
|
|
169
170
|
{name: 'elevation', type: "'none' | 'low' | 'med' | 'high'", description: '静止阴影深度。用于悬浮于内容之上的浮动横幅;none 为默认内联横幅。', default: "'none'"},
|
|
170
|
-
{name: 'children', type: 'ReactNode', description: '
|
|
171
|
-
{name: '
|
|
171
|
+
{name: 'children', type: 'ReactNode', description: '渲染在彩色头部下方卡片背景区域的内容。默认位于展开/折叠开关之后,除非设置 collapsible={false}。'},
|
|
172
|
+
{name: 'collapsible', type: 'boolean | {defaultIsOpen?: boolean; isOpen?: boolean; onOpenChange?: (isOpen: boolean) => void}', description: '内容区域(children)是否位于头部的展开/折叠开关之后。默认开启,且初始为折叠状态。false 表示关闭:内容始终可见且没有开关。{defaultIsOpen: true} 表示初始展开;{isOpen, onOpenChange} 为受控模式。与 Collapsible 使用同一套 CollapsibleConfig。', default: 'true'},
|
|
172
173
|
{
|
|
173
174
|
name: 'xstyle',
|
|
174
175
|
type: 'StyleXStyles',
|
|
@@ -230,7 +231,7 @@ export const docsDense = {
|
|
|
230
231
|
{name: 'Description', required: false, description: 'Detail below title.'},
|
|
231
232
|
{name: 'Action button', required: false, description: 'CTA like Review or Retry.'},
|
|
232
233
|
{name: 'Dismiss button', required: false, description: 'Close button via isDismissable.'},
|
|
233
|
-
{name: '
|
|
234
|
+
{name: 'Content', required: false, description: 'Detail area; behind a toggle unless collapsible={false}.'},
|
|
234
235
|
],
|
|
235
236
|
},
|
|
236
237
|
propDescriptions: {
|
|
@@ -243,7 +244,8 @@ export const docsDense = {
|
|
|
243
244
|
endContent: 'end-aligned action in header, typically button/link; wraps to its own row when the header is too narrow',
|
|
244
245
|
container: 'card=border-radius; section=full-width no radius for page-level',
|
|
245
246
|
elevation: 'resting shadow depth: none|low|med|high; raise for a floating banner',
|
|
246
|
-
children: 'content in card-bg area below colored header',
|
|
247
|
+
children: 'content in card-bg area below colored header; behind a toggle unless collapsible={false}',
|
|
248
|
+
collapsible: 'children behind a header toggle; default true=collapsed. false=always visible, no toggle. {defaultIsOpen:true}=starts open, {isOpen,onOpenChange}=controlled',
|
|
247
249
|
xstyle: 'StyleX layout customization via stylex.create()',
|
|
248
250
|
},
|
|
249
251
|
};
|