@hanzogui/kitchen-sink 3.0.5
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/.detoxrc.js +130 -0
- package/.env.production +2 -0
- package/.maestro/config.yaml +4 -0
- package/.maestro/flows/shorthand-variables.yaml +23 -0
- package/.watchmanconfig +1 -0
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/app.json +43 -0
- package/assets/adaptive-icon.png +0 -0
- package/assets/favicon.png +0 -0
- package/assets/icon.png +0 -0
- package/assets/splash.png +0 -0
- package/babel.config.js +25 -0
- package/e2e/CompilerExtraction.test.ts +147 -0
- package/e2e/GroupPressNative.test.ts +167 -0
- package/e2e/MediaQueryGtMd.test.ts +71 -0
- package/e2e/NativePortal.test.ts +113 -0
- package/e2e/PointerEvents.test.ts +116 -0
- package/e2e/PressStyleNative.noRngh.test.ts +191 -0
- package/e2e/PressStyleNative.test.ts +231 -0
- package/e2e/SafeArea.test.ts +57 -0
- package/e2e/SelectAndroidOnPress.test.ts +181 -0
- package/e2e/SelectRemount.test.ts +137 -0
- package/e2e/SheetDragResist.test.ts +370 -0
- package/e2e/SheetKeyboardDrag.test.ts +249 -0
- package/e2e/SheetScrollableDrag.test.ts +560 -0
- package/e2e/ShorthandVariables.test.ts +53 -0
- package/e2e/ThemeChangeBasic.test.ts +123 -0
- package/e2e/ThemeMutation.test.ts +80 -0
- package/e2e/check-rngh-status.test.ts +31 -0
- package/e2e/jest.config.js +19 -0
- package/e2e/utils/colors.ts +75 -0
- package/e2e/utils/navigation.ts +53 -0
- package/eas.json +22 -0
- package/flows/AlertDialog.yaml +17 -0
- package/flows/OpenApp.yaml +25 -0
- package/flows/Select.yaml +13 -0
- package/flows/Sheet.yaml +12 -0
- package/flows/Tabs.yaml +13 -0
- package/flows/Toast.yaml +14 -0
- package/flows/WarmUp.yaml +24 -0
- package/index.html +21 -0
- package/index.js +17 -0
- package/metro.config.js +64 -0
- package/next-router-shim.ts +9 -0
- package/package.json +118 -0
- package/plans/toast-2.md +471 -0
- package/playwright.config.ts +71 -0
- package/plugins/expo-modules-core-swift6.js +76 -0
- package/pod-install.sh +7 -0
- package/public/favicon.svg +70 -0
- package/public/fonts/inter.css +15 -0
- package/public/fonts/noto-cn.otf +0 -0
- package/public/gui-icon.svg +68 -0
- package/run-detox.sh +230 -0
- package/run-native-tests.sh +4 -0
- package/run-tests-parallel.ts +195 -0
- package/screenshots/Screenshotter.test.tsx +48 -0
- package/src/AnimationDemos.tsx +131 -0
- package/src/App.native.tsx +121 -0
- package/src/App.tsx +121 -0
- package/src/Navigation.tsx +98 -0
- package/src/Sandbox.tsx +87 -0
- package/src/TestDynamicEval.tsx +33 -0
- package/src/TestNativeSheet.tsx +100 -0
- package/src/components/TimedRender.tsx +18 -0
- package/src/constants/test-ids.ts +52 -0
- package/src/features/demos/demo-screen.tsx +72 -0
- package/src/features/home/ColorSchemeListItem.tsx +41 -0
- package/src/features/home/TestBuildAButton.tsx +102 -0
- package/src/features/home/TestSeparator.tsx +0 -0
- package/src/features/home/screen.tsx +285 -0
- package/src/features/testcases/screen.tsx +59 -0
- package/src/features/testcases/test-screen.tsx +50 -0
- package/src/generatedV5Theme.ts +112 -0
- package/src/gui.config.ts +411 -0
- package/src/guy.png +0 -0
- package/src/index.tsx +6 -0
- package/src/provider/index.tsx +18 -0
- package/src/test-gui-stack.tsx +11 -0
- package/src/test.tsx +3 -0
- package/src/useKitchenSinkTheme.tsx +15 -0
- package/src/usecases/ActionsSheetComparison.tsx +194 -0
- package/src/usecases/AnimatePresenceEnterExitCase.tsx +255 -0
- package/src/usecases/AnimatePresenceExitTest.tsx +69 -0
- package/src/usecases/AnimatedByProp.tsx +39 -0
- package/src/usecases/AnimationComprehensiveCase.tsx +2515 -0
- package/src/usecases/AnimationValueLoggingCase.tsx +526 -0
- package/src/usecases/AnimationsWithMediaQueriesCase.tsx +110 -0
- package/src/usecases/Benchmark.tsx +148 -0
- package/src/usecases/BenchmarkSelect.tsx +34 -0
- package/src/usecases/ButtonCircular.tsx +3 -0
- package/src/usecases/ButtonCustom.tsx +33 -0
- package/src/usecases/ButtonIconColor.tsx +18 -0
- package/src/usecases/ButtonInverse.tsx +30 -0
- package/src/usecases/ButtonUnstyled.tsx +31 -0
- package/src/usecases/CheckboxDisabledOnPress.tsx +62 -0
- package/src/usecases/ClickDuringEnterCase.tsx +59 -0
- package/src/usecases/CodeExamplesInput.tsx +9 -0
- package/src/usecases/ColorTokenFallback.tsx +52 -0
- package/src/usecases/CompilerExtraction.tsx +380 -0
- package/src/usecases/ComplexVariants.tsx +164 -0
- package/src/usecases/CrashAdaptSheet.tsx +98 -0
- package/src/usecases/CustomStyledAnimatedPopover.tsx +42 -0
- package/src/usecases/CustomStyledAnimatedTooltip.tsx +72 -0
- package/src/usecases/DOMNodeAPIs.tsx +154 -0
- package/src/usecases/DialogFocusScopeCase.tsx +277 -0
- package/src/usecases/DialogFocusScopeDebug.tsx +85 -0
- package/src/usecases/DialogNestedCase.tsx +121 -0
- package/src/usecases/DialogOpenControlled.tsx +49 -0
- package/src/usecases/DialogPointerEventsCase.tsx +58 -0
- package/src/usecases/DialogScopedCase.tsx +106 -0
- package/src/usecases/DialogSheetAdaptCase.tsx +178 -0
- package/src/usecases/DialogSheetAdaptResizeCase.tsx +98 -0
- package/src/usecases/DismissLayerStackingCase.tsx +223 -0
- package/src/usecases/DriverDisableAnimationPropsCase.tsx +44 -0
- package/src/usecases/Example.tsx +10 -0
- package/src/usecases/ExitCompletionCase.tsx +713 -0
- package/src/usecases/FocusVisibleButton.tsx +14 -0
- package/src/usecases/FocusVisibleButtonPointer.tsx +13 -0
- package/src/usecases/FocusVisibleButtonWithFocusStyle.tsx +16 -0
- package/src/usecases/FocusWithinCase.tsx +55 -0
- package/src/usecases/FontTokensInVariants.tsx +14 -0
- package/src/usecases/FormButtonTypeCase.tsx +34 -0
- package/src/usecases/GlobalScopedTriggerIsolationCase.tsx +178 -0
- package/src/usecases/GroupHoverMobile.tsx +39 -0
- package/src/usecases/GroupPressInVariant.tsx +92 -0
- package/src/usecases/GroupPressNative.tsx +200 -0
- package/src/usecases/GroupProp.tsx +96 -0
- package/src/usecases/GroupPseudoVariantOverride.tsx +56 -0
- package/src/usecases/GroupUseCases.tsx +94 -0
- package/src/usecases/HeightMediaQueryOverrideCase.tsx +183 -0
- package/src/usecases/InputAutoFocusAfterMenuCase.tsx +105 -0
- package/src/usecases/InputAutoFocusStyledCase.tsx +39 -0
- package/src/usecases/KeyboardControllerTest.tsx +146 -0
- package/src/usecases/ListItem.tsx +123 -0
- package/src/usecases/MediaQueriesV5.tsx +137 -0
- package/src/usecases/MediaQueryGtMd.tsx +73 -0
- package/src/usecases/MenuAboveDialogCase.tsx +75 -0
- package/src/usecases/MenuAccessibilityCase.tsx +133 -0
- package/src/usecases/MenuAnimatePositionCase.tsx +41 -0
- package/src/usecases/MenuArrowAnimatePresenceCase.tsx +98 -0
- package/src/usecases/MenuAsChildPositionCase.tsx +24 -0
- package/src/usecases/MenuAutoResizeCase.tsx +57 -0
- package/src/usecases/MenuBottomCase.tsx +55 -0
- package/src/usecases/MenuFocusLeaveCase.tsx +135 -0
- package/src/usecases/MenuHighlightCase.tsx +44 -0
- package/src/usecases/MenuItemFocusCase.tsx +79 -0
- package/src/usecases/MenuItemPseudoOverrideCase.tsx +270 -0
- package/src/usecases/MenuMultiTriggerCase.tsx +47 -0
- package/src/usecases/MenuOverflowCase.tsx +60 -0
- package/src/usecases/MenuSubCase.tsx +223 -0
- package/src/usecases/MenuSubLeftCase.tsx +178 -0
- package/src/usecases/MenuSubNestedPositionCase.tsx +171 -0
- package/src/usecases/MenuSubStyledCase.tsx +145 -0
- package/src/usecases/MenuThemeCase.tsx +50 -0
- package/src/usecases/MenuUnstyledCase.tsx +52 -0
- package/src/usecases/MultiDriverAnimation.tsx +118 -0
- package/src/usecases/NativePortalTest.tsx +179 -0
- package/src/usecases/NewInputBasic.tsx +16 -0
- package/src/usecases/NewInputEvents.tsx +29 -0
- package/src/usecases/NonGuiTextStyledType.tsx +23 -0
- package/src/usecases/OnLayoutCase.tsx +134 -0
- package/src/usecases/OnLayoutScaleCase.tsx +88 -0
- package/src/usecases/OnLayoutStressCase.tsx +353 -0
- package/src/usecases/OpacityModifierCase.tsx +113 -0
- package/src/usecases/OverlayStyled.tsx +66 -0
- package/src/usecases/ParagraphSpanFontInheritance.tsx +53 -0
- package/src/usecases/PlaceholderTextColor.tsx +20 -0
- package/src/usecases/PointerEventsCase.tsx +100 -0
- package/src/usecases/PopoverAndMenuMultiTriggerCase.tsx +138 -0
- package/src/usecases/PopoverCase.tsx +222 -0
- package/src/usecases/PopoverContentStyledPlusAnimations.tsx +44 -0
- package/src/usecases/PopoverFocusScopeCase.tsx +171 -0
- package/src/usecases/PopoverHoverableCase.tsx +167 -0
- package/src/usecases/PopoverHoverableDisableClickCase.tsx +118 -0
- package/src/usecases/PopoverHoverableRapidCase.tsx +103 -0
- package/src/usecases/PopoverHoverableScopedCase.tsx +135 -0
- package/src/usecases/PopoverScopedCase.tsx +76 -0
- package/src/usecases/PopoverTriggerIsolationCase.tsx +80 -0
- package/src/usecases/PressStyleNative.tsx +143 -0
- package/src/usecases/PseudoStyleMerge.tsx +25 -0
- package/src/usecases/PseudoTransitionCase.tsx +174 -0
- package/src/usecases/RawAnimatedValueCase.tsx +231 -0
- package/src/usecases/RemoveScrollCase.tsx +66 -0
- package/src/usecases/RenderPropCase.tsx +263 -0
- package/src/usecases/SafeAreaCase.tsx +236 -0
- package/src/usecases/ScrollViewRefCase.tsx +88 -0
- package/src/usecases/SecondPage.tsx +5 -0
- package/src/usecases/SelectAndroidOnPress.tsx +129 -0
- package/src/usecases/SelectFocusScopeCase.tsx +270 -0
- package/src/usecases/SelectRemount.tsx +136 -0
- package/src/usecases/Shadows.tsx +5 -0
- package/src/usecases/SheetAnimationCase.tsx +155 -0
- package/src/usecases/SheetDragCase.tsx +183 -0
- package/src/usecases/SheetDragResistCase.tsx +433 -0
- package/src/usecases/SheetDragResistCase.web.tsx +359 -0
- package/src/usecases/SheetKeyboardDragCase.tsx +328 -0
- package/src/usecases/SheetKeyboardFitContentCase.tsx +165 -0
- package/src/usecases/SheetOnAnimationCompleteCase.tsx +54 -0
- package/src/usecases/SheetScrollLockCase.tsx +166 -0
- package/src/usecases/SheetScrollableDrag.tsx +249 -0
- package/src/usecases/SheetSnapPointsFitCase.tsx +393 -0
- package/src/usecases/ShorthandVariables.tsx +49 -0
- package/src/usecases/SlowThemeReRender.tsx +48 -0
- package/src/usecases/SpinnerCustomColors.tsx +34 -0
- package/src/usecases/StackZIndex.tsx +82 -0
- package/src/usecases/StressPage.tsx +301 -0
- package/src/usecases/StylePlatform.tsx +30 -0
- package/src/usecases/StyleProp.tsx +29 -0
- package/src/usecases/StyledAnchor.tsx +27 -0
- package/src/usecases/StyledButtonAnimationAuto.tsx +99 -0
- package/src/usecases/StyledButtonTheme.tsx +63 -0
- package/src/usecases/StyledButtonVariantPseudo.tsx +25 -0
- package/src/usecases/StyledButtonVariantPseudoMerge.tsx +77 -0
- package/src/usecases/StyledCheckboxTheme.tsx +23 -0
- package/src/usecases/StyledContextColor.tsx +246 -0
- package/src/usecases/StyledContextTokens.tsx +147 -0
- package/src/usecases/StyledHOCNamed.tsx +20 -0
- package/src/usecases/StyledHtmlCase.tsx +144 -0
- package/src/usecases/StyledIconColor.tsx +19 -0
- package/src/usecases/StyledInputFocusStyle.tsx +21 -0
- package/src/usecases/StyledInputOnFocus.tsx +30 -0
- package/src/usecases/StyledMediaQueryMerge.tsx +95 -0
- package/src/usecases/StyledOverridePsuedo.tsx +26 -0
- package/src/usecases/StyledRNW.tsx +61 -0
- package/src/usecases/StyledStyleableInputOnFocus.tsx +34 -0
- package/src/usecases/StyledStyleableInputVariant.tsx +48 -0
- package/src/usecases/StyledStyledStyleableInputOnFocus.tsx +36 -0
- package/src/usecases/StyledVariantTextColor.tsx +25 -0
- package/src/usecases/StyledViewOnFocus.tsx +32 -0
- package/src/usecases/TabHoverAnimationCase.tsx +212 -0
- package/src/usecases/TextNestedInheritance.tsx +80 -0
- package/src/usecases/ThemeChange.tsx +100 -0
- package/src/usecases/ThemeChangeBasic.tsx +52 -0
- package/src/usecases/ThemeComponentResolution.tsx +119 -0
- package/src/usecases/ThemeConditionalName.tsx +31 -0
- package/src/usecases/ThemeMediaAnimationCase.tsx +39 -0
- package/src/usecases/ThemeMutation.tsx +86 -0
- package/src/usecases/ThemeNested.tsx +103 -0
- package/src/usecases/ThemeReset.tsx +62 -0
- package/src/usecases/ThemeShallowCase.tsx +83 -0
- package/src/usecases/ToastCase.tsx +46 -0
- package/src/usecases/ToggleGroupActiveProps.tsx +40 -0
- package/src/usecases/ToggleGroupXGroupCase.tsx +104 -0
- package/src/usecases/TooltipAnimationCase.tsx +99 -0
- package/src/usecases/TooltipCase.tsx +32 -0
- package/src/usecases/TooltipGlobalPatternCase.tsx +83 -0
- package/src/usecases/TooltipGroupCase.tsx +102 -0
- package/src/usecases/TooltipMultiTriggerCase.tsx +88 -0
- package/src/usecases/TooltipPositionJumpCase.tsx +91 -0
- package/src/usecases/TooltipTriggerInlineCase.tsx +60 -0
- package/src/usecases/TransformMediaQueryMerge.tsx +98 -0
- package/src/usecases/UseCases.tsx +409 -0
- package/src/usecases/UseTheme.tsx +41 -0
- package/src/usecases/V5ThemeBuilderOutput.tsx +231 -0
- package/src/usecases/VariantFontFamily.tsx +25 -0
- package/src/usecases/VariantsOrder.tsx +117 -0
- package/src/usecases/ZIndex.tsx +155 -0
- package/src/usecases/helpers.tsx +44 -0
- package/src/usecases/index.native.ts +122 -0
- package/src/usecases/index.ts +3 -0
- package/src/usecases/index.web.ts +177 -0
- package/tests/AnimatePresenceEnterExit.animated.test.tsx +176 -0
- package/tests/AnimatedByProp.animated.test.tsx +138 -0
- package/tests/AnimationBehavior.animated.test.tsx +543 -0
- package/tests/AnimationTiming.animated.test.tsx +195 -0
- package/tests/AnimationsWithMediaQueries.animated.test.tsx +154 -0
- package/tests/BuildAButton.test.tsx +87 -0
- package/tests/ButtonCircular.test.tsx +17 -0
- package/tests/ButtonCustom.test.tsx +17 -0
- package/tests/ButtonIconColor.test.tsx +23 -0
- package/tests/ButtonUnstyled.test.tsx +56 -0
- package/tests/ClickDuringEnter.animated.test.tsx +174 -0
- package/tests/ColorTokenFallback.test.tsx +45 -0
- package/tests/DOMNodeAPIs.test.tsx +161 -0
- package/tests/DialogFocusScope.animated.test.tsx +309 -0
- package/tests/DialogNested.test.tsx +128 -0
- package/tests/DialogOpenControlled.test.tsx +42 -0
- package/tests/DialogPointerEvents.animated.test.tsx +108 -0
- package/tests/DialogScoped.test.tsx +137 -0
- package/tests/DialogSheetAdapt.test.tsx +68 -0
- package/tests/DialogSheetAdaptResize.test.tsx +161 -0
- package/tests/DismissLayerStacking.test.tsx +292 -0
- package/tests/DriverDisableAnimationProps.animated.test.tsx +157 -0
- package/tests/ExitCompletion.animated.test.tsx +425 -0
- package/tests/ExitTimingCheck.animated.test.ts +34 -0
- package/tests/FocusVisibleButton.test.tsx +41 -0
- package/tests/FocusVisibleButtonPointerFocus.test.tsx +23 -0
- package/tests/FocusVisibleButtonPointerFocusWithFocusStyle.test.tsx +40 -0
- package/tests/FocusWithinStyle.animated.test.tsx +66 -0
- package/tests/FocusWithinStyle.test.tsx +60 -0
- package/tests/FormButtonType.test.tsx +42 -0
- package/tests/GlobalScopedTriggerIsolation.test.tsx +89 -0
- package/tests/GroupHoverMobile.test.tsx +52 -0
- package/tests/GroupPressInVariant.test.tsx +82 -0
- package/tests/GroupProp.test.tsx +30 -0
- package/tests/GroupPseudoVariantOverride.test.tsx +57 -0
- package/tests/GroupUseCases.test.tsx +111 -0
- package/tests/GuiSiteMotion.test.ts +481 -0
- package/tests/HeightMediaQueryOverride.test.tsx +112 -0
- package/tests/InputAutoFocusAfterMenu.test.tsx +55 -0
- package/tests/InputAutoFocusStyled.test.tsx +22 -0
- package/tests/ListItem.test.tsx +129 -0
- package/tests/MediaQueriesV5.test.tsx +113 -0
- package/tests/MediaQueryGtMd.test.tsx +84 -0
- package/tests/MenuAboveDialog.test.tsx +108 -0
- package/tests/MenuAccessibility.test.tsx +346 -0
- package/tests/MenuAnimatePosition.animated.test.tsx +57 -0
- package/tests/MenuArrowAnimatePresence.animated.test.tsx +71 -0
- package/tests/MenuAsChildPosition.test.tsx +16 -0
- package/tests/MenuAutoResize.test.tsx +54 -0
- package/tests/MenuFocusLeave.test.tsx +181 -0
- package/tests/MenuHighlight.test.tsx +165 -0
- package/tests/MenuHoverKeyboardBugs.test.tsx +252 -0
- package/tests/MenuItemFocus.test.tsx +59 -0
- package/tests/MenuItemPseudoOverride.test.tsx +231 -0
- package/tests/MenuMultiTrigger.test.tsx +101 -0
- package/tests/MenuOverflow.test.tsx +93 -0
- package/tests/MenuStayInFrame.test.tsx +102 -0
- package/tests/MenuSubKeyboardFocus.test.tsx +220 -0
- package/tests/MenuSubLeftSafePolygon.test.tsx +88 -0
- package/tests/MenuSubNestedPosition.test.tsx +48 -0
- package/tests/MenuSubSafePolygon.test.tsx +97 -0
- package/tests/MenuSubStyled.test.tsx +40 -0
- package/tests/MenuTheme.test.tsx +34 -0
- package/tests/MenuUnstyled.test.tsx +56 -0
- package/tests/MultiDriverAnimation.test.tsx +207 -0
- package/tests/NewInputBasic.test.tsx +50 -0
- package/tests/NewInputEvents.test.tsx +55 -0
- package/tests/OnLayout.test.tsx +163 -0
- package/tests/OnLayoutScale.test.tsx +100 -0
- package/tests/OnLayoutStress.test.tsx +304 -0
- package/tests/ParagraphSpanFontInheritance.test.tsx +73 -0
- package/tests/PointerEvents.test.tsx +123 -0
- package/tests/Popover.animated.test.tsx +234 -0
- package/tests/PopoverAndMenuMultiTrigger.test.tsx +184 -0
- package/tests/PopoverAnimatePosition.animated.test.tsx +51 -0
- package/tests/PopoverClickDuringEnter.animated.test.tsx +197 -0
- package/tests/PopoverFocusScope.test.tsx +242 -0
- package/tests/PopoverHoverable.test.tsx +383 -0
- package/tests/PopoverHoverableDisableClick.test.tsx +106 -0
- package/tests/PopoverHoverableRapid.test.tsx +129 -0
- package/tests/PopoverHoverableReposition.test.tsx +111 -0
- package/tests/PopoverHoverableScoped.animated.test.tsx +103 -0
- package/tests/PopoverHoverableStress.test.tsx +169 -0
- package/tests/PopoverInitialPosition.animated.test.tsx +82 -0
- package/tests/PopoverMiddlewareSkipRegression.animated.test.tsx +221 -0
- package/tests/PopoverScoped.test.tsx +128 -0
- package/tests/PopoverScopedPositionGlitch.animated.test.tsx +184 -0
- package/tests/PopoverTriggerIsolation.test.tsx +62 -0
- package/tests/PseudoTransition.animated.test.tsx +319 -0
- package/tests/RawAnimatedValue.test.tsx +147 -0
- package/tests/RemoveScroll.test.tsx +223 -0
- package/tests/RenderProp.test.tsx +293 -0
- package/tests/ScrollViewRef.test.tsx +39 -0
- package/tests/SelectClickHold.test.tsx +147 -0
- package/tests/SelectFocusScope.test.tsx +176 -0
- package/tests/SelectInnerPositioning.test.tsx +82 -0
- package/tests/SelectKeyboardNav.test.tsx +173 -0
- package/tests/SelectPositioning.test.tsx +56 -0
- package/tests/SelectTypeahead.test.tsx +63 -0
- package/tests/Shadows.test.tsx +14 -0
- package/tests/SheetAnimation.animated.test.tsx +413 -0
- package/tests/SheetDrag.animated.test.tsx +223 -0
- package/tests/SheetDragResist.animated.test.tsx +393 -0
- package/tests/SheetOnAnimationComplete.animated.test.tsx +62 -0
- package/tests/SheetScrollLock.animated.test.tsx +287 -0
- package/tests/SheetScrollableDrag.animated.test.tsx +1264 -0
- package/tests/SheetSnapPointsFit.animated.test.tsx +259 -0
- package/tests/ShorthandVariables.test.tsx +44 -0
- package/tests/SpinnerCustomColors.test.tsx +67 -0
- package/tests/StackZIndex.test.tsx +51 -0
- package/tests/StressPagePerf.test.tsx +76 -0
- package/tests/StylePlatform.test.tsx +38 -0
- package/tests/StyleProp.test.tsx +20 -0
- package/tests/StyledAnchor.test.tsx +17 -0
- package/tests/StyledButtonTheme.test.tsx +22 -0
- package/tests/StyledButtonVariantPseudo.test.tsx +20 -0
- package/tests/StyledButtonVariantPseudoMerge.animated.test.tsx +33 -0
- package/tests/StyledCheckboxTheme.test.tsx +16 -0
- package/tests/StyledContextColor.test.tsx +119 -0
- package/tests/StyledContextTokens.test.tsx +56 -0
- package/tests/StyledHOCNamed.test.tsx +16 -0
- package/tests/StyledHtml.test.tsx +161 -0
- package/tests/StyledIconColor.test.tsx +32 -0
- package/tests/StyledInputFocusStyle.test.tsx +19 -0
- package/tests/StyledInputOnFocus.test.tsx +27 -0
- package/tests/StyledMediaQueryMerge.test.tsx +66 -0
- package/tests/StyledRNW.test.tsx +17 -0
- package/tests/StyledStyleableInputOnFocus.test.tsx +27 -0
- package/tests/StyledStyleableInputVariant.test.tsx +22 -0
- package/tests/StyledStyledStyleableInputOnFocus.test.tsx +27 -0
- package/tests/StyledVariantTextColor.test.tsx +24 -0
- package/tests/StyledViewOnFocus.test.tsx +27 -0
- package/tests/TabHoverAnimation.animated.test.tsx +468 -0
- package/tests/TabHoverPositionSmooth.animated.test.tsx +129 -0
- package/tests/TextNestedInheritance.test.tsx +93 -0
- package/tests/ThemeChange.test.tsx +70 -0
- package/tests/ThemeComponentResolution.test.tsx +82 -0
- package/tests/ThemeConditionalName.test.tsx +34 -0
- package/tests/ThemeMediaAnimation.test.tsx +65 -0
- package/tests/ThemeNested.test.tsx +141 -0
- package/tests/ThemeReset.test.tsx +63 -0
- package/tests/ThemeShallow.test.tsx +95 -0
- package/tests/Toast.test.tsx +106 -0
- package/tests/ToggleGroup.test.tsx +61 -0
- package/tests/ToggleGroupActiveProps.test.tsx +38 -0
- package/tests/ToggleGroupXGroup.test.tsx +172 -0
- package/tests/TooltipAnimation.animated.test.tsx +260 -0
- package/tests/TooltipEnterInterrupt.animated.test.tsx +76 -0
- package/tests/TooltipGlobalPattern.animated.test.tsx +208 -0
- package/tests/TooltipGroup.animated.test.tsx +79 -0
- package/tests/TooltipMultiTrigger.test.tsx +116 -0
- package/tests/TooltipPositionJump.animated.test.tsx +229 -0
- package/tests/TooltipPositionJumpNotes.md +219 -0
- package/tests/TooltipRapidSwitch.animated.test.tsx +399 -0
- package/tests/TooltipTriggerInline.test.tsx +65 -0
- package/tests/TransformMediaQueryMerge.test.tsx +104 -0
- package/tests/TransitionEnterExit.animated.test.tsx +311 -0
- package/tests/UseTheme.test.tsx +16 -0
- package/tests/V5ThemeBuilderOutput.test.tsx +164 -0
- package/tests/VariantFontFamily.test.tsx +11 -0
- package/tests/VariantsOrder.test.tsx +53 -0
- package/tests/_debug_position.mjs +52 -0
- package/tests/test-utils.ts +106 -0
- package/tests/utils.tsx +54 -0
- package/tsconfig.json +45 -0
- package/vite-env.d.ts +1 -0
- package/vite.config.ts +14 -0
- package/webpack.config.js +139 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
|
|
3
|
+
import { setupPage } from './test-utils'
|
|
4
|
+
|
|
5
|
+
test.describe('Menu Submenu Keyboard Focus', () => {
|
|
6
|
+
test.beforeEach(async ({ page }) => {
|
|
7
|
+
await setupPage(page, { name: 'MenuAccessibilityCase', type: 'useCase' })
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
test('submenu trigger should have focusVisible style when opened via ArrowRight', async ({
|
|
11
|
+
page,
|
|
12
|
+
}) => {
|
|
13
|
+
await page.waitForLoadState('networkidle')
|
|
14
|
+
|
|
15
|
+
// open menu via keyboard
|
|
16
|
+
const trigger = page.getByTestId('menu-trigger')
|
|
17
|
+
await trigger.focus()
|
|
18
|
+
await page.keyboard.press('Enter')
|
|
19
|
+
await page.waitForTimeout(300)
|
|
20
|
+
|
|
21
|
+
const menuContent = page.getByTestId('menu-content')
|
|
22
|
+
await expect(menuContent).toBeVisible()
|
|
23
|
+
|
|
24
|
+
// navigate to submenu trigger via keyboard
|
|
25
|
+
const submenuTrigger = page.getByTestId('submenu-trigger')
|
|
26
|
+
await submenuTrigger.focus()
|
|
27
|
+
await expect(submenuTrigger).toBeFocused()
|
|
28
|
+
|
|
29
|
+
// press ArrowRight to open submenu
|
|
30
|
+
await page.keyboard.press('ArrowRight')
|
|
31
|
+
await page.waitForTimeout(300)
|
|
32
|
+
|
|
33
|
+
const submenuContent = page.getByTestId('submenu-content')
|
|
34
|
+
await expect(submenuContent).toBeVisible()
|
|
35
|
+
|
|
36
|
+
// the first submenu item should be focused AND have focusVisible
|
|
37
|
+
const firstSubmenuItem = page.getByTestId('submenu-item-1')
|
|
38
|
+
await expect(firstSubmenuItem).toBeFocused()
|
|
39
|
+
|
|
40
|
+
// check that the focused item has the data-highlighted attribute (indicates focus style)
|
|
41
|
+
const hasHighlight = await firstSubmenuItem.getAttribute('data-highlighted')
|
|
42
|
+
expect(hasHighlight).toBe('')
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test('submenu trigger should have focusVisible style when opened via Enter', async ({
|
|
46
|
+
page,
|
|
47
|
+
}) => {
|
|
48
|
+
await page.waitForLoadState('networkidle')
|
|
49
|
+
|
|
50
|
+
// open menu via keyboard
|
|
51
|
+
const trigger = page.getByTestId('menu-trigger')
|
|
52
|
+
await trigger.focus()
|
|
53
|
+
await page.keyboard.press('Enter')
|
|
54
|
+
await page.waitForTimeout(300)
|
|
55
|
+
|
|
56
|
+
const menuContent = page.getByTestId('menu-content')
|
|
57
|
+
await expect(menuContent).toBeVisible()
|
|
58
|
+
|
|
59
|
+
// navigate to submenu trigger via keyboard
|
|
60
|
+
const submenuTrigger = page.getByTestId('submenu-trigger')
|
|
61
|
+
await submenuTrigger.focus()
|
|
62
|
+
await expect(submenuTrigger).toBeFocused()
|
|
63
|
+
|
|
64
|
+
// press Enter to open submenu
|
|
65
|
+
await page.keyboard.press('Enter')
|
|
66
|
+
await page.waitForTimeout(300)
|
|
67
|
+
|
|
68
|
+
const submenuContent = page.getByTestId('submenu-content')
|
|
69
|
+
await expect(submenuContent).toBeVisible()
|
|
70
|
+
|
|
71
|
+
// the first submenu item should be focused AND have focusVisible
|
|
72
|
+
const firstSubmenuItem = page.getByTestId('submenu-item-1')
|
|
73
|
+
await expect(firstSubmenuItem).toBeFocused()
|
|
74
|
+
|
|
75
|
+
// check that the focused item has the data-highlighted attribute
|
|
76
|
+
const hasHighlight = await firstSubmenuItem.getAttribute('data-highlighted')
|
|
77
|
+
expect(hasHighlight).toBe('')
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
test('submenu trigger should have focusVisible when escape returns focus from submenu', async ({
|
|
81
|
+
page,
|
|
82
|
+
}) => {
|
|
83
|
+
await page.waitForLoadState('networkidle')
|
|
84
|
+
|
|
85
|
+
// open menu via keyboard
|
|
86
|
+
const trigger = page.getByTestId('menu-trigger')
|
|
87
|
+
await trigger.focus()
|
|
88
|
+
await page.keyboard.press('Enter')
|
|
89
|
+
await page.waitForTimeout(300)
|
|
90
|
+
|
|
91
|
+
const menuContent = page.getByTestId('menu-content')
|
|
92
|
+
await expect(menuContent).toBeVisible()
|
|
93
|
+
|
|
94
|
+
// navigate to submenu trigger and open via keyboard
|
|
95
|
+
const submenuTrigger = page.getByTestId('submenu-trigger')
|
|
96
|
+
await submenuTrigger.focus()
|
|
97
|
+
await page.keyboard.press('ArrowRight')
|
|
98
|
+
await page.waitForTimeout(300)
|
|
99
|
+
|
|
100
|
+
const submenuContent = page.getByTestId('submenu-content')
|
|
101
|
+
await expect(submenuContent).toBeVisible()
|
|
102
|
+
|
|
103
|
+
// press Escape to close submenu
|
|
104
|
+
await page.keyboard.press('Escape')
|
|
105
|
+
await page.waitForTimeout(300)
|
|
106
|
+
|
|
107
|
+
// submenu should be closed
|
|
108
|
+
await expect(submenuContent).not.toBeVisible()
|
|
109
|
+
|
|
110
|
+
// parent menu should still be open
|
|
111
|
+
await expect(menuContent).toBeVisible()
|
|
112
|
+
|
|
113
|
+
// focus should return to submenu trigger WITH focusVisible
|
|
114
|
+
await expect(submenuTrigger).toBeFocused()
|
|
115
|
+
|
|
116
|
+
// check that the submenu trigger has the data-highlighted attribute (focus visible)
|
|
117
|
+
const hasHighlight = await submenuTrigger.getAttribute('data-highlighted')
|
|
118
|
+
expect(hasHighlight).toBe('')
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
test('submenu trigger should have focusVisible when ArrowLeft returns focus from submenu', async ({
|
|
122
|
+
page,
|
|
123
|
+
}) => {
|
|
124
|
+
await page.waitForLoadState('networkidle')
|
|
125
|
+
|
|
126
|
+
// open menu via keyboard
|
|
127
|
+
const trigger = page.getByTestId('menu-trigger')
|
|
128
|
+
await trigger.focus()
|
|
129
|
+
await page.keyboard.press('Enter')
|
|
130
|
+
await page.waitForTimeout(300)
|
|
131
|
+
|
|
132
|
+
const menuContent = page.getByTestId('menu-content')
|
|
133
|
+
await expect(menuContent).toBeVisible()
|
|
134
|
+
|
|
135
|
+
// navigate to submenu trigger and open via keyboard
|
|
136
|
+
const submenuTrigger = page.getByTestId('submenu-trigger')
|
|
137
|
+
await submenuTrigger.focus()
|
|
138
|
+
await page.keyboard.press('ArrowRight')
|
|
139
|
+
await page.waitForTimeout(300)
|
|
140
|
+
|
|
141
|
+
const submenuContent = page.getByTestId('submenu-content')
|
|
142
|
+
await expect(submenuContent).toBeVisible()
|
|
143
|
+
|
|
144
|
+
// focus first item in submenu
|
|
145
|
+
const submenuItem = page.getByTestId('submenu-item-1')
|
|
146
|
+
await expect(submenuItem).toBeFocused()
|
|
147
|
+
|
|
148
|
+
// press ArrowLeft to close submenu and return to parent
|
|
149
|
+
await page.keyboard.press('ArrowLeft')
|
|
150
|
+
await page.waitForTimeout(300)
|
|
151
|
+
|
|
152
|
+
// submenu should be closed
|
|
153
|
+
await expect(submenuContent).not.toBeVisible()
|
|
154
|
+
|
|
155
|
+
// parent menu should still be open
|
|
156
|
+
await expect(menuContent).toBeVisible()
|
|
157
|
+
|
|
158
|
+
// focus should return to submenu trigger WITH focusVisible
|
|
159
|
+
await expect(submenuTrigger).toBeFocused()
|
|
160
|
+
|
|
161
|
+
// check that the submenu trigger has the data-highlighted attribute (focus visible)
|
|
162
|
+
const hasHighlight = await submenuTrigger.getAttribute('data-highlighted')
|
|
163
|
+
expect(hasHighlight).toBe('')
|
|
164
|
+
})
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
test.describe('Menu Submenu Left-Side Keyboard Navigation', () => {
|
|
168
|
+
test.beforeEach(async ({ page }) => {
|
|
169
|
+
await setupPage(page, { name: 'MenuSubLeftCase', type: 'useCase' })
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
test('ArrowRight opens left-side submenu (same as right-side)', async ({ page }) => {
|
|
173
|
+
await page.waitForLoadState('networkidle')
|
|
174
|
+
|
|
175
|
+
// open menu
|
|
176
|
+
const menuTrigger = page.locator('#menu-trigger')
|
|
177
|
+
await menuTrigger.click()
|
|
178
|
+
await page.waitForTimeout(200)
|
|
179
|
+
|
|
180
|
+
const menuContent = page.locator('#menu-content')
|
|
181
|
+
await expect(menuContent).toBeVisible()
|
|
182
|
+
|
|
183
|
+
// focus submenu trigger
|
|
184
|
+
const submenuTrigger = page.locator('#submenu-trigger')
|
|
185
|
+
await submenuTrigger.focus()
|
|
186
|
+
await expect(submenuTrigger).toBeFocused()
|
|
187
|
+
|
|
188
|
+
// ArrowRight should open submenu regardless of placement side
|
|
189
|
+
await page.keyboard.press('ArrowRight')
|
|
190
|
+
await page.waitForTimeout(300)
|
|
191
|
+
|
|
192
|
+
const submenuContent = page.locator('#submenu-content')
|
|
193
|
+
await expect(submenuContent).toBeVisible()
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
test('ArrowLeft closes left-side submenu (same as right-side)', async ({ page }) => {
|
|
197
|
+
await page.waitForLoadState('networkidle')
|
|
198
|
+
|
|
199
|
+
// open menu
|
|
200
|
+
const menuTrigger = page.locator('#menu-trigger')
|
|
201
|
+
await menuTrigger.click()
|
|
202
|
+
await page.waitForTimeout(200)
|
|
203
|
+
|
|
204
|
+
// open submenu via ArrowRight
|
|
205
|
+
const submenuTrigger = page.locator('#submenu-trigger')
|
|
206
|
+
await submenuTrigger.focus()
|
|
207
|
+
await page.keyboard.press('ArrowRight')
|
|
208
|
+
await page.waitForTimeout(300)
|
|
209
|
+
|
|
210
|
+
const submenuContent = page.locator('#submenu-content')
|
|
211
|
+
await expect(submenuContent).toBeVisible()
|
|
212
|
+
|
|
213
|
+
// ArrowLeft should close submenu regardless of placement side
|
|
214
|
+
await page.keyboard.press('ArrowLeft')
|
|
215
|
+
await page.waitForTimeout(300)
|
|
216
|
+
|
|
217
|
+
await expect(submenuContent).not.toBeVisible()
|
|
218
|
+
await expect(submenuTrigger).toBeFocused()
|
|
219
|
+
})
|
|
220
|
+
})
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
|
|
3
|
+
import { setupPage } from './test-utils'
|
|
4
|
+
|
|
5
|
+
test.beforeEach(async ({ page }) => {
|
|
6
|
+
await setupPage(page, { name: 'MenuSubLeftCase', type: 'useCase' })
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Tests for Menu Submenu SafePolygon behavior when submenu opens to the LEFT
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
test('left-side submenu has data-side="left" attribute required for safePolygon', async ({
|
|
14
|
+
page,
|
|
15
|
+
}) => {
|
|
16
|
+
await page.waitForLoadState('networkidle')
|
|
17
|
+
|
|
18
|
+
const menuTrigger = page.locator('#menu-trigger')
|
|
19
|
+
const menuContent = page.locator('#menu-content')
|
|
20
|
+
const submenuTrigger = page.locator('#submenu-trigger')
|
|
21
|
+
const submenuContent = page.locator('#submenu-content')
|
|
22
|
+
|
|
23
|
+
await menuTrigger.click()
|
|
24
|
+
await expect(menuContent).toBeVisible({ timeout: 5000 })
|
|
25
|
+
|
|
26
|
+
await submenuTrigger.hover()
|
|
27
|
+
await page.waitForTimeout(200)
|
|
28
|
+
await expect(submenuContent).toBeVisible({ timeout: 5000 })
|
|
29
|
+
|
|
30
|
+
// data-side tells safePolygon which direction the submenu is
|
|
31
|
+
// for left-side submenus, this should be 'left'
|
|
32
|
+
const dataSide = await submenuContent.getAttribute('data-side')
|
|
33
|
+
expect(dataSide).toBe('left')
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test('safePolygon keeps left-side submenu open when mouse crosses parent menu items', async ({
|
|
37
|
+
page,
|
|
38
|
+
}) => {
|
|
39
|
+
await page.waitForLoadState('networkidle')
|
|
40
|
+
|
|
41
|
+
const menuTrigger = page.locator('#menu-trigger')
|
|
42
|
+
const menuContent = page.locator('#menu-content')
|
|
43
|
+
const submenuTrigger = page.locator('#submenu-trigger')
|
|
44
|
+
const submenuContent = page.locator('#submenu-content')
|
|
45
|
+
|
|
46
|
+
await menuTrigger.click()
|
|
47
|
+
await expect(menuContent).toBeVisible({ timeout: 5000 })
|
|
48
|
+
|
|
49
|
+
await submenuTrigger.hover()
|
|
50
|
+
await page.waitForTimeout(200)
|
|
51
|
+
await expect(submenuContent).toBeVisible({ timeout: 5000 })
|
|
52
|
+
|
|
53
|
+
// get positions
|
|
54
|
+
const triggerBox = await submenuTrigger.boundingBox()
|
|
55
|
+
const submenuBox = await submenuContent.boundingBox()
|
|
56
|
+
|
|
57
|
+
if (!triggerBox || !submenuBox) {
|
|
58
|
+
throw new Error('Could not get bounding boxes')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// start at the submenu trigger
|
|
62
|
+
const startX = triggerBox.x + triggerBox.width / 2
|
|
63
|
+
const startY = triggerBox.y + triggerBox.height / 2
|
|
64
|
+
|
|
65
|
+
// end inside submenu content - moving LEFT and DOWN
|
|
66
|
+
// the submenu is to the LEFT of the trigger
|
|
67
|
+
const endX = submenuBox.x + submenuBox.width / 2
|
|
68
|
+
const endY = submenuBox.y + submenuBox.height - 20
|
|
69
|
+
|
|
70
|
+
await page.mouse.move(startX, startY)
|
|
71
|
+
await page.waitForTimeout(30)
|
|
72
|
+
|
|
73
|
+
// move diagonally DOWN and LEFT
|
|
74
|
+
// this path crosses through menu items below the trigger
|
|
75
|
+
// safePolygon should prevent those items from stealing focus
|
|
76
|
+
const steps = 12
|
|
77
|
+
for (let i = 1; i <= steps; i++) {
|
|
78
|
+
const progress = i / steps
|
|
79
|
+
const x = startX + (endX - startX) * progress
|
|
80
|
+
const y = startY + (endY - startY) * progress
|
|
81
|
+
await page.mouse.move(x, y)
|
|
82
|
+
await page.waitForTimeout(20)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// submenu should stay open because safePolygon correctly identifies
|
|
86
|
+
// side='left' from the placement and matches it with pointerDir='left'
|
|
87
|
+
await expect(submenuContent).toBeVisible()
|
|
88
|
+
})
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
|
|
3
|
+
import { setupPage } from './test-utils'
|
|
4
|
+
|
|
5
|
+
test.beforeEach(async ({ page }) => {
|
|
6
|
+
await setupPage(page, { name: 'MenuSubNestedPositionCase', type: 'useCase' })
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
test('nested submenu does not overlap parent submenu', async ({ page }) => {
|
|
10
|
+
await page.setViewportSize({ width: 500, height: 600 })
|
|
11
|
+
await page.waitForLoadState('networkidle')
|
|
12
|
+
|
|
13
|
+
// open root menu
|
|
14
|
+
await page.locator('#menu-trigger').focus()
|
|
15
|
+
await page.keyboard.press('Enter')
|
|
16
|
+
await page.waitForTimeout(400)
|
|
17
|
+
await expect(page.locator('#menu-content')).toBeVisible({ timeout: 5000 })
|
|
18
|
+
|
|
19
|
+
// open sub
|
|
20
|
+
await page.keyboard.press('ArrowDown')
|
|
21
|
+
await page.waitForTimeout(100)
|
|
22
|
+
await page.keyboard.press('ArrowRight')
|
|
23
|
+
await page.waitForTimeout(400)
|
|
24
|
+
await expect(page.locator('#sub-content')).toBeVisible({ timeout: 5000 })
|
|
25
|
+
|
|
26
|
+
// open nested
|
|
27
|
+
await page.keyboard.press('ArrowDown')
|
|
28
|
+
await page.waitForTimeout(100)
|
|
29
|
+
await page.keyboard.press('ArrowRight')
|
|
30
|
+
await page.waitForTimeout(400)
|
|
31
|
+
await expect(page.locator('#nested-content')).toBeVisible({ timeout: 5000 })
|
|
32
|
+
|
|
33
|
+
// nested center must be far from its PARENT sub center (not root)
|
|
34
|
+
const centers = await page.evaluate(() => {
|
|
35
|
+
const rect = (id: string) => {
|
|
36
|
+
const r = document.getElementById(id)!.getBoundingClientRect()
|
|
37
|
+
return { cx: r.x + r.width / 2, cy: r.y + r.height / 2 }
|
|
38
|
+
}
|
|
39
|
+
return { sub: rect('sub-content'), nested: rect('nested-content') }
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const dx = Math.abs(centers.nested.cx - centers.sub.cx)
|
|
43
|
+
const dy = Math.abs(centers.nested.cy - centers.sub.cy)
|
|
44
|
+
const distance = Math.sqrt(dx * dx + dy * dy)
|
|
45
|
+
|
|
46
|
+
// centers must be far apart - nested should NOT sit on top of parent sub
|
|
47
|
+
expect(distance).toBeGreaterThan(100)
|
|
48
|
+
})
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
|
|
3
|
+
import { setupPage } from './test-utils'
|
|
4
|
+
|
|
5
|
+
test.beforeEach(async ({ page }) => {
|
|
6
|
+
await setupPage(page, { name: 'MenuSubCase', type: 'useCase' })
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Tests for Menu Submenu SafePolygon behavior
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
test('submenu has data-side attribute required for safePolygon', async ({ page }) => {
|
|
14
|
+
await page.waitForLoadState('networkidle')
|
|
15
|
+
|
|
16
|
+
const menuTrigger = page.locator('#menu-trigger')
|
|
17
|
+
const menuContent = page.locator('#menu-content')
|
|
18
|
+
const submenuTrigger = page.locator('#submenu-trigger')
|
|
19
|
+
const submenuContent = page.locator('#submenu-content')
|
|
20
|
+
|
|
21
|
+
await menuTrigger.click()
|
|
22
|
+
await expect(menuContent).toBeVisible({ timeout: 5000 })
|
|
23
|
+
|
|
24
|
+
await submenuTrigger.hover()
|
|
25
|
+
await page.waitForTimeout(200)
|
|
26
|
+
await expect(submenuContent).toBeVisible({ timeout: 5000 })
|
|
27
|
+
|
|
28
|
+
// data-side tells safePolygon which direction the submenu is
|
|
29
|
+
// Without it, isPointerMovingToSubmenu always returns false
|
|
30
|
+
const dataSide = await submenuContent.getAttribute('data-side')
|
|
31
|
+
expect(dataSide).toBe('right')
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test('safePolygon keeps submenu open when mouse crosses parent menu items', async ({
|
|
35
|
+
page,
|
|
36
|
+
}) => {
|
|
37
|
+
await page.waitForLoadState('networkidle')
|
|
38
|
+
|
|
39
|
+
const menuTrigger = page.locator('#menu-trigger')
|
|
40
|
+
const menuContent = page.locator('#menu-content')
|
|
41
|
+
const submenuTrigger = page.locator('#submenu-trigger')
|
|
42
|
+
const submenuContent = page.locator('#submenu-content')
|
|
43
|
+
const menuItem4 = page.locator('#menu-item-4') // Below the submenu trigger
|
|
44
|
+
|
|
45
|
+
await menuTrigger.click()
|
|
46
|
+
await expect(menuContent).toBeVisible({ timeout: 5000 })
|
|
47
|
+
|
|
48
|
+
await submenuTrigger.hover()
|
|
49
|
+
await page.waitForTimeout(200)
|
|
50
|
+
await expect(submenuContent).toBeVisible({ timeout: 5000 })
|
|
51
|
+
|
|
52
|
+
// Get positions
|
|
53
|
+
const triggerBox = await submenuTrigger.boundingBox()
|
|
54
|
+
const submenuBox = await submenuContent.boundingBox()
|
|
55
|
+
const item4Box = await menuItem4.boundingBox()
|
|
56
|
+
|
|
57
|
+
if (!triggerBox || !submenuBox || !item4Box) {
|
|
58
|
+
throw new Error('Could not get bounding boxes')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Start at the submenu trigger
|
|
62
|
+
const startX = triggerBox.x + triggerBox.width / 2
|
|
63
|
+
const startY = triggerBox.y + triggerBox.height / 2
|
|
64
|
+
|
|
65
|
+
// End inside submenu content - but path goes DOWN through item4's vertical space
|
|
66
|
+
// then RIGHT into the submenu
|
|
67
|
+
const endX = submenuBox.x + submenuBox.width / 2
|
|
68
|
+
const endY = submenuBox.y + submenuBox.height - 20 // Bottom of submenu
|
|
69
|
+
|
|
70
|
+
await page.mouse.move(startX, startY)
|
|
71
|
+
await page.waitForTimeout(30)
|
|
72
|
+
|
|
73
|
+
// Move diagonally DOWN and RIGHT
|
|
74
|
+
// This path crosses through the area where item4 is located horizontally
|
|
75
|
+
// Without safePolygon, hovering over item4 would close the submenu
|
|
76
|
+
const steps = 12
|
|
77
|
+
for (let i = 1; i <= steps; i++) {
|
|
78
|
+
const progress = i / steps
|
|
79
|
+
const x = startX + (endX - startX) * progress
|
|
80
|
+
const y = startY + (endY - startY) * progress
|
|
81
|
+
await page.mouse.move(x, y)
|
|
82
|
+
await page.waitForTimeout(20)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// With safePolygon working:
|
|
86
|
+
// - When leaving trigger, polygon is created with side='right'
|
|
87
|
+
// - Mouse moving right matches side='right', so isPointerMovingToSubmenu=true
|
|
88
|
+
// - onItemEnter on item4 calls preventDefault, item4 doesn't steal focus
|
|
89
|
+
// - Submenu stays open
|
|
90
|
+
//
|
|
91
|
+
// Without fix (side=undefined):
|
|
92
|
+
// - isPointerMovingToSubmenu returns false (pointerDir 'right' !== undefined)
|
|
93
|
+
// - onItemEnter doesn't preventDefault
|
|
94
|
+
// - item4 gets focused, triggering onFocusOutside on submenu
|
|
95
|
+
// - Submenu closes
|
|
96
|
+
await expect(submenuContent).toBeVisible()
|
|
97
|
+
})
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
|
|
3
|
+
import { setupPage } from './test-utils'
|
|
4
|
+
|
|
5
|
+
test.beforeEach(async ({ page }) => {
|
|
6
|
+
await setupPage(page, { name: 'MenuSubStyledCase', type: 'useCase' })
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
test('styled(Menu.SubContent) positions submenu correctly', async ({ page }) => {
|
|
10
|
+
await page.waitForLoadState('networkidle')
|
|
11
|
+
|
|
12
|
+
// open the menu
|
|
13
|
+
await page.click('#menu-trigger')
|
|
14
|
+
await page.waitForTimeout(300)
|
|
15
|
+
|
|
16
|
+
// hover on submenu trigger to open submenu
|
|
17
|
+
await page.hover('#submenu-trigger')
|
|
18
|
+
await page.waitForTimeout(500)
|
|
19
|
+
|
|
20
|
+
// check that submenu is visible
|
|
21
|
+
const submenuContent = page.locator('#submenu-content')
|
|
22
|
+
await expect(submenuContent).toBeVisible()
|
|
23
|
+
|
|
24
|
+
// get positions
|
|
25
|
+
const triggerBox = await page.locator('#submenu-trigger').boundingBox()
|
|
26
|
+
const submenuBox = await submenuContent.boundingBox()
|
|
27
|
+
|
|
28
|
+
expect(triggerBox).toBeTruthy()
|
|
29
|
+
expect(submenuBox).toBeTruthy()
|
|
30
|
+
|
|
31
|
+
// submenu should be positioned to the right of the trigger, not at top-left (0,0)
|
|
32
|
+
// the submenu's left edge should be near or to the right of the trigger's right edge
|
|
33
|
+
expect(submenuBox!.x).toBeGreaterThan(triggerBox!.x)
|
|
34
|
+
// the submenu should not be at y=0 (top of viewport)
|
|
35
|
+
expect(submenuBox!.y).toBeGreaterThan(50)
|
|
36
|
+
|
|
37
|
+
// verify submenu has items
|
|
38
|
+
await expect(page.locator('#submenu-item-1')).toBeVisible()
|
|
39
|
+
await expect(page.locator('#submenu-item-2')).toBeVisible()
|
|
40
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
|
|
4
|
+
test.describe('Menu Theme Inheritance', () => {
|
|
5
|
+
test.beforeEach(async ({ page }) => {
|
|
6
|
+
await setupPage(page, { name: 'MenuThemeCase', type: 'useCase' })
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
test('menu content inherits theme from parent context', async ({ page }) => {
|
|
10
|
+
const trigger = page.getByTestId('menu-trigger')
|
|
11
|
+
await expect(trigger).toBeVisible()
|
|
12
|
+
|
|
13
|
+
await trigger.focus()
|
|
14
|
+
await page.keyboard.press('Enter')
|
|
15
|
+
await page.waitForTimeout(300)
|
|
16
|
+
|
|
17
|
+
const menuContent = page.getByTestId('menu-content')
|
|
18
|
+
await expect(menuContent).toBeVisible()
|
|
19
|
+
|
|
20
|
+
// check that menu content ancestor has the theme class
|
|
21
|
+
const hasThemeClass = await menuContent.evaluate((el) => {
|
|
22
|
+
let current = el.parentElement
|
|
23
|
+
while (current) {
|
|
24
|
+
if (current.className?.includes('t_blue')) {
|
|
25
|
+
return true
|
|
26
|
+
}
|
|
27
|
+
current = current.parentElement
|
|
28
|
+
}
|
|
29
|
+
return false
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
expect(hasThemeClass).toBe(true)
|
|
33
|
+
})
|
|
34
|
+
})
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
|
|
4
|
+
test.beforeEach(async ({ page }) => {
|
|
5
|
+
await setupPage(page, { name: 'MenuUnstyledCase', type: 'useCase' })
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
test('Menu.Content unstyled removes all default styles', async ({ page }) => {
|
|
9
|
+
// open the unstyled menu
|
|
10
|
+
await page.getByTestId('unstyled-menu-trigger').click()
|
|
11
|
+
await page.waitForTimeout(300)
|
|
12
|
+
|
|
13
|
+
const unstyledContent = page.getByTestId('unstyled-menu-content')
|
|
14
|
+
await expect(unstyledContent).toBeVisible()
|
|
15
|
+
|
|
16
|
+
// check that unstyled menu has no background/padding/border from defaults
|
|
17
|
+
const unstyledStyles = await unstyledContent.evaluate((el) => {
|
|
18
|
+
const computed = window.getComputedStyle(el)
|
|
19
|
+
return {
|
|
20
|
+
backgroundColor: computed.backgroundColor,
|
|
21
|
+
padding: computed.padding,
|
|
22
|
+
borderWidth: computed.borderWidth,
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
// unstyled should have transparent/none background (rgba(0,0,0,0) or transparent)
|
|
27
|
+
expect(
|
|
28
|
+
unstyledStyles.backgroundColor === 'rgba(0, 0, 0, 0)' ||
|
|
29
|
+
unstyledStyles.backgroundColor === 'transparent'
|
|
30
|
+
).toBe(true)
|
|
31
|
+
|
|
32
|
+
// close the unstyled menu
|
|
33
|
+
await page.keyboard.press('Escape')
|
|
34
|
+
await page.waitForTimeout(200)
|
|
35
|
+
|
|
36
|
+
// open the styled menu (default)
|
|
37
|
+
await page.getByTestId('styled-menu-trigger').click()
|
|
38
|
+
await page.waitForTimeout(300)
|
|
39
|
+
|
|
40
|
+
const styledContent = page.getByTestId('styled-menu-content')
|
|
41
|
+
await expect(styledContent).toBeVisible()
|
|
42
|
+
|
|
43
|
+
// check that styled menu has background applied
|
|
44
|
+
const styledStyles = await styledContent.evaluate((el) => {
|
|
45
|
+
const computed = window.getComputedStyle(el)
|
|
46
|
+
return {
|
|
47
|
+
backgroundColor: computed.backgroundColor,
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
// styled should have a real background color (not transparent)
|
|
52
|
+
expect(
|
|
53
|
+
styledStyles.backgroundColor !== 'rgba(0, 0, 0, 0)' &&
|
|
54
|
+
styledStyles.backgroundColor !== 'transparent'
|
|
55
|
+
).toBe(true)
|
|
56
|
+
})
|