@astryxdesign/core 0.7.5 → 0.7.6-canary.5cd7a15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AlertDialog/AlertDialog.d.ts +1 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +5 -5
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +12 -3
- package/dist/Badge/Badge.d.ts.map +1 -1
- package/dist/Badge/Badge.js +7 -1
- package/dist/BottomSheet/BottomSheet.js +1 -1
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +2 -1
- package/dist/BottomSheet/useSheetGestures.d.ts +12 -0
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
- package/dist/BottomSheet/useSheetGestures.js +30 -3
- package/dist/Button/Button.js +4 -4
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +6 -5
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +12 -4
- package/dist/DateInput/MonthScroller.d.ts.map +1 -1
- package/dist/DateInput/MonthScroller.js +101 -15
- package/dist/DateInput/TouchDateField.d.ts.map +1 -1
- package/dist/DateInput/TouchDateField.js +8 -3
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +1 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts +5 -2
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +23 -12
- package/dist/DateTimeInput/NativeTimeSegment.d.ts.map +1 -1
- package/dist/DateTimeInput/NativeTimeSegment.js +5 -4
- package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
- package/dist/DateTimeInput/TouchDateTimeField.js +4 -3
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +34 -9
- package/dist/Dialog/DialogHeader.d.ts.map +1 -1
- package/dist/Dialog/DialogHeader.js +5 -4
- package/dist/Divider/Divider.d.ts.map +1 -1
- package/dist/Divider/Divider.js +2 -1
- package/dist/Drawer/Drawer.d.ts +1 -0
- package/dist/Drawer/Drawer.d.ts.map +1 -1
- package/dist/Drawer/Drawer.js +7 -2
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +4 -1
- package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts.map +1 -1
- package/dist/DropdownMenu/MenuBottomSheetActionList.js +6 -5
- package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts +10 -1
- package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts.map +1 -1
- package/dist/DropdownMenu/lazyMenuBottomSheet.js +16 -2
- package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
- package/dist/DropdownMenu/renderDropdownItems.js +21 -16
- package/dist/EmptyState/EmptyState.d.ts.map +1 -1
- package/dist/EmptyState/EmptyState.js +2 -1
- package/dist/Field/FieldLabel.d.ts +1 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +4 -4
- package/dist/Field/InputClearButton.js +3 -3
- package/dist/Field/PanelSearchInput.js +2 -2
- package/dist/FieldStatus/FieldStatus.js +2 -2
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +7 -1
- package/dist/Heading/Heading.js +1 -1
- package/dist/Icon/Icon.js +1 -1
- package/dist/Indicator/CheckIndicator.d.ts.map +1 -1
- package/dist/Indicator/CheckIndicator.js +2 -1
- package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
- package/dist/Indicator/CheckboxIndicator.js +3 -1
- package/dist/Indicator/RadioIndicator.d.ts.map +1 -1
- package/dist/Indicator/RadioIndicator.js +3 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +2 -1
- package/dist/Item/ItemSwipeLayer.js +1 -1
- package/dist/Layout/Layout.js +1 -1
- package/dist/Layout/LayoutContent.js +1 -1
- package/dist/Layout/LayoutFooter.js +1 -1
- package/dist/Layout/LayoutHeader.js +1 -1
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +5 -0
- package/dist/Lightbox/LightboxViewport.a11y.browser.spec.js +5 -4
- package/dist/List/List.js +1 -1
- package/dist/List/ListItem.js +3 -3
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +7 -2
- package/dist/MultiSelector/MultiSelector.d.ts +1 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +5 -2
- package/dist/NumberInput/NumberInput.d.ts +3 -1
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +3 -3
- package/dist/NumberInput/numberParser.d.ts +3 -0
- package/dist/NumberInput/numberParser.d.ts.map +1 -1
- package/dist/NumberInput/numberParser.js +7 -44
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +16 -12
- package/dist/Resizable/useResizable.d.ts.map +1 -1
- package/dist/Resizable/useResizable.js +28 -2
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +4 -1
- package/dist/Selector/useSelectorPresentation.d.ts +8 -1
- package/dist/Selector/useSelectorPresentation.d.ts.map +1 -1
- package/dist/Selector/useSelectorPresentation.js +20 -4
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +7 -1
- package/dist/Spinner/Spinner.js +2 -2
- package/dist/Stack/Stack.js +1 -1
- package/dist/Stack/StackItem.js +1 -1
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +16 -1
- package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
- package/dist/Table/plugins/columnResize/useTableColumnResize.js +9 -1
- package/dist/Text/Text.js +1 -1
- package/dist/Text/useTruncation.d.ts.map +1 -1
- package/dist/Text/useTruncation.js +23 -5
- package/dist/TextArea/TextArea.d.ts +1 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +13 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +3 -3
- package/dist/TimeInput/TimeInput.d.ts +6 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +21 -14
- package/dist/TimeInput/TouchTimeField.d.ts.map +1 -1
- package/dist/TimeInput/TouchTimeField.js +5 -4
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +2 -2
- package/dist/Timestamp/TimestampHoverCard.js +4 -4
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +60 -20
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +82 -51
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +13 -2
- package/dist/Tokenizer/TokenizerBottomSheet.js +3 -3
- package/dist/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.js +2 -1
- package/dist/Typeahead/Typeahead.d.ts +1 -1
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +9 -1
- package/dist/astryx.css +15 -1
- package/dist/gestures/GestureArena.d.ts +6 -0
- package/dist/gestures/GestureArena.d.ts.map +1 -1
- package/dist/gestures/GestureArena.js +39 -0
- package/dist/gestures/GestureHost.d.ts +352 -0
- package/dist/gestures/GestureHost.d.ts.map +1 -0
- package/dist/gestures/GestureHost.js +1773 -0
- package/dist/gestures/GestureRecognizer.d.ts +10 -0
- package/dist/gestures/GestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/GestureRecognizer.js +16 -0
- package/dist/gestures/LongPressGestureRecognizer.d.ts +1 -0
- package/dist/gestures/LongPressGestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/LongPressGestureRecognizer.js +3 -0
- package/dist/gestures/PanGestureRecognizer.d.ts +1 -0
- package/dist/gestures/PanGestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/PanGestureRecognizer.js +3 -0
- package/dist/gestures/PinchGestureRecognizer.d.ts +31 -0
- package/dist/gestures/PinchGestureRecognizer.d.ts.map +1 -0
- package/dist/gestures/PinchGestureRecognizer.js +128 -0
- package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts +71 -0
- package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts.map +1 -0
- package/dist/gestures/ScreenEdgePanGestureRecognizer.js +223 -0
- package/dist/gestures/SwipeGestureRecognizer.d.ts +37 -0
- package/dist/gestures/SwipeGestureRecognizer.d.ts.map +1 -0
- package/dist/gestures/SwipeGestureRecognizer.js +148 -0
- package/dist/gestures/TapGestureRecognizer.d.ts +1 -0
- package/dist/gestures/TapGestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/TapGestureRecognizer.js +3 -0
- package/dist/gestures/VelocityTracker.d.ts +6 -2
- package/dist/gestures/VelocityTracker.d.ts.map +1 -1
- package/dist/gestures/VelocityTracker.js +7 -3
- package/dist/gestures/haptics.d.ts +65 -0
- package/dist/gestures/haptics.d.ts.map +1 -0
- package/dist/gestures/haptics.js +182 -0
- package/dist/gestures/nativeScroll.d.ts +42 -0
- package/dist/gestures/nativeScroll.d.ts.map +1 -0
- package/dist/gestures/nativeScroll.js +228 -0
- package/dist/gestures/touchAction.d.ts +60 -0
- package/dist/gestures/touchAction.d.ts.map +1 -0
- package/dist/gestures/touchAction.js +157 -0
- package/dist/gestures/touchActionRule.d.ts +34 -0
- package/dist/gestures/touchActionRule.d.ts.map +1 -0
- package/dist/gestures/touchActionRule.js +140 -0
- package/dist/gestures/types.d.ts +18 -7
- package/dist/gestures/types.d.ts.map +1 -1
- package/dist/gestures/types.js +22 -2
- package/dist/hooks/useAdaptivePresentation.d.ts.map +1 -1
- package/dist/hooks/useAdaptivePresentation.js +4 -1
- package/dist/hooks/useMenuHover.d.ts.map +1 -1
- package/dist/hooks/useMenuHover.js +12 -1
- package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/en.generated.js +3 -0
- package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pseudo.generated.js +3 -0
- package/dist/motion/animator.d.ts +7 -1
- package/dist/motion/animator.d.ts.map +1 -1
- package/dist/motion/animator.js +119 -27
- package/dist/theme/defineTheme.js +1 -1
- package/dist/theme/domainTokens/domainTokenDefaults.d.ts +3 -0
- package/dist/theme/domainTokens/domainTokenDefaults.d.ts.map +1 -0
- package/dist/theme/domainTokens/domainTokenDefaults.js +19 -0
- package/dist/theme/domainTokens/index.d.ts +5 -4
- package/dist/theme/domainTokens/index.d.ts.map +1 -1
- package/dist/theme/domainTokens/index.js +5 -9
- package/dist/utils/focusReturn.d.ts +17 -1
- package/dist/utils/focusReturn.d.ts.map +1 -1
- package/dist/utils/focusReturn.js +11 -4
- package/dist/utils/getNodeText.d.ts +8 -0
- package/dist/utils/getNodeText.d.ts.map +1 -0
- package/dist/utils/getNodeText.js +37 -0
- package/dist/utils/interactionModality.d.ts +11 -2
- package/dist/utils/interactionModality.d.ts.map +1 -1
- package/dist/utils/interactionModality.js +58 -5
- package/dist/utils/plainDate.d.ts +2 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +46 -3
- package/dist/utils/presentation.d.ts +50 -0
- package/dist/utils/presentation.d.ts.map +1 -0
- package/dist/utils/presentation.js +125 -0
- package/dist/utils/primaryClick.d.ts +11 -0
- package/dist/utils/primaryClick.d.ts.map +1 -0
- package/dist/utils/primaryClick.js +25 -0
- package/dist/utils/timeFormat.d.ts +47 -0
- package/dist/utils/timeFormat.d.ts.map +1 -0
- package/dist/utils/timeFormat.js +240 -0
- package/dist/utils/touchPresentation.d.ts.map +1 -1
- package/dist/utils/touchPresentation.js +5 -3
- package/dist/utils/touchPresentation.stylex.d.ts +15 -0
- package/dist/utils/touchPresentation.stylex.d.ts.map +1 -0
- package/dist/utils/touchPresentation.stylex.js +33 -0
- package/dist/utils/unicodeDigits.d.ts +20 -0
- package/dist/utils/unicodeDigits.d.ts.map +1 -0
- package/dist/utils/unicodeDigits.js +70 -0
- package/locales/en.json +15 -3
- package/locales/pseudo.json +9 -0
- package/package.json +5 -4
- package/src/AlertDialog/AlertDialog.tsx +6 -5
- package/src/AlertDialog/__tests__/AlertDialog.a11y.chromium.spec.ts +18 -6
- package/src/Avatar/Avatar.spec.md +22 -22
- package/src/Avatar/Avatar.tsx +18 -1
- package/src/Avatar/__tests__/AvatarForcedColors.a11y.chromium.spec.ts +126 -0
- package/src/Badge/Badge.doc.mjs +1 -1
- package/src/Badge/Badge.tsx +19 -2
- package/src/Badge/__tests__/BadgeLargerText.a11y.chromium.spec.ts +260 -0
- package/src/BottomSheet/BottomSheet.test.tsx +46 -0
- package/src/BottomSheet/BottomSheet.tsx +1 -1
- package/src/BottomSheet/BottomSheetPanel.tsx +2 -1
- package/src/BottomSheet/useSheetGestures.test.ts +52 -0
- package/src/BottomSheet/useSheetGestures.ts +37 -6
- package/src/Breadcrumbs/__tests__/Breadcrumbs.a11y.chromium.spec.ts +18 -6
- package/src/Button/Button.tsx +4 -4
- package/src/Calendar/Calendar.spec.md +87 -48
- package/src/Calendar/__tests__/Calendar.a11y.chromium.spec.ts +21 -7
- package/src/Carousel/__tests__/Carousel.a11y.chromium.spec.ts +21 -7
- package/src/CheckboxInput/CheckboxInput.tsx +6 -5
- package/src/Collapsible/Collapsible.spec.md +2 -0
- package/src/Collapsible/CollapsibleGroup.spec.md +57 -29
- package/src/Collapsible/__tests__/Collapsible.a11y.chromium.spec.ts +18 -7
- package/src/Collapsible/__tests__/CollapsibleGroupAccordion.a11y.chromium.spec.ts +18 -6
- package/src/ComplexSelector/ComplexSelector.test.tsx +37 -0
- package/src/ContextMenu/ContextMenu.test.tsx +35 -0
- package/src/DateInput/DateInput.test.tsx +115 -3
- package/src/DateInput/DateInput.tsx +29 -14
- package/src/DateInput/DateInputTouch.test.tsx +76 -0
- package/src/DateInput/MonthScroller.tsx +106 -20
- package/src/DateInput/MonthScrollerSettle.test.tsx +165 -0
- package/src/DateInput/TouchDateField.tsx +14 -3
- package/src/DateInput/__tests__/MonthScrollerSteps.interaction.browser.spec.ts +312 -0
- package/src/DateRangeInput/DateRangeInput.test.tsx +46 -3
- package/src/DateRangeInput/DateRangeInput.tsx +16 -12
- package/src/DateTimeInput/DateTimeInput.doc.mjs +10 -8
- package/src/DateTimeInput/DateTimeInput.spec.md +75 -51
- package/src/DateTimeInput/DateTimeInput.test.tsx +81 -0
- package/src/DateTimeInput/DateTimeInput.tsx +46 -24
- package/src/DateTimeInput/NativeTimeSegment.tsx +4 -6
- package/src/DateTimeInput/TouchDateTimeField.tsx +3 -7
- package/src/Dialog/Dialog.test.tsx +216 -2
- package/src/Dialog/Dialog.tsx +42 -9
- package/src/Dialog/DialogHeader.tsx +5 -4
- package/src/Dialog/__tests__/DialogSecondDocument.a11y.browser.spec.ts +202 -0
- package/src/Divider/Divider.tsx +2 -1
- package/src/Drawer/Drawer.spec.md +111 -80
- package/src/Drawer/Drawer.test.tsx +35 -0
- package/src/Drawer/Drawer.tsx +13 -2
- package/src/Drawer/DrawerHeader.spec.md +181 -0
- package/src/Drawer/__tests__/DrawerNonModalPageScroll.a11y.chromium.spec.ts +267 -0
- package/src/DropdownMenu/DropdownMenu.test.tsx +41 -0
- package/src/DropdownMenu/DropdownMenu.tsx +7 -1
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +34 -0
- package/src/DropdownMenu/MenuBottomSheetActionList.tsx +6 -5
- package/src/DropdownMenu/__tests__/Menu.a11y.chromium.spec.ts +19 -7
- package/src/DropdownMenu/__tests__/MenuButton.a11y.chromium.spec.ts +21 -9
- package/src/DropdownMenu/lazyMenuBottomSheet.test.ts +53 -0
- package/src/DropdownMenu/lazyMenuBottomSheet.ts +23 -6
- package/src/DropdownMenu/renderDropdownItems.tsx +24 -19
- package/src/EmptyState/EmptyState.tsx +2 -1
- package/src/Field/FieldLabel.tsx +5 -4
- package/src/Field/InputClearButton.tsx +3 -3
- package/src/Field/PanelSearchInput.tsx +2 -2
- package/src/FieldStatus/FieldStatus.tsx +2 -2
- package/src/FileInput/FileInput.test.tsx +21 -0
- package/src/FileInput/FileInput.tsx +4 -1
- package/src/FormLayout/FormLayout.spec.md +7 -8
- package/src/Heading/Heading.tsx +1 -1
- package/src/Icon/Icon.tsx +1 -1
- package/src/Indicator/CheckIndicator.spec.md +47 -42
- package/src/Indicator/CheckIndicator.tsx +2 -1
- package/src/Indicator/CheckboxIndicator.spec.md +40 -37
- package/src/Indicator/CheckboxIndicator.tsx +3 -1
- package/src/Indicator/Indicator.spec.md +188 -0
- package/src/Indicator/RadioIndicator.tsx +3 -1
- package/src/Item/Item.tsx +2 -1
- package/src/Item/ItemSwipeLayer.tsx +1 -1
- package/src/Layout/Layout.spec.md +127 -131
- package/src/Layout/Layout.tsx +1 -1
- package/src/Layout/LayoutContent.spec.md +205 -0
- package/src/Layout/LayoutContent.tsx +1 -1
- package/src/Layout/LayoutFooter.spec.md +190 -0
- package/src/Layout/LayoutFooter.tsx +1 -1
- package/src/Layout/LayoutHeader.spec.md +193 -0
- package/src/Layout/LayoutHeader.tsx +1 -1
- package/src/Layout/LayoutPanel.spec.md +194 -0
- package/src/Layout/__tests__/Layout.a11y.chromium.spec.ts +18 -6
- package/src/Lightbox/Lightbox.test.tsx +18 -0
- package/src/Lightbox/Lightbox.tsx +5 -0
- package/src/Lightbox/LightboxViewport.a11y.browser.spec.ts +8 -4
- package/src/Link/__tests__/Link.a11y.chromium.spec.ts +18 -8
- package/src/List/List.tsx +1 -1
- package/src/List/ListItem.spec.md +205 -0
- package/src/List/ListItem.tsx +3 -3
- package/src/MobileNav/MobileNav.test.tsx +15 -0
- package/src/MobileNav/MobileNav.tsx +9 -1
- package/src/MobileNav/__tests__/MobileNavHeader.a11y.chromium.spec.ts +89 -0
- package/src/MoreMenu/MoreMenu.test.tsx +11 -0
- package/src/MultiSelector/MultiSelector.spec.md +7 -4
- package/src/MultiSelector/MultiSelector.test.tsx +118 -1
- package/src/MultiSelector/MultiSelector.tsx +6 -2
- package/src/MultiSelector/__tests__/MultiSelector.listbox.a11y.test.tsx +8 -1
- package/src/NavMenu/NavHeadingMenu.spec.md +1 -5
- package/src/NumberInput/NumberInput.doc.mjs +13 -7
- package/src/NumberInput/NumberInput.spec.md +59 -37
- package/src/NumberInput/NumberInput.tsx +13 -3
- package/src/NumberInput/__tests__/NumberInput.coarse-pointer.a11y.chromium.spec.ts +102 -0
- package/src/NumberInput/numberParser.ts +7 -45
- package/src/ProgressBar/ProgressBar.test.tsx +108 -32
- package/src/ProgressBar/ProgressBar.tsx +58 -10
- package/src/ProgressBar/__tests__/ProgressBar.a11y.chromium.spec.ts +21 -9
- package/src/ProgressBar/__tests__/ProgressBarMotion.a11y.chromium.spec.ts +831 -0
- package/src/Resizable/__tests__/ResizeHandle.a11y.chromium.spec.ts +21 -14
- package/src/Resizable/useResizable.test.ts +43 -0
- package/src/Resizable/useResizable.ts +32 -9
- package/src/SegmentedControl/SegmentedControl.test.tsx +84 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +11 -5
- package/src/Selector/Selector.test.tsx +90 -1
- package/src/Selector/__tests__/Selector.combobox.a11y.test.tsx +8 -1
- package/src/Selector/__tests__/Selector.listbox.a11y.test.tsx +8 -1
- package/src/Selector/useSelectorPresentation.ts +31 -3
- package/src/SideNav/SideNav.test.tsx +27 -0
- package/src/SideNav/__tests__/SideNavRailMotion.interaction.browser.spec.ts +176 -51
- package/src/Slider/Slider.test.tsx +12 -0
- package/src/Slider/Slider.tsx +4 -1
- package/src/Slider/__tests__/Slider.a11y.chromium.spec.ts +19 -7
- package/src/Spinner/Spinner.tsx +2 -2
- package/src/Stack/Stack.tsx +1 -1
- package/src/Stack/StackItem.tsx +1 -1
- package/src/TabList/TabList.test.tsx +58 -4
- package/src/TabList/TabList.tsx +16 -1
- package/src/TabList/__tests__/TabPressPointer.interaction.browser.spec.ts +163 -0
- package/src/Table/__tests__/Table.a11y.chromium.spec.ts +18 -6
- package/src/Table/plugins/columnResize/useTableColumnResize.test.tsx +22 -0
- package/src/Table/plugins/columnResize/useTableColumnResize.tsx +8 -4
- package/src/Text/Text.tsx +1 -1
- package/src/Text/useTruncation.test.tsx +128 -1
- package/src/Text/useTruncation.ts +23 -5
- package/src/TextArea/TextArea.spec.md +10 -13
- package/src/TextArea/TextArea.test.tsx +60 -0
- package/src/TextArea/TextArea.tsx +15 -1
- package/src/TextInput/TextInput.test.tsx +21 -0
- package/src/TextInput/TextInput.tsx +3 -1
- package/src/TimeInput/NativeTimeInput.test.tsx +17 -0
- package/src/TimeInput/Presentation.test.tsx +21 -0
- package/src/TimeInput/TimeInput.doc.mjs +8 -8
- package/src/TimeInput/TimeInput.spec.md +45 -48
- package/src/TimeInput/TimeInput.test.tsx +76 -0
- package/src/TimeInput/TimeInput.tsx +36 -18
- package/src/TimeInput/TouchTimeField.tsx +4 -6
- package/src/Timestamp/Timestamp.spec.md +6 -12
- package/src/Timestamp/Timestamp.test.tsx +30 -5
- package/src/Timestamp/Timestamp.tsx +6 -2
- package/src/Timestamp/TimestampHoverCard.tsx +4 -4
- package/src/Toast/Toast.spec.md +14 -20
- package/src/Toast/Toast.tsx +104 -36
- package/src/Toast/ToastViewport.test.tsx +719 -1
- package/src/Toast/ToastViewport.tsx +100 -50
- package/src/Tokenizer/Tokenizer.spec.md +5 -3
- package/src/Tokenizer/Tokenizer.test.tsx +68 -0
- package/src/Tokenizer/Tokenizer.tsx +14 -2
- package/src/Tokenizer/TokenizerBottomSheet.test.tsx +15 -4
- package/src/Tokenizer/TokenizerBottomSheet.tsx +3 -3
- package/src/Toolbar/Toolbar.spec.md +5 -6
- package/src/Toolbar/Toolbar.test.tsx +30 -0
- package/src/Toolbar/Toolbar.tsx +2 -1
- package/src/Toolbar/__tests__/Toolbar.a11y.chromium.spec.ts +18 -6
- package/src/Tooltip/__tests__/Tooltip.a11y.chromium.spec.ts +18 -7
- package/src/TopNav/TopNav.test.tsx +27 -0
- package/src/Typeahead/Typeahead.test.tsx +40 -0
- package/src/Typeahead/Typeahead.tsx +12 -1
- package/src/gestures/GestureArena.ts +35 -0
- package/src/gestures/GestureHost.ts +2065 -0
- package/src/gestures/GestureRecognizer.ts +18 -0
- package/src/gestures/LongPressGestureRecognizer.ts +4 -0
- package/src/gestures/PanGestureRecognizer.ts +4 -0
- package/src/gestures/PinchGestureRecognizer.ts +148 -0
- package/src/gestures/ScreenEdgePanGestureRecognizer.ts +256 -0
- package/src/gestures/SwipeGestureRecognizer.ts +197 -0
- package/src/gestures/TapGestureRecognizer.ts +4 -0
- package/src/gestures/VelocityTracker.ts +10 -3
- package/src/gestures/__tests__/GestureHost.test.ts +2087 -0
- package/src/gestures/__tests__/PanGestureRecognizer.test.ts +4 -4
- package/src/gestures/__tests__/PinchGestureRecognizer.test.ts +74 -0
- package/src/gestures/__tests__/ScreenEdgePanGestureRecognizer.test.ts +498 -0
- package/src/gestures/__tests__/SwipeGestureRecognizer.test.ts +108 -0
- package/src/gestures/__tests__/arena.test.ts +5 -0
- package/src/gestures/__tests__/arenaPinchSwipeEdge.test.ts +193 -0
- package/src/gestures/__tests__/browser/build-fixture.mjs +46 -0
- package/src/gestures/__tests__/browser/fixture.ts +307 -0
- package/src/gestures/__tests__/browser/gestures.interaction.browser.spec.ts +1137 -0
- package/src/gestures/__tests__/browserNegotiation.test.ts +293 -0
- package/src/gestures/__tests__/haptics.test.ts +187 -0
- package/src/gestures/__tests__/harness.ts +21 -2
- package/src/gestures/__tests__/recognizerKind.test.ts +78 -0
- package/src/gestures/__tests__/touchActionRule.test.ts +54 -0
- package/src/gestures/haptics.ts +203 -0
- package/src/gestures/nativeScroll.ts +277 -0
- package/src/gestures/touchAction.ts +191 -0
- package/src/gestures/touchActionRule.ts +157 -0
- package/src/gestures/types.ts +30 -9
- package/src/hooks/useAdaptivePresentation.ts +4 -1
- package/src/hooks/useMenuHover.ts +15 -1
- package/src/i18n/generated-locales/en.generated.ts +4 -0
- package/src/i18n/generated-locales/pseudo.generated.ts +4 -0
- package/src/motion/README.md +11 -1
- package/src/motion/animator.test.ts +151 -3
- package/src/motion/animator.ts +149 -33
- package/src/theme/defineTheme.ts +1 -1
- package/src/theme/derivedVarRegistry.test.ts +4 -0
- package/src/theme/domainTokens/domainTokenDefaults.ts +19 -0
- package/src/theme/domainTokens/index.ts +6 -10
- package/src/utils/focusReturn.ts +17 -6
- package/src/utils/getNodeText.test.ts +24 -0
- package/src/utils/getNodeText.ts +37 -0
- package/src/utils/interactionModality.test.ts +45 -1
- package/src/utils/interactionModality.ts +64 -5
- package/src/utils/plainDate.test.ts +90 -0
- package/src/utils/plainDate.ts +58 -3
- package/src/utils/presentation.test.ts +380 -0
- package/src/utils/presentation.ts +180 -0
- package/src/utils/pressPaintPriority.test.ts +80 -0
- package/src/utils/primaryClick.test.ts +38 -0
- package/src/utils/primaryClick.ts +28 -0
- package/src/utils/timeFormat.test.ts +204 -0
- package/src/utils/timeFormat.ts +314 -0
- package/src/utils/touchPresentation.stylex.ts +43 -0
- package/src/utils/touchPresentation.test.ts +140 -1
- package/src/utils/touchPresentation.ts +5 -3
- package/src/utils/unicodeDigits.test.ts +44 -0
- package/src/utils/unicodeDigits.ts +71 -0
|
@@ -120,16 +120,30 @@ function bindingState(id: string): CarouselBindingRow {
|
|
|
120
120
|
return state;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
123
|
+
// Checking coverage runs every state again, which on a loaded runner nears
|
|
124
|
+
// the per-test timeout as one test. It runs as one serial part per state,
|
|
125
|
+
// sharing their results, then one check over all of them.
|
|
126
|
+
test.describe('every expectation is exercised by at least one Carousel state', () => {
|
|
127
|
+
test.describe.configure({mode: 'serial'});
|
|
127
128
|
const results: BindingResult[] = [];
|
|
129
|
+
|
|
128
130
|
for (const state of CAROUSEL_BINDING_STATES) {
|
|
129
|
-
|
|
131
|
+
test(`runs ${state.id}`, async ({page}) => {
|
|
132
|
+
const cdp = await page.context().newCDPSession(page);
|
|
133
|
+
results.push(await runState(page, cdp, state));
|
|
134
|
+
});
|
|
130
135
|
}
|
|
131
|
-
|
|
132
|
-
|
|
136
|
+
|
|
137
|
+
test('no expectation is left unexercised', () => {
|
|
138
|
+
// Every part ran in this worker; this test alone proves nothing.
|
|
139
|
+
expect(results.map(result => result.state).sort()).toEqual(
|
|
140
|
+
CAROUSEL_BINDING_STATES.map(state => state.id).sort(),
|
|
141
|
+
);
|
|
142
|
+
expect(neverExercised(results)).toEqual([]);
|
|
143
|
+
expect(unmatchedKnownFailures(CAROUSEL_KNOWN_FAILURES, results)).toEqual(
|
|
144
|
+
[],
|
|
145
|
+
);
|
|
146
|
+
});
|
|
133
147
|
});
|
|
134
148
|
|
|
135
149
|
for (const state of CAROUSEL_BINDING_STATES) {
|
|
@@ -41,17 +41,18 @@ import {FieldLabel} from '../Field/FieldLabel';
|
|
|
41
41
|
import {FieldStatus} from '../FieldStatus/FieldStatus';
|
|
42
42
|
import type {IconType} from '../Icon';
|
|
43
43
|
import type {InputStatus} from '../Field/types';
|
|
44
|
-
import {Spinner} from '../Spinner';
|
|
45
|
-
import {useTooltip} from '../Tooltip';
|
|
46
|
-
import {mergeProps
|
|
44
|
+
import {Spinner} from '../Spinner/Spinner';
|
|
45
|
+
import {useTooltip} from '../Tooltip/useTooltip';
|
|
46
|
+
import {mergeProps} from '../utils/mergeProps';
|
|
47
|
+
import {rtlStyles} from '../utils/rtlStyles';
|
|
47
48
|
import {indicatorScope} from '../Indicator/indicator.markers.stylex';
|
|
48
49
|
import {interactionOverlayStyles} from '../utils/interactionOverlay.stylex';
|
|
49
|
-
import {useTranslator} from '../i18n';
|
|
50
|
+
import {useTranslator} from '../i18n/useTranslator';
|
|
50
51
|
import {useIndicatorFocusRing} from '../hooks/useIndicatorFocusRing';
|
|
51
52
|
import {useBusyAnnouncement} from '../hooks/useBusyAnnouncement';
|
|
52
53
|
import {usePressFeedback} from '../hooks/usePressFeedback';
|
|
53
54
|
import {useResolvedRequired} from '../hooks/useResolvedRequired';
|
|
54
|
-
import {useIndicator} from '../Indicator';
|
|
55
|
+
import {useIndicator} from '../Indicator/useIndicator';
|
|
55
56
|
import {themeProps} from '../utils/themeProps';
|
|
56
57
|
|
|
57
58
|
import {useMergedRefs} from '../hooks/useMergedRefs';
|
|
@@ -69,6 +69,8 @@ Consumer migration instructions belong in consumer docs and release notes.
|
|
|
69
69
|
- caller-provided chevron, cue, icon, or render-function escape hatches;
|
|
70
70
|
- TreeList, Table, or another component's disclosure indicator;
|
|
71
71
|
- generic icon resolution or artwork customization;
|
|
72
|
+
- sibling open-value coordination, group state, and the divided group wrapper
|
|
73
|
+
— owned by `component:CollapsibleGroup`;
|
|
72
74
|
- a shared responsive or directional API; or
|
|
73
75
|
- new content-reveal motion behavior. Existing behavior outside this decision stays
|
|
74
76
|
unchanged until its own current authority changes it.
|
|
@@ -3,11 +3,11 @@ schema_version: 3
|
|
|
3
3
|
template_version: 7
|
|
4
4
|
kind: component
|
|
5
5
|
id: component:CollapsibleGroup
|
|
6
|
-
authority:
|
|
6
|
+
authority: current
|
|
7
7
|
archive_reason: null
|
|
8
8
|
superseded_by: null
|
|
9
|
-
approved_by:
|
|
10
|
-
approved_at:
|
|
9
|
+
approved_by: cixzhang
|
|
10
|
+
approved_at: 2026-10-31
|
|
11
11
|
owners: [cixzhang, imdreamrunner]
|
|
12
12
|
review_triggers: [public-api, behavior, layout, accessibility, theming]
|
|
13
13
|
verified_by:
|
|
@@ -17,6 +17,8 @@ verified_by:
|
|
|
17
17
|
packages/core/src/Collapsible/__tests__/Collapsible.a11y.test.tsx,
|
|
18
18
|
packages/core/src/Collapsible/__tests__/Collapsible.a11y.chromium.spec.ts,
|
|
19
19
|
packages/core/src/Collapsible/__tests__/CollapsibleGroup.a11y.chromium.spec.ts,
|
|
20
|
+
packages/core/src/Collapsible/__tests__/CollapsibleGroup.a11y.test.tsx,
|
|
21
|
+
packages/core/src/Collapsible/__tests__/CollapsibleGroupAccordion.a11y.chromium.spec.ts,
|
|
20
22
|
packages/core/src/theme/themingTargets.test.ts,
|
|
21
23
|
apps/storybook/stories/CollapsibleGroup.stories.tsx,
|
|
22
24
|
]
|
|
@@ -31,7 +33,7 @@ architecture:
|
|
|
31
33
|
architecture:component-test-sufficiency,
|
|
32
34
|
]
|
|
33
35
|
contributing: [contributing:api-conventions]
|
|
34
|
-
system_specs: [spec:AST-029]
|
|
36
|
+
system_specs: [spec:AST-029, spec:AST-085]
|
|
35
37
|
---
|
|
36
38
|
|
|
37
39
|
# CollapsibleGroup component contract
|
|
@@ -44,11 +46,11 @@ system_specs: [spec:AST-029]
|
|
|
44
46
|
| Behavior | Direct children with a `value` read group state; opening an item replaces or extends the open-value set according to mode. The group renders no wrapper unless divider chrome is enabled. |
|
|
45
47
|
| End-user impact | People can reveal one section or several sections without disclosure state drifting between sibling rows; divided groups keep one coherent visual and directional treatment. |
|
|
46
48
|
| Builder impact | Builders choose state ownership and selection mode, give participating items stable values, and may opt into divided-row presentation. |
|
|
47
|
-
| Compatibility/readiness |
|
|
49
|
+
| Compatibility/readiness | Records shipped behavior; no public change. Three implementation gaps, listed under Current-state impact. |
|
|
48
50
|
| Review checks | Reject lost single/multiple coordination, controlled state that mutates internally, uncontrolled state that stops updating, presentation leakage into nested disclosures, or a wrapper appearing when dividers are absent. |
|
|
49
51
|
| Governing rules | `component:Collapsible/FR7–FR9,DEC-2`; `architecture:public-component-api/INV1,INV5–INV9`; `architecture:react-component-runtime/INV1,INV8–INV9`; `architecture:component-theming-surface/INV3–INV7`. |
|
|
50
52
|
|
|
51
|
-
This table is a review projection; the body below is authoritative
|
|
53
|
+
This table is a review projection; the body below is authoritative.
|
|
52
54
|
|
|
53
55
|
## Intent
|
|
54
56
|
|
|
@@ -57,12 +59,29 @@ Coordinate a set of disclosure items so their open state follows one group owner
|
|
|
57
59
|
## Compatibility and migration
|
|
58
60
|
|
|
59
61
|
- Released default preserved: yes
|
|
60
|
-
- Compatibility class:
|
|
62
|
+
- Compatibility class: records shipped behavior; no public change
|
|
61
63
|
- Controlled/uncontrolled behavior: unchanged
|
|
62
64
|
- Migration decision: none
|
|
63
65
|
|
|
64
66
|
Consumer migration instructions belong in consumer docs and release notes.
|
|
65
67
|
|
|
68
|
+
## Current-state impact
|
|
69
|
+
|
|
70
|
+
- **A disabled header leaves the Tab order.** A disabled direct item's header
|
|
71
|
+
carries `aria-disabled` but drops out of the Tab order, so a keyboard user
|
|
72
|
+
cannot reach it to learn why it is unavailable. `spec:AST-085` FR1 keeps a
|
|
73
|
+
disabled control focusable; the header is owned by `component:Collapsible`.
|
|
74
|
+
- **Equal values can rebuild the coordination context.** An equal new
|
|
75
|
+
controlled array, or a new `onChange` such as an inline handler, rebuilds the
|
|
76
|
+
coordination context on every parent render, so memoized direct items
|
|
77
|
+
re-render. `architecture:react-component-runtime` INV9 keeps an unchanged
|
|
78
|
+
payload from broadcasting a new identity (FR7).
|
|
79
|
+
- **The accordion binding runs adopted rows as advisory.** The binding runs
|
|
80
|
+
the header-to-header Tab step, single-mode sibling collapse, and no
|
|
81
|
+
arrow-key movement as advisory rows, so
|
|
82
|
+
a regression there does not fail the binding lane. `spec:AST-020` FR9 makes
|
|
83
|
+
an adopted expectation required once this record adopts it (AR4).
|
|
84
|
+
|
|
66
85
|
## Ownership boundary
|
|
67
86
|
|
|
68
87
|
**Owns**
|
|
@@ -90,15 +109,15 @@ Consumer migration instructions belong in consumer docs and release notes.
|
|
|
90
109
|
|
|
91
110
|
## Behavioral and layout contract
|
|
92
111
|
|
|
93
|
-
| ID |
|
|
94
|
-
| --- |
|
|
95
|
-
| FR1 | In `single` mode, toggling a closed direct item MUST replace the open-value set with that item, and toggling the open item MUST clear the set.
|
|
96
|
-
| FR2 | In `multiple` mode, toggling a direct item MUST add or remove only that value while preserving the state of other values.
|
|
97
|
-
| FR3 | Supplying `value` MUST keep state caller-owned and report requested changes through `onChange`; omitting it MUST keep state internal after initialization from `defaultValue`.
|
|
98
|
-
| FR4 | A direct `Collapsible` with a `value` MUST use group coordination; an item without a value MUST retain standalone ownership.
|
|
99
|
-
| FR5 | With `hasDividers=false`, the group MUST add no DOM wrapper. With dividers enabled it MUST render one wrapper that receives documented root props and the `collapsible-group` target.
|
|
100
|
-
| FR6 | Density, divider, and chevron defaults MUST reach direct items without leaking through a direct item's revealed content into nested independent disclosures.
|
|
101
|
-
| FR7 | Presentation context identity MUST remain stable while divider, density, and chevron inputs are unchanged; coordination identity MUST
|
|
112
|
+
| ID | Invariant | Basis |
|
|
113
|
+
| --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
114
|
+
| FR1 | In `single` mode, toggling a closed direct item MUST replace the open-value set with that item, and toggling the open item MUST clear the set. | shipped source, consumer docs, and focused interaction tests |
|
|
115
|
+
| FR2 | In `multiple` mode, toggling a direct item MUST add or remove only that value while preserving the state of other values. | shipped source, consumer docs, and focused interaction tests |
|
|
116
|
+
| FR3 | Supplying `value` MUST keep state caller-owned and report requested changes through `onChange`; omitting it MUST keep state internal after initialization from `defaultValue`. | `architecture:react-component-runtime/INV1,INV8`; shipped controlled and uncontrolled tests |
|
|
117
|
+
| FR4 | A direct `Collapsible` with a `value` MUST use group coordination; an item without a value MUST retain standalone ownership. | shipped hook behavior and focused group/standalone tests |
|
|
118
|
+
| FR5 | With `hasDividers=false`, the group MUST add no DOM wrapper. With dividers enabled it MUST render one wrapper that receives documented root props and the `collapsible-group` target. | `architecture:public-component-api/INV5–INV8`; `architecture:component-theming-surface/INV3–INV7` |
|
|
119
|
+
| FR6 | Density, divider, and chevron defaults MUST reach direct items without leaking through a direct item's revealed content into nested independent disclosures. | `component:Collapsible/FR7–FR8,DEC-2`; focused nesting tests |
|
|
120
|
+
| FR7 | Presentation context identity MUST remain stable while divider, density, and chevron inputs are unchanged; coordination identity MUST stay stable across a rerender with an unchanged controlled string, the same controlled array reference, or unchanged internal state, with the same `type` and `onChange`. Implementation gap: an equal new controlled array or a new `onChange` rebuilds it (Current-state impact). | `architecture:react-component-runtime/INV9`; memoized source and interaction tests |
|
|
102
121
|
|
|
103
122
|
### Allowed variation
|
|
104
123
|
|
|
@@ -126,14 +145,14 @@ Consumer migration instructions belong in consumer docs and release notes.
|
|
|
126
145
|
### Performance and resources
|
|
127
146
|
|
|
128
147
|
- **PR1 — Render-owned coordination.** The group derives output from props, state, and context and owns no Effect, listener, observer, timer, request, subscription, or imperative browser resource.
|
|
129
|
-
- **PR2 — Stable broadcasts.** Memoized context values
|
|
148
|
+
- **PR2 — Stable broadcasts.** Memoized context values keep the identities FR7 names stable for direct consumers.
|
|
130
149
|
|
|
131
150
|
## Accessibility contract
|
|
132
151
|
|
|
133
152
|
- **AR1 — Child semantics remain primary.** Group coordination MUST preserve each Collapsible button's accessible name, `aria-expanded`, `aria-controls`, controlled region, and keyboard activation.
|
|
134
153
|
- **AR2 — Presentation adds no competing interaction.** The divider wrapper MUST NOT add a role, focus target, accessible name, or keyboard behavior.
|
|
135
154
|
- **AR3 — Direction stays with Collapsible.** Group chevron defaults MUST preserve `component:Collapsible/AR1–AR3`, including the inward leading cue under LTR and RTL.
|
|
136
|
-
- **AR4 — The group adopts the APG Accordion pattern's required parts** (`spec:AST-020/FR15`): each direct item's header is a `button` whose accessible name is the item's title, with `aria-expanded` reflecting its panel, `aria-controls` naming the panel it reveals, and `aria-disabled` when it cannot be toggled; every enabled header sits in the page Tab order and Enter or Space toggles its panel, in `single` mode collapsing the sibling that was open; a disabled header carries `aria-disabled
|
|
155
|
+
- **AR4 — The group adopts the APG Accordion pattern's required parts** (`spec:AST-020/FR15`): each direct item's header is a `button` whose accessible name is the item's title, with `aria-expanded` reflecting its panel, `aria-controls` naming the panel it reveals, and `aria-disabled` when it cannot be toggled; every enabled header sits in the page Tab order and Enter or Space toggles its panel, in `single` mode collapsing the sibling that was open; a disabled header carries `aria-disabled` and cannot be toggled, apart from the Tab-order gap (Current-state impact). Not adopted: a heading element around each header (this record requires none; the caller's document structure supplies headings), the optional `region` role on panels, and arrow-key or Home/End movement between headers — the group is a set of independent disclosures, not one composite control.
|
|
137
156
|
|
|
138
157
|
## Design relationships
|
|
139
158
|
|
|
@@ -142,7 +161,7 @@ Consumer migration instructions belong in consumer docs and release notes.
|
|
|
142
161
|
| Group container | Optional divider chrome visually associates sibling disclosures as a set. | observed shipped representation | aggregate container | FR5–FR6, AR2 |
|
|
143
162
|
| Direct item | Density and chevron defaults remain consistent across sibling rows. | `component:Collapsible/FR7–FR8` | disclosure row | FR6, AR3 |
|
|
144
163
|
|
|
145
|
-
No current design record prescribes exact CollapsibleGroup pixels. This
|
|
164
|
+
No current design record prescribes exact CollapsibleGroup pixels. This record covers the shipped divided and plain relationships without deciding new visual direction.
|
|
146
165
|
|
|
147
166
|
### Theming anatomy
|
|
148
167
|
|
|
@@ -160,7 +179,7 @@ No current design record prescribes exact CollapsibleGroup pixels. This observat
|
|
|
160
179
|
}
|
|
161
180
|
```
|
|
162
181
|
|
|
163
|
-
The Group container is CollapsibleGroup's conditional aggregate wrapper. The other anatomy rows remain owned by `component:Collapsible`; they are repeated in this
|
|
182
|
+
The Group container is CollapsibleGroup's conditional aggregate wrapper. The other anatomy rows remain owned by `component:Collapsible`; they are repeated in this subcomponent map only because the released consumer anatomy and target inventory are shared. Trigger, content, chevron, open state, disabled state, density padding, and per-item dividers remain with Collapsible's contract.
|
|
164
183
|
|
|
165
184
|
## Family and system relationships
|
|
166
185
|
|
|
@@ -172,14 +191,23 @@ The Group container is CollapsibleGroup's conditional aggregate wrapper. The oth
|
|
|
172
191
|
|
|
173
192
|
## Verification map
|
|
174
193
|
|
|
175
|
-
| Contract | Verification
|
|
176
|
-
| ---------------------- |
|
|
177
|
-
| FR1–FR4, ORD1 | `CollapsibleGroup.test.tsx`; `useCollapsible.test.tsx`
|
|
178
|
-
| FR5–FR6, ORD2–ORD3 | `CollapsibleGroup.test.tsx`; `Collapsible.test.tsx`; `themingTargets.test.ts`
|
|
179
|
-
| AR4 | `Collapsible.test.tsx` (disabled trigger: `aria-disabled
|
|
180
|
-
| AR1–AR3 | DOM and Chromium accessibility suites; component-owned Storybook fixture; RTL audit
|
|
181
|
-
| PR1–PR2, FR7 | source review plus context and interaction tests
|
|
182
|
-
| Consumer documentation | CLI component projection, docs checks, and `CollapsibleGroup.stories.tsx`
|
|
194
|
+
| Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
|
|
195
|
+
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
|
|
196
|
+
| FR1–FR4, ORD1 | `CollapsibleGroup.test.tsx`; `useCollapsible.test.tsx` | single/multiple; controlled/uncontrolled; valued/unvalued | A sibling stays open in single mode, closes in multiple mode, controlled state mutates internally, or an unvalued item loses local state. | `audit:CollapsibleGroup/behavior` |
|
|
197
|
+
| FR5–FR6, ORD2–ORD3 | `CollapsibleGroup.test.tsx`; `Collapsible.test.tsx`; `themingTargets.test.ts` | plain/divided; each density; group/item/nested position | Wrapper/target reachability changes, defaults stop reaching direct items, or presentation leaks into nested content. | `audit:CollapsibleGroup/theming` |
|
|
198
|
+
| AR4 | `Collapsible.test.tsx` (disabled trigger: `aria-disabled` and no toggle; its out-of-Tab-order assertion pins the gap, pending conformance); `CollapsibleGroup.test.tsx` (single/multiple coordination, `aria-expanded`, Enter activation); `Collapsible.a11y.test.tsx` and `Collapsible.a11y.chromium.spec.ts` (disclosure semantics, Space, Tab reachability for a lone item); `CollapsibleGroup.a11y.test.tsx` and `CollapsibleGroupAccordion.a11y.chromium.spec.ts` (Space on grouped headers; the header-to-header Tab step, single-mode sibling collapse, and no arrow-key movement run as advisory rows) | single/multiple; open/closed; a disabled item, open or closed; Tab order; Enter/Space round trip | A header loses its button role, name, `aria-expanded`, or `aria-controls`; Enter or Space stops toggling; arrow keys move focus between headers | `audit:CollapsibleGroup/accessibility` |
|
|
199
|
+
| AR1–AR3 | DOM and Chromium accessibility suites; component-owned Storybook fixture; RTL audit | open/closed; single/multiple; leading/trailing; LTR/RTL | Disclosure semantics diverge from state, the wrapper becomes interactive, or leading direction stops mirroring. | `audit:CollapsibleGroup/accessibility` |
|
|
200
|
+
| PR1–PR2, FR7 | source review plus context and interaction tests | unchanged and changed state/presentation inputs | An Effect/resource appears, unchanged payload broadcasts a new identity, or changed group behavior fails to reach consumers. | `audit:CollapsibleGroup/code-health` |
|
|
201
|
+
| Consumer documentation | CLI component projection, docs checks, and `CollapsibleGroup.stories.tsx` | every public concept and representative composition | A released prop/default is undiscoverable or the owned browser route loses representative state coverage. | `audit:CollapsibleGroup/docs` |
|
|
202
|
+
|
|
203
|
+
Read from source, with no focused test yet:
|
|
204
|
+
|
|
205
|
+
- AR4: no Home/End movement between headers.
|
|
206
|
+
- FR7: presentation context identity staying stable while divider, density,
|
|
207
|
+
and chevron inputs are unchanged, and coordination identity across the same
|
|
208
|
+
array reference, unchanged internal state, and an equal new array; only the
|
|
209
|
+
controlled-string case is tested.
|
|
210
|
+
- PR1: the group owning no Effect or browser resource.
|
|
183
211
|
|
|
184
212
|
## Decision log
|
|
185
213
|
|
|
@@ -194,7 +222,7 @@ Rejected: arrow-key movement between headers; a required heading element around
|
|
|
194
222
|
|
|
195
223
|
## Open questions
|
|
196
224
|
|
|
197
|
-
None. This
|
|
225
|
+
None. This record does not broaden the released coordination modes or decide new presentation.
|
|
198
226
|
|
|
199
227
|
## Content boundary
|
|
200
228
|
|
|
@@ -155,16 +155,27 @@ test('the state inventory matches rendered disclosure facts', async ({
|
|
|
155
155
|
expect(wrong).toEqual([]);
|
|
156
156
|
});
|
|
157
157
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
158
|
+
// Checking coverage runs every state again, which on a loaded runner nears
|
|
159
|
+
// the per-test timeout as one test. It runs as one serial part per state,
|
|
160
|
+
// sharing their results, then one check over all of them.
|
|
161
|
+
test.describe('every disclosure expectation is exercised by a Collapsible state', () => {
|
|
162
|
+
test.describe.configure({mode: 'serial'});
|
|
163
163
|
const results: BindingResult[] = [];
|
|
164
|
+
|
|
164
165
|
for (const state of COLLAPSIBLE_DISCLOSURE_STATES) {
|
|
165
|
-
|
|
166
|
+
test(`runs ${state.id}`, async ({page}) => {
|
|
167
|
+
const cdp = await page.context().newCDPSession(page);
|
|
168
|
+
results.push(await runState(page, cdp, state));
|
|
169
|
+
});
|
|
166
170
|
}
|
|
167
|
-
|
|
171
|
+
|
|
172
|
+
test('no expectation is left unexercised', () => {
|
|
173
|
+
// Every part ran in this worker; this test alone proves nothing.
|
|
174
|
+
expect(results.map(result => result.state).sort()).toEqual(
|
|
175
|
+
COLLAPSIBLE_DISCLOSURE_STATES.map(state => state.id).sort(),
|
|
176
|
+
);
|
|
177
|
+
expect(neverExercised(results)).toEqual([]);
|
|
178
|
+
});
|
|
168
179
|
});
|
|
169
180
|
|
|
170
181
|
for (const state of COLLAPSIBLE_DISCLOSURE_STATES) {
|
|
@@ -103,15 +103,27 @@ async function runState(
|
|
|
103
103
|
});
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
106
|
+
// Checking coverage runs every state again, which on a loaded runner nears
|
|
107
|
+
// the per-test timeout as one test. It runs as one serial part per state,
|
|
108
|
+
// sharing their results, then one check over all of them.
|
|
109
|
+
test.describe('every accordion expectation is exercised by a CollapsibleGroup state', () => {
|
|
110
|
+
test.describe.configure({mode: 'serial'});
|
|
110
111
|
const results: BindingResult[] = [];
|
|
112
|
+
|
|
111
113
|
for (const state of COLLAPSIBLE_GROUP_ACCORDION_STATES) {
|
|
112
|
-
|
|
114
|
+
test(`runs ${state.id}`, async ({page}) => {
|
|
115
|
+
const cdp = await page.context().newCDPSession(page);
|
|
116
|
+
results.push(await runState(page, cdp, state));
|
|
117
|
+
});
|
|
113
118
|
}
|
|
114
|
-
|
|
119
|
+
|
|
120
|
+
test('no expectation is left unexercised', () => {
|
|
121
|
+
// Every part ran in this worker; this test alone proves nothing.
|
|
122
|
+
expect(results.map(result => result.state).sort()).toEqual(
|
|
123
|
+
COLLAPSIBLE_GROUP_ACCORDION_STATES.map(state => state.id).sort(),
|
|
124
|
+
);
|
|
125
|
+
expect(neverExercised(results)).toEqual([]);
|
|
126
|
+
});
|
|
115
127
|
});
|
|
116
128
|
|
|
117
129
|
for (const state of COLLAPSIBLE_GROUP_ACCORDION_STATES) {
|
|
@@ -755,6 +755,43 @@ describe('ComplexSelector trigger semantics', () => {
|
|
|
755
755
|
expect(trigger).toHaveAttribute('aria-labelledby', 'trip-heading');
|
|
756
756
|
});
|
|
757
757
|
|
|
758
|
+
// WCAG 2.5.3 Label in Name (axe `label-content-name-mismatch`) applies to
|
|
759
|
+
// controls named from their content. A button named by `aria-labelledby`
|
|
760
|
+
// while showing the chosen value failed it, and hid the value from the
|
|
761
|
+
// accessibility tree. As a combobox the label is the name and the text it
|
|
762
|
+
// shows is the value, as on `Selector`.
|
|
763
|
+
it('names the trigger by its label and shows the chosen value as its content', () => {
|
|
764
|
+
render(
|
|
765
|
+
<ComplexSelector
|
|
766
|
+
label="Supplier"
|
|
767
|
+
value="1"
|
|
768
|
+
onChange={() => {}}
|
|
769
|
+
triggerLabel="Acme Ltd">
|
|
770
|
+
{() => <p>Choose a supplier</p>}
|
|
771
|
+
</ComplexSelector>,
|
|
772
|
+
);
|
|
773
|
+
// A combobox takes no name from its content, so the value is not in the
|
|
774
|
+
// name and Label in Name has nothing to compare it with.
|
|
775
|
+
expect(screen.queryByRole('button', {name: /Supplier/})).toBeNull();
|
|
776
|
+
const trigger = screen.getByRole('combobox', {name: 'Supplier'});
|
|
777
|
+
expect(trigger).toHaveTextContent('Acme Ltd');
|
|
778
|
+
expect(trigger).toHaveAccessibleName('Supplier');
|
|
779
|
+
});
|
|
780
|
+
|
|
781
|
+
it('keeps the field label as the name when the trigger shows the placeholder', () => {
|
|
782
|
+
render(
|
|
783
|
+
<ComplexSelector
|
|
784
|
+
label="Supplier"
|
|
785
|
+
value=""
|
|
786
|
+
onChange={() => {}}
|
|
787
|
+
placeholder="Choose a supplier">
|
|
788
|
+
{() => <p>Pick one</p>}
|
|
789
|
+
</ComplexSelector>,
|
|
790
|
+
);
|
|
791
|
+
const trigger = screen.getByRole('combobox', {name: 'Supplier'});
|
|
792
|
+
expect(trigger).toHaveTextContent('Choose a supplier');
|
|
793
|
+
});
|
|
794
|
+
|
|
758
795
|
it('spreads the combobox role, required, and disabled state onto a caller control', async () => {
|
|
759
796
|
const user = userEvent.setup();
|
|
760
797
|
const onClick = vi.fn();
|
|
@@ -1320,6 +1320,41 @@ describe('ContextMenu keyboard access for menuitemradio/menuitemcheckbox (#3829)
|
|
|
1320
1320
|
});
|
|
1321
1321
|
});
|
|
1322
1322
|
|
|
1323
|
+
describe('ContextMenu data-driven submenu inside a section', () => {
|
|
1324
|
+
it('renders a submenu row for an item with nested items inside a section', () => {
|
|
1325
|
+
render(
|
|
1326
|
+
<ContextMenu
|
|
1327
|
+
items={[
|
|
1328
|
+
{
|
|
1329
|
+
type: 'section',
|
|
1330
|
+
title: 'Organize',
|
|
1331
|
+
items: [
|
|
1332
|
+
{label: 'Rename', onClick: () => {}},
|
|
1333
|
+
{
|
|
1334
|
+
label: 'Move to',
|
|
1335
|
+
items: [
|
|
1336
|
+
{label: 'Folder A', onClick: () => {}},
|
|
1337
|
+
{label: 'Folder B', onClick: () => {}},
|
|
1338
|
+
],
|
|
1339
|
+
},
|
|
1340
|
+
],
|
|
1341
|
+
},
|
|
1342
|
+
]}>
|
|
1343
|
+
<div>Right-click me</div>
|
|
1344
|
+
</ContextMenu>,
|
|
1345
|
+
);
|
|
1346
|
+
fireEvent.contextMenu(screen.getByText('Right-click me'));
|
|
1347
|
+
const trigger = screen.getByRole('menuitem', {
|
|
1348
|
+
name: /Move to/,
|
|
1349
|
+
hidden: true,
|
|
1350
|
+
});
|
|
1351
|
+
expect(trigger).toHaveAttribute('aria-haspopup', 'menu');
|
|
1352
|
+
expect(
|
|
1353
|
+
screen.getByRole('menuitem', {name: 'Folder A', hidden: true}),
|
|
1354
|
+
).toBeInTheDocument();
|
|
1355
|
+
});
|
|
1356
|
+
});
|
|
1357
|
+
|
|
1323
1358
|
describe('ContextMenu press model', () => {
|
|
1324
1359
|
const touch = {pointerType: 'touch', pointerId: 1};
|
|
1325
1360
|
const item = (name: string) =>
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
} from '@testing-library/react';
|
|
22
22
|
import userEvent from '@testing-library/user-event';
|
|
23
23
|
import {getButton, queryButton} from '../__tests__/fastRoleQueries';
|
|
24
|
-
import {DateInput} from './DateInput';
|
|
24
|
+
import {DateInput, type DateInputProps} from './DateInput';
|
|
25
25
|
import {Icon} from '../Icon';
|
|
26
26
|
import {InputGroup} from '../InputGroup';
|
|
27
27
|
import {InputGroupText} from '../InputGroup/InputGroupText';
|
|
@@ -570,6 +570,67 @@ describe('DateInput', () => {
|
|
|
570
570
|
);
|
|
571
571
|
});
|
|
572
572
|
|
|
573
|
+
it('blocks selection in an open picker after the field becomes disabled', async () => {
|
|
574
|
+
const user = userEvent.setup();
|
|
575
|
+
const props = {
|
|
576
|
+
label: 'Date',
|
|
577
|
+
value: '2026-10-15',
|
|
578
|
+
presentation: 'popover',
|
|
579
|
+
onChange: vi.fn(),
|
|
580
|
+
changeAction: vi.fn(),
|
|
581
|
+
} satisfies DateInputProps;
|
|
582
|
+
const {rerender} = render(<DateInput {...props} />);
|
|
583
|
+
const input = screen.getByRole('combobox');
|
|
584
|
+
act(() => input.focus());
|
|
585
|
+
await user.keyboard('{ArrowDown}');
|
|
586
|
+
const day = getButton(/October 16, 2026/);
|
|
587
|
+
act(() => day.focus());
|
|
588
|
+
|
|
589
|
+
rerender(<DateInput {...props} isDisabled />);
|
|
590
|
+
expect(day).toHaveFocus();
|
|
591
|
+
await user.click(day);
|
|
592
|
+
await user.keyboard(' ');
|
|
593
|
+
|
|
594
|
+
rerender(
|
|
595
|
+
<DateInput
|
|
596
|
+
{...props}
|
|
597
|
+
isDisabled
|
|
598
|
+
disabledMessage="Scheduling is locked"
|
|
599
|
+
/>,
|
|
600
|
+
);
|
|
601
|
+
expect(day).toHaveFocus();
|
|
602
|
+
await user.keyboard('{Enter}');
|
|
603
|
+
expect(props.onChange).not.toHaveBeenCalled();
|
|
604
|
+
expect(props.changeAction).not.toHaveBeenCalled();
|
|
605
|
+
expect(input).toHaveValue('October 15, 2026');
|
|
606
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
607
|
+
expect(day).toHaveFocus();
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
it('dismisses an open picker without committing while loading', async () => {
|
|
611
|
+
const user = userEvent.setup();
|
|
612
|
+
const props = {
|
|
613
|
+
label: 'Date',
|
|
614
|
+
value: '2026-10-15',
|
|
615
|
+
presentation: 'popover',
|
|
616
|
+
onChange: vi.fn(),
|
|
617
|
+
changeAction: vi.fn(),
|
|
618
|
+
} satisfies DateInputProps;
|
|
619
|
+
const {rerender} = render(<DateInput {...props} />);
|
|
620
|
+
await user.click(getButton('Open calendar'));
|
|
621
|
+
const day = getButton(/October 16, 2026/);
|
|
622
|
+
|
|
623
|
+
rerender(<DateInput {...props} isLoading />);
|
|
624
|
+
await user.click(day);
|
|
625
|
+
expect(props.onChange).not.toHaveBeenCalled();
|
|
626
|
+
expect(props.changeAction).not.toHaveBeenCalled();
|
|
627
|
+
expect(screen.getByRole('combobox')).toHaveValue('October 15, 2026');
|
|
628
|
+
expect(screen.getByRole('combobox')).toHaveAttribute(
|
|
629
|
+
'aria-expanded',
|
|
630
|
+
'false',
|
|
631
|
+
);
|
|
632
|
+
});
|
|
633
|
+
|
|
573
634
|
// --- Enter key commits typed date ---
|
|
574
635
|
|
|
575
636
|
it('commits typed date and fires onChange on Enter key', () => {
|
|
@@ -633,15 +694,19 @@ describe('DateInput', () => {
|
|
|
633
694
|
}
|
|
634
695
|
|
|
635
696
|
render(<ControlledDateInput />);
|
|
636
|
-
|
|
697
|
+
const toggle = getButton('Open calendar');
|
|
698
|
+
await user.click(toggle);
|
|
637
699
|
await user.click(getButton(/January 15, 2026/));
|
|
700
|
+
// The calendar mounts only while open; reopen it to read the selection.
|
|
701
|
+
await user.click(toggle);
|
|
638
702
|
expect(
|
|
639
703
|
screen.getAllByRole('gridcell', {selected: true, hidden: true}),
|
|
640
704
|
).toHaveLength(1);
|
|
705
|
+
await user.click(toggle);
|
|
641
706
|
|
|
642
707
|
await user.click(getButton('Clear Date'));
|
|
643
708
|
expect(screen.getByRole('combobox')).toHaveValue('');
|
|
644
|
-
await user.click(
|
|
709
|
+
await user.click(toggle);
|
|
645
710
|
|
|
646
711
|
expect(
|
|
647
712
|
screen.queryAllByRole('gridcell', {selected: true, hidden: true}),
|
|
@@ -1152,6 +1217,53 @@ describe('DateInput', () => {
|
|
|
1152
1217
|
expect(screen.getByDisplayValue('Mar 10, 2026')).toBeInTheDocument();
|
|
1153
1218
|
});
|
|
1154
1219
|
});
|
|
1220
|
+
describe('calendar while the popover is closed', () => {
|
|
1221
|
+
const calendarGrid = () => document.querySelector('[role="grid"]');
|
|
1222
|
+
|
|
1223
|
+
it('renders no calendar until the popover opens, and none after it closes', () => {
|
|
1224
|
+
render(<DateInput label="Date" value="2026-01-25" onChange={() => {}} />);
|
|
1225
|
+
const toggle = getButton('Open calendar');
|
|
1226
|
+
expect(calendarGrid()).toBeNull();
|
|
1227
|
+
|
|
1228
|
+
fireEvent.click(toggle);
|
|
1229
|
+
expect(calendarGrid()).not.toBeNull();
|
|
1230
|
+
|
|
1231
|
+
fireEvent.click(toggle);
|
|
1232
|
+
expect(calendarGrid()).toBeNull();
|
|
1233
|
+
});
|
|
1234
|
+
|
|
1235
|
+
it('opens on the month of a date typed while closed', () => {
|
|
1236
|
+
function Controlled() {
|
|
1237
|
+
const [value, setValue] = useState<ISODateString | undefined>(
|
|
1238
|
+
'2026-01-25',
|
|
1239
|
+
);
|
|
1240
|
+
return <DateInput label="Date" value={value} onChange={setValue} />;
|
|
1241
|
+
}
|
|
1242
|
+
render(<Controlled />);
|
|
1243
|
+
const input = screen.getByRole('combobox');
|
|
1244
|
+
|
|
1245
|
+
fireEvent.change(input, {target: {value: 'March 5, 2027'}});
|
|
1246
|
+
fireEvent.keyDown(input, {key: 'ArrowDown'});
|
|
1247
|
+
|
|
1248
|
+
expect(calendarGrid()).toHaveAccessibleName('March 2027');
|
|
1249
|
+
});
|
|
1250
|
+
|
|
1251
|
+
it('moves focus into the calendar on each open from the toggle', async () => {
|
|
1252
|
+
render(<DateInput label="Date" value="2026-01-25" onChange={() => {}} />);
|
|
1253
|
+
const toggle = getButton('Open calendar');
|
|
1254
|
+
|
|
1255
|
+
for (let i = 0; i < 2; i++) {
|
|
1256
|
+
fireEvent.click(toggle);
|
|
1257
|
+
// The first calendar control takes focus, not the dialog surface.
|
|
1258
|
+
await waitFor(() => {
|
|
1259
|
+
expect(getButton('Previous month')).toHaveFocus();
|
|
1260
|
+
});
|
|
1261
|
+
fireEvent.click(toggle);
|
|
1262
|
+
expect(calendarGrid()).toBeNull();
|
|
1263
|
+
}
|
|
1264
|
+
});
|
|
1265
|
+
});
|
|
1266
|
+
|
|
1155
1267
|
describe('weekStartsOn', () => {
|
|
1156
1268
|
// The calendar popover renders in the top layer; jsdom keeps the content in
|
|
1157
1269
|
// the DOM but role queries skip it, so read the columnheaders directly.
|