@astryxdesign/core 0.7.5 → 0.7.6-canary.0ef60dd
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/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +37 -4
- 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 +7 -3
- package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts.map +1 -1
- package/dist/DropdownMenu/MenuBottomSheetActionList.js +6 -5
- package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts +20 -2
- package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts.map +1 -1
- package/dist/DropdownMenu/lazyMenuBottomSheet.js +31 -3
- 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/Layer/popoverOperations.d.ts +27 -0
- package/dist/Layer/popoverOperations.d.ts.map +1 -0
- package/dist/Layer/popoverOperations.js +159 -0
- package/dist/Layer/useLayer.d.ts +1 -1
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +93 -59
- 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/CreateRow.a11y.chromium.spec.js +7 -6
- package/dist/MultiSelector/MultiSelector.d.ts +1 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +26 -10
- 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/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/Skeleton/Skeleton.js +1 -1
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +10 -2
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +3 -3
- 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/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +3 -0
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +1 -0
- 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 +20 -4
- 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/index.d.ts +1 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/modalAnnounce.d.ts.map +1 -1
- package/dist/hooks/modalAnnounce.js +107 -61
- package/dist/hooks/useAdaptivePresentation.d.ts.map +1 -1
- package/dist/hooks/useAdaptivePresentation.js +4 -1
- package/dist/hooks/useAnnounce.d.ts +101 -42
- package/dist/hooks/useAnnounce.d.ts.map +1 -1
- package/dist/hooks/useAnnounce.js +161 -75
- package/dist/hooks/useAnnounceRenderedText.d.ts +11 -3
- package/dist/hooks/useAnnounceRenderedText.d.ts.map +1 -1
- package/dist/hooks/useAnnounceRenderedText.js +5 -3
- package/dist/hooks/useBusyAnnouncement.d.ts.map +1 -1
- package/dist/hooks/useBusyAnnouncement.js +6 -12
- 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 +5 -0
- package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pseudo.generated.js +5 -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.d.ts +19 -5
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/defineTheme.js +64 -4
- 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/theme/index.d.ts +1 -0
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/motionKnobs.d.ts +56 -0
- package/dist/theme/motionKnobs.d.ts.map +1 -0
- package/dist/theme/motionKnobs.js +48 -0
- package/dist/theme/resolveThemeValues.d.ts +11 -4
- package/dist/theme/resolveThemeValues.d.ts.map +1 -1
- package/dist/theme/resolveThemeValues.js +40 -4
- package/dist/theme/themeAdaptations.d.ts +7 -3
- package/dist/theme/themeAdaptations.d.ts.map +1 -1
- package/dist/theme/themeAdaptations.js +36 -7
- package/dist/theme/themeMotion.d.ts +96 -0
- package/dist/theme/themeMotion.d.ts.map +1 -0
- package/dist/theme/themeMotion.js +177 -0
- package/dist/theme/tokenReferences.d.ts +31 -0
- package/dist/theme/tokenReferences.d.ts.map +1 -0
- package/dist/theme/tokenReferences.js +132 -0
- package/dist/theme/tokens.d.ts +1 -0
- package/dist/theme/tokens.d.ts.map +1 -1
- package/dist/theme/tokens.js +9 -129
- package/dist/theme/tokens.stylex.d.ts +12 -0
- package/dist/theme/tokens.stylex.d.ts.map +1 -1
- package/dist/theme/tokens.stylex.js +12 -0
- 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/interactionOverlay.stylex.d.ts.map +1 -1
- package/dist/utils/interactionOverlay.stylex.js +17 -8
- 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/pressFeedback.d.ts.map +1 -1
- package/dist/utils/pressFeedback.js +20 -1
- 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 +23 -3
- package/locales/pseudo.json +15 -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/ClickableCard/ClickableCard.test.tsx +96 -0
- package/src/ClickableCard/ClickableCard.tsx +48 -4
- 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 +10 -3
- 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 +60 -0
- package/src/DropdownMenu/lazyMenuBottomSheet.ts +36 -7
- 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/Kbd/Kbd.spec.md +81 -38
- package/src/Layer/__tests__/LayerBrowserHide.a11y.chromium.spec.ts +126 -0
- package/src/Layer/popoverOperations.test.ts +205 -0
- package/src/Layer/popoverOperations.ts +172 -0
- package/src/Layer/useLayer.test.tsx +348 -1
- package/src/Layer/useLayer.tsx +118 -71
- 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/MetadataList/MetadataList.spec.md +187 -0
- package/src/MetadataList/MetadataListItem.spec.md +165 -0
- 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/CreateRow.a11y.chromium.spec.ts +7 -8
- package/src/MultiSelector/MultiSelector.spec.md +7 -4
- package/src/MultiSelector/MultiSelector.test.tsx +270 -1
- package/src/MultiSelector/MultiSelector.tsx +25 -10
- 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/Skeleton/Skeleton.tsx +3 -1
- package/src/Slider/Slider.test.tsx +31 -0
- package/src/Slider/Slider.tsx +8 -3
- package/src/Slider/__tests__/Slider.a11y.chromium.spec.ts +19 -7
- package/src/Spinner/Spinner.tsx +5 -3
- 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/TopNav/TopNavMegaMenu.test.tsx +21 -0
- package/src/TopNav/TopNavMegaMenu.tsx +4 -1
- package/src/TopNav/TopNavMenu.test.tsx +17 -0
- package/src/TopNav/TopNavMenu.tsx +1 -0
- package/src/Typeahead/Typeahead.test.tsx +40 -0
- package/src/Typeahead/Typeahead.tsx +12 -1
- package/src/__tests__/pressState.ts +8 -4
- 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/index.ts +5 -1
- package/src/hooks/modalAnnounce.ts +129 -72
- package/src/hooks/useAdaptivePresentation.ts +4 -1
- package/src/hooks/useAnnounce.doc.mjs +35 -3
- package/src/hooks/useAnnounce.replace.test.tsx +516 -0
- package/src/hooks/useAnnounce.ts +209 -102
- package/src/hooks/useAnnounceRenderedText.adopters.test.tsx +10 -1
- package/src/hooks/useAnnounceRenderedText.ts +17 -3
- package/src/hooks/useBusyAnnouncement.ts +7 -10
- package/src/hooks/useMenuHover.ts +15 -1
- package/src/i18n/generated-locales/en.generated.ts +6 -0
- package/src/i18n/generated-locales/pseudo.generated.ts +6 -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/Theme.doc.mjs +1 -1
- package/src/theme/defineTheme.ts +117 -8
- 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/theme/expandMotionScale.test.ts +1 -1
- package/src/theme/index.ts +5 -0
- package/src/theme/motionKnobs.ts +82 -0
- package/src/theme/resolveThemeValues.ts +68 -6
- package/src/theme/themeAdaptations.ts +52 -12
- package/src/theme/themeMotion.test.ts +620 -0
- package/src/theme/themeMotion.ts +221 -0
- package/src/theme/tokenReferences.ts +149 -0
- package/src/theme/tokens.stylex.ts +10 -0
- package/src/theme/tokens.ts +15 -158
- 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/interactionOverlay.stylex.ts +12 -3
- 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/pressFeedback.test.ts +138 -0
- package/src/utils/pressFeedback.ts +34 -11
- 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
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
---
|
|
2
|
+
schema_version: 3
|
|
3
|
+
template_version: 7
|
|
4
|
+
kind: component
|
|
5
|
+
id: component:DrawerHeader
|
|
6
|
+
authority: current
|
|
7
|
+
archive_reason: null
|
|
8
|
+
superseded_by: null
|
|
9
|
+
approved_by: cixzhang
|
|
10
|
+
approved_at: 2026-10-30
|
|
11
|
+
owners: [cixzhang, imdreamrunner]
|
|
12
|
+
review_triggers: [public-api, behavior, layout, theming, accessibility]
|
|
13
|
+
verified_by:
|
|
14
|
+
[
|
|
15
|
+
packages/core/src/Drawer/DrawerHeader.test.tsx,
|
|
16
|
+
apps/storybook/stories/DrawerHeader.stories.tsx,
|
|
17
|
+
scripts/check-knowledge.mjs,
|
|
18
|
+
]
|
|
19
|
+
modules: []
|
|
20
|
+
families: [family:layout-regions]
|
|
21
|
+
design_specs: []
|
|
22
|
+
architecture:
|
|
23
|
+
[architecture:component-theming-surface, architecture:container-padding]
|
|
24
|
+
contributing: []
|
|
25
|
+
system_specs: []
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
# DrawerHeader component contract
|
|
29
|
+
|
|
30
|
+
## Contract at a glance
|
|
31
|
+
|
|
32
|
+
| Area | Contract |
|
|
33
|
+
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
34
|
+
| Public contract | `DrawerHeader` with `title`, `subtitle`, `onOpenChange`, `startContent`, `endContent`, `endContentEdgeCompensation` (`inline`, `block`, `all`), and `hasDivider`; five `drawer-header` targets. |
|
|
35
|
+
| Behavior | A Layout header row for a Drawer: optional start content, an h2 title with optional subtitle, optional end content, and a close button only when `onOpenChange` is given. |
|
|
36
|
+
| End-user impact | Users see the drawer's title and, when the caller provides one, a named close button; focus is not moved when the header mounts. |
|
|
37
|
+
| Builder impact | None. |
|
|
38
|
+
| Compatibility/readiness | Records shipped behavior; no public change. |
|
|
39
|
+
| Review checks | Reject a close button rendered without `onOpenChange`, a header that names the Drawer or moves focus on mount, or a title that is not an h2. |
|
|
40
|
+
| Governing rules | `component:Drawer` (the panel and naming); `family:layout-regions`; `architecture:component-theming-surface`. |
|
|
41
|
+
|
|
42
|
+
This table is a review projection; the body below is authoritative.
|
|
43
|
+
|
|
44
|
+
## Intent
|
|
45
|
+
|
|
46
|
+
DrawerHeader is the optional title row a caller composes in a Drawer's Layout
|
|
47
|
+
header slot. It owns the row's parts, its close button, and its targets.
|
|
48
|
+
Consumer usage lives in `DrawerHeader.doc.mjs`.
|
|
49
|
+
|
|
50
|
+
## Compatibility and migration
|
|
51
|
+
|
|
52
|
+
- Released default preserved: `yes`
|
|
53
|
+
- Compatibility class: records shipped behavior; no public change
|
|
54
|
+
- Controlled/uncontrolled behavior: the close button calls the caller's
|
|
55
|
+
`onOpenChange(false)` and owns no state
|
|
56
|
+
- Migration decision: none
|
|
57
|
+
|
|
58
|
+
Consumer migration instructions belong in consumer docs and release notes.
|
|
59
|
+
|
|
60
|
+
## Ownership boundary
|
|
61
|
+
|
|
62
|
+
**Owns**
|
|
63
|
+
|
|
64
|
+
- The header row, its slots, title semantics, close button, end-content edge
|
|
65
|
+
compensation, and five targets (FR1–FR5).
|
|
66
|
+
|
|
67
|
+
**Does not own / non-goals**
|
|
68
|
+
|
|
69
|
+
- The Drawer's name, focus entry, and open state — owned by `component:Drawer`.
|
|
70
|
+
- The header region's padding, divider default, and place in the Layout — owned
|
|
71
|
+
by `family:layout-regions` through `LayoutHeader`.
|
|
72
|
+
- The close Button — owned by `component:Button`.
|
|
73
|
+
|
|
74
|
+
## Public concepts
|
|
75
|
+
|
|
76
|
+
| Concept | Closed values or states | Meaning | Availability by variant/orientation/state | Default | Owner | Stability | Invalid-value behavior |
|
|
77
|
+
| ------------------------ | --------------------------------- | --------------------------------------------------------------------------------------------- | ----------------------------------------- | ---------------------------------------------------- | ------------------------ | --------- | -------------------------------- |
|
|
78
|
+
| End-content compensation | `inline`, `block`, `all`, omitted | Which edges of the end slot pull outward to align a trailing control with the container edge. | End slot. | Both axes when `onOpenChange` is set, none otherwise | `component:DrawerHeader` | Stable | TypeScript rejects other values. |
|
|
79
|
+
|
|
80
|
+
## Behavioral and layout contract
|
|
81
|
+
|
|
82
|
+
| ID | Invariant | Basis |
|
|
83
|
+
| --- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ |
|
|
84
|
+
| FR1 | DrawerHeader renders inside a LayoutHeader that receives `ref`, `hasDivider`, `xstyle`, `className`, `style`, and other DOM props. Its row carries `drawer-header` and shows, in order, start content, the title block, and the end slot. | Current source and tests |
|
|
85
|
+
| FR2 | The title renders as an h2; a renderable `subtitle` (including `0`) renders below it as secondary small body text, and an empty one renders nothing. Start and end slots render when their content is renderable, including `0`. | Current source and tests |
|
|
86
|
+
| FR3 | With `onOpenChange`, the end slot ends with an icon-only ghost Button named and tooltipped by `@astryx.dialog.close` that calls `onOpenChange(false)`; without it there is no close button. | Current source and tests |
|
|
87
|
+
| FR4 | The end slot pulls outward by `--spacing-2` on the block axis, the inline-end edge, or both, per `endContentEdgeCompensation`; when omitted, both apply only if there is a close button. | Current source |
|
|
88
|
+
| FR5 | The start slot, title block, end slot, and close glyph carry `drawer-header-start-content`, `drawer-header-title-block`, `drawer-header-end-content`, and `drawer-header-close-icon`. | Current source and tests |
|
|
89
|
+
| FR6 | Mounting the header does not move focus, and the header does not name the Drawer. | Current source and tests |
|
|
90
|
+
|
|
91
|
+
### Allowed variation
|
|
92
|
+
|
|
93
|
+
- **AV1 — Slots.** Start, end, and subtitle content vary or are absent.
|
|
94
|
+
|
|
95
|
+
### Representative states
|
|
96
|
+
|
|
97
|
+
| State | Required invariant | Allowed variation |
|
|
98
|
+
| ------------------- | ------------------------------------------------- | ----------------- |
|
|
99
|
+
| Title only | h2 title; no close button. | — |
|
|
100
|
+
| With `onOpenChange` | Named close button at the end; edges compensated. | End content. |
|
|
101
|
+
| Start and end slots | Order: start, title block, end. | Content. |
|
|
102
|
+
|
|
103
|
+
### Transformation and precedence order
|
|
104
|
+
|
|
105
|
+
- **ORD1 — Compensation.** `endContentEdgeCompensation`, then the close-button
|
|
106
|
+
default (FR4).
|
|
107
|
+
|
|
108
|
+
### Performance and resources
|
|
109
|
+
|
|
110
|
+
- No resource rule.
|
|
111
|
+
|
|
112
|
+
## Accessibility contract
|
|
113
|
+
|
|
114
|
+
- **AR1 — Heading.** The title is an h2.
|
|
115
|
+
- **AR2 — Close name.** FR3's translated name and tooltip.
|
|
116
|
+
- **AR3 — Focus.** FR6.
|
|
117
|
+
|
|
118
|
+
## Design relationships
|
|
119
|
+
|
|
120
|
+
| Anatomy or state | Design requirement | Representation authority | Hierarchy role | Component contract |
|
|
121
|
+
| ---------------- | --------------------------------------------- | ------------------------------ | -------------- | ------------------ |
|
|
122
|
+
| Header row | Start, title block, end in one row. | Current source and public docs | Supporting | FR1 |
|
|
123
|
+
| Start content | Leading caller content. | Current source and public docs | Supporting | FR2, FR5 |
|
|
124
|
+
| Title block | Title and optional subtitle. | Current source and public docs | Prominent | FR2, FR5 |
|
|
125
|
+
| End content | Trailing caller content and the close button. | Current source and public docs | Supporting | FR3–FR5 |
|
|
126
|
+
| Close icon | Close glyph inside the button. | Current source and public docs | Supporting | FR3, FR5 |
|
|
127
|
+
|
|
128
|
+
### Theming anatomy
|
|
129
|
+
|
|
130
|
+
<!-- anatomy-theming:v1 -->
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"Header row": {"target": "drawer-header"},
|
|
135
|
+
"Start content": {"target": "drawer-header-start-content"},
|
|
136
|
+
"Title block": {"target": "drawer-header-title-block"},
|
|
137
|
+
"End content": {"target": "drawer-header-end-content"},
|
|
138
|
+
"Close icon": {"target": "drawer-header-close-icon"}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Family and system relationships
|
|
143
|
+
|
|
144
|
+
- `component:Drawer` hosts the header in its Layout and owns naming and focus.
|
|
145
|
+
- `family:layout-regions` owns the header region it renders into.
|
|
146
|
+
|
|
147
|
+
## Verification map
|
|
148
|
+
|
|
149
|
+
| Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
|
|
150
|
+
| ------------------- | -------------------------------------------- | ---------------------------------------- | -------------------------------------------------- | ---------------------------------- |
|
|
151
|
+
| FR1, FR2, AR1 | `DrawerHeader.test.tsx` title and slot tests | Title, subtitle, `0` values, empty slots | Wrong heading level or dropped content fails. | `audit:DrawerHeader/anatomy` |
|
|
152
|
+
| FR3, AR2 | `DrawerHeader.test.tsx` close-button tests | With and without `onOpenChange` | A button without a callback, or no name, fails. | `audit:DrawerHeader/accessibility` |
|
|
153
|
+
| FR5 | `DrawerHeader.test.tsx` theming target test | All slots | A missing target fails. | `audit:DrawerHeader/theming` |
|
|
154
|
+
| FR6, AR3 | `DrawerHeader.test.tsx` focus test | Mount | Focus moved on mount fails. | `audit:DrawerHeader/accessibility` |
|
|
155
|
+
| Theming anatomy map | `scripts/check-knowledge.mjs` | Consumer anatomy and current targets | Missing, extra, or stale mappings fail validation. | `audit:DrawerHeader/theming` |
|
|
156
|
+
|
|
157
|
+
FR4 is read from source; no focused test checks it yet.
|
|
158
|
+
|
|
159
|
+
Read from source, with no focused test yet:
|
|
160
|
+
|
|
161
|
+
- FR1: `ref`, `hasDivider`, `xstyle`, `className`, `style`, and other DOM
|
|
162
|
+
props reaching the LayoutHeader.
|
|
163
|
+
- FR3: the close button's tooltip.
|
|
164
|
+
- FR4: the end slot's edge compensation.
|
|
165
|
+
- FR6: the header not naming the Drawer.
|
|
166
|
+
|
|
167
|
+
## Decision log
|
|
168
|
+
|
|
169
|
+
No component-local decision is recorded.
|
|
170
|
+
|
|
171
|
+
## Open questions
|
|
172
|
+
|
|
173
|
+
- How do `endContentEdgeCompensation`'s `inline`, `block`, and `all` axis
|
|
174
|
+
values map onto `endContentEdge` treatment values
|
|
175
|
+
(`architecture:container-padding`), and when does the old prop enter its
|
|
176
|
+
compatibility window? Today the prop stays supported as released.
|
|
177
|
+
|
|
178
|
+
## Content boundary
|
|
179
|
+
|
|
180
|
+
This file does not duplicate consumer prop tables, examples, or Drawer
|
|
181
|
+
behavior. It links to their owners.
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file DrawerNonModalPageScroll.a11y.chromium.spec.ts
|
|
5
|
+
* @input The built Drawer stories "Row Inspector" (non-modal) and "Showcase"
|
|
6
|
+
* (modal), real Chromium touch input (CDP `Input.dispatchTouchEvent`) in a
|
|
7
|
+
* phone context
|
|
8
|
+
* @output Browser evidence that under a finger the page beside an open
|
|
9
|
+
* non-modal drawer still scrolls, because the panel is no scroll container
|
|
10
|
+
* whose overscroll containment could hold the drag, while a modal drawer
|
|
11
|
+
* still holds the page behind its scrim. With `overflow: hidden` on the
|
|
12
|
+
* panel, Chromium held every such drag while the drawer was open, whether it
|
|
13
|
+
* had opened from code (a selection, a deep link, an assistive
|
|
14
|
+
* technology's click) or from a tap.
|
|
15
|
+
* @position Chromium proof for Drawer.tsx's `overflow: clip`; the declaration
|
|
16
|
+
* itself is pinned in Drawer.test.tsx
|
|
17
|
+
*
|
|
18
|
+
* Each check plays one drag, proves the page received it (a capture-phase
|
|
19
|
+
* touch probe), and measures the page by the visual viewport's place in the
|
|
20
|
+
* document, so a pan that moves only the visual viewport counts too.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import {expect, test, type Page} from '@playwright/test';
|
|
24
|
+
import {
|
|
25
|
+
DEFAULT_STORYBOOK_DIR,
|
|
26
|
+
serveStorybook,
|
|
27
|
+
type StaticServer,
|
|
28
|
+
} from '@astryxdesign/a11y-spec/storybook';
|
|
29
|
+
|
|
30
|
+
let storybook: StaticServer;
|
|
31
|
+
test.beforeAll(async () => {
|
|
32
|
+
storybook = await serveStorybook(
|
|
33
|
+
process.env.ASTRYX_STORYBOOK_DIR ?? DEFAULT_STORYBOOK_DIR,
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
test.afterAll(async () => {
|
|
37
|
+
await storybook?.close();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test.use({
|
|
41
|
+
hasTouch: true,
|
|
42
|
+
isMobile: true,
|
|
43
|
+
viewport: {width: 402, height: 714},
|
|
44
|
+
deviceScaleFactor: 1,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
/** In the strip the drawer leaves free on the phone. */
|
|
48
|
+
const STRIP_X = 20;
|
|
49
|
+
|
|
50
|
+
async function frames(page: Page, count = 2): Promise<void> {
|
|
51
|
+
await page.evaluate(async n => {
|
|
52
|
+
for (let i = 0; i < n; i++) {
|
|
53
|
+
await new Promise(resolve => requestAnimationFrame(resolve));
|
|
54
|
+
}
|
|
55
|
+
}, count);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const sleep = async (ms: number) =>
|
|
59
|
+
new Promise(resolve => {
|
|
60
|
+
setTimeout(resolve, ms);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* A finger dragging up the strip, 350 px in 200 ms at 60 Hz, then resting
|
|
65
|
+
* 150 ms before it lifts so no fling outlives the pan. Paced in real time, as
|
|
66
|
+
* a finger is: each event goes out at its own time, stamped with it.
|
|
67
|
+
*/
|
|
68
|
+
async function dragUp(page: Page): Promise<void> {
|
|
69
|
+
const cdp = await page.context().newCDPSession(page);
|
|
70
|
+
const from = 600;
|
|
71
|
+
const to = 250;
|
|
72
|
+
const steps = 12;
|
|
73
|
+
const at = (y: number) => [
|
|
74
|
+
{x: STRIP_X, y, id: 0, radiusX: 1, radiusY: 1, force: 1},
|
|
75
|
+
];
|
|
76
|
+
type Point = {
|
|
77
|
+
x: number;
|
|
78
|
+
y: number;
|
|
79
|
+
id: number;
|
|
80
|
+
radiusX: number;
|
|
81
|
+
radiusY: number;
|
|
82
|
+
force: number;
|
|
83
|
+
};
|
|
84
|
+
const send = async (
|
|
85
|
+
type: 'touchStart' | 'touchMove' | 'touchEnd',
|
|
86
|
+
touchPoints: Point[],
|
|
87
|
+
) =>
|
|
88
|
+
cdp.send('Input.dispatchTouchEvent', {
|
|
89
|
+
type,
|
|
90
|
+
touchPoints,
|
|
91
|
+
timestamp: Date.now() / 1000,
|
|
92
|
+
});
|
|
93
|
+
await send('touchStart', at(from));
|
|
94
|
+
for (let i = 1; i <= steps; i++) {
|
|
95
|
+
await sleep(200 / steps);
|
|
96
|
+
await send('touchMove', at(from + ((to - from) * i) / steps));
|
|
97
|
+
}
|
|
98
|
+
await sleep(150);
|
|
99
|
+
await send('touchEnd', []);
|
|
100
|
+
await cdp.detach();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Records every touch the page receives, and whether the browser took one to
|
|
105
|
+
* pan something (a `pointercancel`): a window capture listener added before
|
|
106
|
+
* the page's own scripts. Install it before opening the story.
|
|
107
|
+
*/
|
|
108
|
+
async function installTouchProbe(page: Page): Promise<void> {
|
|
109
|
+
await page.addInitScript(() => {
|
|
110
|
+
const seen: string[] = [];
|
|
111
|
+
(window as unknown as {__touchProbe: string[]}).__touchProbe = seen;
|
|
112
|
+
for (const type of [
|
|
113
|
+
'touchstart',
|
|
114
|
+
'touchmove',
|
|
115
|
+
'touchend',
|
|
116
|
+
'touchcancel',
|
|
117
|
+
'pointercancel',
|
|
118
|
+
]) {
|
|
119
|
+
window.addEventListener(type, () => seen.push(type), {
|
|
120
|
+
capture: true,
|
|
121
|
+
passive: true,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Plays one drag up the strip and returns what the page received: its touch
|
|
129
|
+
* events, and whether the browser took the touch to pan something. A drag the
|
|
130
|
+
* page never received shows here, so it cannot pass as one that scrolled
|
|
131
|
+
* nothing.
|
|
132
|
+
*/
|
|
133
|
+
async function playDrag(
|
|
134
|
+
page: Page,
|
|
135
|
+
): Promise<{received: string[]; panned: boolean}> {
|
|
136
|
+
const take = async () =>
|
|
137
|
+
page.evaluate(() =>
|
|
138
|
+
(window as unknown as {__touchProbe: string[]}).__touchProbe.splice(0),
|
|
139
|
+
);
|
|
140
|
+
await take();
|
|
141
|
+
await dragUp(page);
|
|
142
|
+
await frames(page, 4);
|
|
143
|
+
const seen = await take();
|
|
144
|
+
return {
|
|
145
|
+
received: seen.filter(type => type.startsWith('touch')),
|
|
146
|
+
panned: seen.includes('pointercancel'),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** The whole drag reached the page: a touchstart, its moves and its touchend. */
|
|
151
|
+
function expectDelivered(played: {received: string[]}): void {
|
|
152
|
+
expect(played.received[0], 'the drag reached the page').toBe('touchstart');
|
|
153
|
+
expect(played.received).toContain('touchmove');
|
|
154
|
+
expect(played.received.at(-1)).toBe('touchend');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Where the visual viewport is in the document. A page wider than the phone
|
|
159
|
+
* (main's story stage) lets a pan first move the visual viewport inside the
|
|
160
|
+
* layout viewport, which `window.scrollY` does not report.
|
|
161
|
+
*/
|
|
162
|
+
const pageTop = async (page: Page) =>
|
|
163
|
+
page.evaluate(() => {
|
|
164
|
+
if (window.visualViewport == null) {
|
|
165
|
+
throw new Error('the page has no visual viewport');
|
|
166
|
+
}
|
|
167
|
+
return window.visualViewport.pageTop;
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Opens the story on a page taller than the screen, checks that a drag
|
|
172
|
+
* scrolls it, then opens the drawer (with a tap, or from code: a click with no
|
|
173
|
+
* input behind it) and waits until it is in.
|
|
174
|
+
*/
|
|
175
|
+
async function openOnTallPage(
|
|
176
|
+
page: Page,
|
|
177
|
+
story: string,
|
|
178
|
+
opener: string,
|
|
179
|
+
how: 'tap' | 'code' = 'tap',
|
|
180
|
+
) {
|
|
181
|
+
await installTouchProbe(page);
|
|
182
|
+
await page.goto(`${storybook.origin}/iframe.html?id=${story}&viewMode=story`);
|
|
183
|
+
const button = page.getByRole('button', {name: opener});
|
|
184
|
+
await expect(button).toBeVisible();
|
|
185
|
+
await page.evaluate(() => {
|
|
186
|
+
const spacer = document.createElement('div');
|
|
187
|
+
spacer.style.height = '300vh';
|
|
188
|
+
document.body.append(spacer);
|
|
189
|
+
});
|
|
190
|
+
const before = await playDrag(page);
|
|
191
|
+
expectDelivered(before);
|
|
192
|
+
expect(before.panned, 'the browser took the drag to scroll').toBe(true);
|
|
193
|
+
expect(
|
|
194
|
+
await pageTop(page),
|
|
195
|
+
'the page scrolls before the drawer opens',
|
|
196
|
+
).toBeGreaterThan(0);
|
|
197
|
+
await button.evaluate(element => element.scrollIntoView({block: 'center'}));
|
|
198
|
+
await frames(page);
|
|
199
|
+
|
|
200
|
+
if (how === 'tap') {
|
|
201
|
+
await button.tap();
|
|
202
|
+
} else {
|
|
203
|
+
await button.evaluate(element => (element as HTMLElement).click());
|
|
204
|
+
}
|
|
205
|
+
const drawer = page.locator('dialog[open], dialog:popover-open');
|
|
206
|
+
await expect(drawer).toHaveCount(1);
|
|
207
|
+
await drawer.evaluate(async element => {
|
|
208
|
+
await Promise.all(
|
|
209
|
+
element.getAnimations().map(async animation =>
|
|
210
|
+
animation.finished.catch((error: unknown) => {
|
|
211
|
+
// A canceled animation's `finished` rejects with an AbortError:
|
|
212
|
+
// it ended. Anything else is a failure, and it surfaces.
|
|
213
|
+
if (!(error instanceof DOMException && error.name === 'AbortError')) {
|
|
214
|
+
throw error;
|
|
215
|
+
}
|
|
216
|
+
}),
|
|
217
|
+
),
|
|
218
|
+
);
|
|
219
|
+
});
|
|
220
|
+
await frames(page);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
for (const how of ['code', 'tap'] as const) {
|
|
224
|
+
test(`a drag on the page beside a non-modal drawer opened from ${how === 'tap' ? 'a tap' : 'code'} scrolls the page`, async ({
|
|
225
|
+
page,
|
|
226
|
+
}) => {
|
|
227
|
+
await openOnTallPage(
|
|
228
|
+
page,
|
|
229
|
+
'core-drawer--row-inspector',
|
|
230
|
+
'Open drawer',
|
|
231
|
+
how,
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
// Measured from where the open left the page: a tap scrolls the opener
|
|
235
|
+
// into view first.
|
|
236
|
+
const start = await pageTop(page);
|
|
237
|
+
const played = await playDrag(page);
|
|
238
|
+
expectDelivered(played);
|
|
239
|
+
expect(played.panned, 'the browser took the drag to scroll').toBe(true);
|
|
240
|
+
expect(await pageTop(page)).toBeGreaterThan(start);
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
test('a modal drawer still holds the page behind its scrim', async ({page}) => {
|
|
245
|
+
await openOnTallPage(page, 'core-drawer--showcase', 'Open inspector');
|
|
246
|
+
|
|
247
|
+
// Measured from where the open left the page, whatever the scroll lock
|
|
248
|
+
// reports there.
|
|
249
|
+
const start = await pageTop(page);
|
|
250
|
+
expectDelivered(await playDrag(page));
|
|
251
|
+
expect(await pageTop(page)).toBe(start);
|
|
252
|
+
await expect(
|
|
253
|
+
page.getByRole('dialog', {name: 'Deployment details'}),
|
|
254
|
+
).toBeVisible();
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
test('the story fits the phone: the page does not scroll sideways', async ({
|
|
258
|
+
page,
|
|
259
|
+
}) => {
|
|
260
|
+
await page.goto(
|
|
261
|
+
`${storybook.origin}/iframe.html?id=core-drawer--row-inspector&viewMode=story`,
|
|
262
|
+
);
|
|
263
|
+
await expect(page.getByRole('button', {name: 'Open drawer'})).toBeVisible();
|
|
264
|
+
expect(
|
|
265
|
+
await page.evaluate(() => document.documentElement.scrollWidth),
|
|
266
|
+
).toBeLessThanOrEqual(402);
|
|
267
|
+
});
|
|
@@ -127,6 +127,47 @@ describe('DropdownMenu', () => {
|
|
|
127
127
|
).not.toBeInTheDocument();
|
|
128
128
|
});
|
|
129
129
|
|
|
130
|
+
it("forwards the button's ref object to the popover trigger", () => {
|
|
131
|
+
const ref = createRef<HTMLButtonElement>();
|
|
132
|
+
render(
|
|
133
|
+
<DropdownMenu
|
|
134
|
+
button={{label: 'Project actions', ref}}
|
|
135
|
+
items={[{label: 'Edit project', onClick: vi.fn()}]}
|
|
136
|
+
/>,
|
|
137
|
+
);
|
|
138
|
+
expect(ref.current).toBe(
|
|
139
|
+
screen.getByRole('button', {name: /Project actions/}),
|
|
140
|
+
);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("forwards the button's ref object to the bottom-sheet trigger", () => {
|
|
144
|
+
const ref = createRef<HTMLButtonElement>();
|
|
145
|
+
render(
|
|
146
|
+
<DropdownMenu
|
|
147
|
+
button={{label: 'Project actions', ref}}
|
|
148
|
+
presentation="bottom-sheet"
|
|
149
|
+
items={[{label: 'Edit project', onClick: vi.fn()}]}
|
|
150
|
+
/>,
|
|
151
|
+
);
|
|
152
|
+
expect(ref.current).toBe(
|
|
153
|
+
screen.getByRole('button', {name: /Project actions/}),
|
|
154
|
+
);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("forwards the button's callback ref to the bottom-sheet trigger", () => {
|
|
158
|
+
const ref = vi.fn();
|
|
159
|
+
render(
|
|
160
|
+
<DropdownMenu
|
|
161
|
+
button={{label: 'Project actions', ref}}
|
|
162
|
+
presentation="bottom-sheet"
|
|
163
|
+
items={[{label: 'Edit project', onClick: vi.fn()}]}
|
|
164
|
+
/>,
|
|
165
|
+
);
|
|
166
|
+
expect(ref).toHaveBeenCalledWith(
|
|
167
|
+
screen.getByRole('button', {name: /Project actions/}),
|
|
168
|
+
);
|
|
169
|
+
});
|
|
170
|
+
|
|
130
171
|
it('renders data-driven actions in a bottom sheet when requested', async () => {
|
|
131
172
|
const user = userEvent.setup();
|
|
132
173
|
const onEdit = vi.fn();
|
|
@@ -67,6 +67,7 @@ import {
|
|
|
67
67
|
type DropdownMenuSurfaceValue,
|
|
68
68
|
} from './DropdownMenuContext';
|
|
69
69
|
import {useIsomorphicLayoutEffect} from '../hooks/useIsomorphicLayoutEffect';
|
|
70
|
+
import {useMergedRefs} from '../hooks/useMergedRefs';
|
|
70
71
|
import {useListFocus} from '../hooks/useListFocus';
|
|
71
72
|
import {useMenuPress} from '../hooks/useMenuPress';
|
|
72
73
|
import type {MenuPressPointerType} from '../hooks/menuPressGesture';
|
|
@@ -621,6 +622,11 @@ function DropdownMenuBottomSheet({
|
|
|
621
622
|
const button = buttonFromProps ?? {label: t(DEFAULT_BUTTON_I18N_KEY)};
|
|
622
623
|
const backLabel = t('@astryx.dropdownMenu.back');
|
|
623
624
|
const buttonRef = useRef<HTMLElement>(null);
|
|
625
|
+
// The caller's `button.ref` rides along with the sheet's own trigger ref.
|
|
626
|
+
const triggerRef = useMergedRefs<HTMLButtonElement>(
|
|
627
|
+
buttonRef as React.Ref<HTMLButtonElement>,
|
|
628
|
+
button.ref,
|
|
629
|
+
);
|
|
624
630
|
const triggerId = useId();
|
|
625
631
|
const sheetId = useId();
|
|
626
632
|
const actionListRef = useRef<HTMLDivElement>(null);
|
|
@@ -645,9 +651,10 @@ function DropdownMenuBottomSheet({
|
|
|
645
651
|
}
|
|
646
652
|
}
|
|
647
653
|
// The closed sheet renders nothing, so load its rows at rest: the first
|
|
648
|
-
// open shows the actions at once.
|
|
654
|
+
// open shows the actions at once. The preload's result says whether they
|
|
655
|
+
// loaded; after a failure the first open loads them.
|
|
649
656
|
useEffect(() => {
|
|
650
|
-
preloadMenuBottomSheetActionList();
|
|
657
|
+
void preloadMenuBottomSheetActionList();
|
|
651
658
|
}, []);
|
|
652
659
|
const currentSubmenu = submenuPath.at(-1);
|
|
653
660
|
const currentItems = currentSubmenu?.items ?? items;
|
|
@@ -806,7 +813,7 @@ function DropdownMenuBottomSheet({
|
|
|
806
813
|
) : (
|
|
807
814
|
<Button
|
|
808
815
|
{...button}
|
|
809
|
-
ref={
|
|
816
|
+
ref={triggerRef}
|
|
810
817
|
xstyle={[
|
|
811
818
|
isOpen && styles.triggerOpen,
|
|
812
819
|
button.xstyle,
|
|
@@ -647,6 +647,40 @@ describe('DropdownMenu data-driven submenus', () => {
|
|
|
647
647
|
expect(onMove).toHaveBeenCalledWith('b');
|
|
648
648
|
});
|
|
649
649
|
|
|
650
|
+
it('renders a submenu for an item with nested items inside a section', async () => {
|
|
651
|
+
const user = userEvent.setup();
|
|
652
|
+
const onWork = vi.fn();
|
|
653
|
+
render(
|
|
654
|
+
<DropdownMenu
|
|
655
|
+
button={{label: 'Share'}}
|
|
656
|
+
items={[
|
|
657
|
+
{
|
|
658
|
+
type: 'section',
|
|
659
|
+
title: 'Send',
|
|
660
|
+
items: [
|
|
661
|
+
{label: 'Copy link', onClick: () => {}},
|
|
662
|
+
{
|
|
663
|
+
label: 'Email',
|
|
664
|
+
items: [
|
|
665
|
+
{label: 'Work', onClick: onWork},
|
|
666
|
+
{label: 'Personal', onClick: () => {}},
|
|
667
|
+
],
|
|
668
|
+
},
|
|
669
|
+
],
|
|
670
|
+
},
|
|
671
|
+
]}
|
|
672
|
+
/>,
|
|
673
|
+
);
|
|
674
|
+
await user.click(screen.getByRole('button', {name: /Share/}));
|
|
675
|
+
const trigger = screen.getByRole('menuitem', {name: /Email/, hidden: true});
|
|
676
|
+
expect(trigger).toHaveAttribute('aria-haspopup', 'menu');
|
|
677
|
+
await user.click(trigger);
|
|
678
|
+
await user.click(
|
|
679
|
+
await screen.findByRole('menuitem', {name: 'Work', hidden: true}),
|
|
680
|
+
);
|
|
681
|
+
expect(onWork).toHaveBeenCalled();
|
|
682
|
+
});
|
|
683
|
+
|
|
650
684
|
it('keyboard-reaches an item positioned after a submenu row', async () => {
|
|
651
685
|
// Regression: the submenu flyout renders inline inside the root menu, so
|
|
652
686
|
// the root's item query swept in the (hidden) flyout items. Arrow nav then
|
|
@@ -11,13 +11,14 @@
|
|
|
11
11
|
|
|
12
12
|
import React, {useRef, type ReactElement} from 'react';
|
|
13
13
|
import * as stylex from '@stylexjs/stylex';
|
|
14
|
-
import {Divider} from '../Divider';
|
|
15
|
-
import {Heading} from '../Heading';
|
|
16
|
-
import {Icon, renderIconSlot} from '../Icon';
|
|
17
|
-
import {List
|
|
14
|
+
import {Divider} from '../Divider/Divider';
|
|
15
|
+
import {Heading} from '../Heading/Heading';
|
|
16
|
+
import {Icon, renderIconSlot} from '../Icon/Icon';
|
|
17
|
+
import {List} from '../List/List';
|
|
18
|
+
import {ListItem} from '../List/ListItem';
|
|
18
19
|
import {useMenuPress} from '../hooks/useMenuPress';
|
|
19
20
|
import {colorVars, spacingVars} from '../theme/tokens.stylex';
|
|
20
|
-
import {rtlStyles} from '../utils';
|
|
21
|
+
import {rtlStyles} from '../utils/rtlStyles';
|
|
21
22
|
import {getInteractionModality} from '../utils/interactionModality';
|
|
22
23
|
import type {DropdownMenuItemData, DropdownMenuOption} from './DropdownMenu';
|
|
23
24
|
import {isModifiedClick} from './menuItemRoles';
|
|
@@ -120,16 +120,28 @@ async function runState(
|
|
|
120
120
|
});
|
|
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 menu expectation is exercised by a DropdownMenu state', () => {
|
|
127
|
+
test.describe.configure({mode: 'serial'});
|
|
127
128
|
const results: BindingResult[] = [];
|
|
129
|
+
|
|
128
130
|
for (const state of MENU_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
|
+
MENU_BINDING_STATES.map(state => state.id).sort(),
|
|
141
|
+
);
|
|
142
|
+
expect(neverExercised(results)).toEqual([]);
|
|
143
|
+
expect(unmatchedKnownFailures(MENU_KNOWN_FAILURES, results)).toEqual([]);
|
|
144
|
+
});
|
|
133
145
|
});
|
|
134
146
|
|
|
135
147
|
for (const state of MENU_BINDING_STATES) {
|
|
@@ -107,18 +107,30 @@ async function runState(
|
|
|
107
107
|
});
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
// Checking coverage runs every state again, which on a loaded runner nears
|
|
111
|
+
// the per-test timeout as one test. It runs as one serial part per state,
|
|
112
|
+
// sharing their results, then one check over all of them.
|
|
113
|
+
test.describe('every menu-button expectation is exercised by a DropdownMenu or MoreMenu state', () => {
|
|
114
|
+
test.describe.configure({mode: 'serial'});
|
|
114
115
|
const results: BindingResult[] = [];
|
|
116
|
+
|
|
115
117
|
for (const state of MENU_BUTTON_BINDING_STATES) {
|
|
116
|
-
|
|
118
|
+
test(`runs ${state.id}`, async ({page}) => {
|
|
119
|
+
const cdp = await page.context().newCDPSession(page);
|
|
120
|
+
results.push(await runState(page, cdp, state));
|
|
121
|
+
});
|
|
117
122
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
123
|
+
|
|
124
|
+
test('no expectation is left unexercised', () => {
|
|
125
|
+
// Every part ran in this worker; this test alone proves nothing.
|
|
126
|
+
expect(results.map(result => result.state).sort()).toEqual(
|
|
127
|
+
MENU_BUTTON_BINDING_STATES.map(state => state.id).sort(),
|
|
128
|
+
);
|
|
129
|
+
expect(neverExercised(results)).toEqual([]);
|
|
130
|
+
expect(unmatchedKnownFailures(MENU_BUTTON_KNOWN_FAILURES, results)).toEqual(
|
|
131
|
+
[],
|
|
132
|
+
);
|
|
133
|
+
});
|
|
122
134
|
});
|
|
123
135
|
|
|
124
136
|
for (const state of MENU_BUTTON_BINDING_STATES) {
|