@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,231 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
|
|
4
|
+
test.beforeEach(async ({ page }) => {
|
|
5
|
+
await setupPage(page, { name: 'MenuItemPseudoOverrideCase', type: 'useCase' })
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
test('spread style object: pseudo styles should override variant defaults', async ({
|
|
9
|
+
page,
|
|
10
|
+
}) => {
|
|
11
|
+
// open the menu with spread style object (no unstyled)
|
|
12
|
+
await page.getByTestId('spread-trigger').click()
|
|
13
|
+
await page.waitForTimeout(300)
|
|
14
|
+
|
|
15
|
+
const spreadItem = page.getByTestId('spread-item')
|
|
16
|
+
await expect(spreadItem).toBeVisible()
|
|
17
|
+
|
|
18
|
+
// focus the item to trigger focusStyle
|
|
19
|
+
await spreadItem.focus()
|
|
20
|
+
await page.waitForTimeout(100)
|
|
21
|
+
|
|
22
|
+
// check that the custom focusStyle is applied (red), not the default variant
|
|
23
|
+
const focusedStyles = await spreadItem.evaluate((el) => {
|
|
24
|
+
const computed = window.getComputedStyle(el)
|
|
25
|
+
return {
|
|
26
|
+
backgroundColor: computed.backgroundColor,
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
// user specified rgb(255, 0, 0) which should override the default $backgroundHover
|
|
31
|
+
expect(focusedStyles.backgroundColor).toBe('rgb(255, 0, 0)')
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test('spread style with unstyled: works correctly', async ({ page }) => {
|
|
35
|
+
// open the menu with spread style + unstyled
|
|
36
|
+
await page.getByTestId('spread-unstyled-trigger').click()
|
|
37
|
+
await page.waitForTimeout(300)
|
|
38
|
+
|
|
39
|
+
const unstyledItem = page.getByTestId('spread-unstyled-item')
|
|
40
|
+
await expect(unstyledItem).toBeVisible()
|
|
41
|
+
|
|
42
|
+
// focus the item to trigger focusStyle
|
|
43
|
+
await unstyledItem.focus()
|
|
44
|
+
await page.waitForTimeout(100)
|
|
45
|
+
|
|
46
|
+
// check that the custom focusStyle is applied
|
|
47
|
+
const focusedStyles = await unstyledItem.evaluate((el) => {
|
|
48
|
+
const computed = window.getComputedStyle(el)
|
|
49
|
+
return {
|
|
50
|
+
backgroundColor: computed.backgroundColor,
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
// user specified rgb(255, 0, 0)
|
|
55
|
+
expect(focusedStyles.backgroundColor).toBe('rgb(255, 0, 0)')
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test('direct props: user-provided pseudo styles override variant defaults', async ({
|
|
59
|
+
page,
|
|
60
|
+
}) => {
|
|
61
|
+
// open the menu with custom pseudo styles
|
|
62
|
+
await page.getByTestId('custom-trigger').click()
|
|
63
|
+
await page.waitForTimeout(300)
|
|
64
|
+
|
|
65
|
+
const customItem = page.getByTestId('custom-item')
|
|
66
|
+
await expect(customItem).toBeVisible()
|
|
67
|
+
|
|
68
|
+
// focus the item to trigger focusStyle
|
|
69
|
+
await customItem.focus()
|
|
70
|
+
await page.waitForTimeout(100)
|
|
71
|
+
|
|
72
|
+
// check that the custom focusStyle is applied (red), not the default variant
|
|
73
|
+
const focusedStyles = await customItem.evaluate((el) => {
|
|
74
|
+
const computed = window.getComputedStyle(el)
|
|
75
|
+
return {
|
|
76
|
+
backgroundColor: computed.backgroundColor,
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
// user specified rgb(255, 0, 0) which should override the default $backgroundHover
|
|
81
|
+
expect(focusedStyles.backgroundColor).toBe('rgb(255, 0, 0)')
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
test('unstyled item with custom pseudo styles works correctly', async ({ page }) => {
|
|
85
|
+
// open the unstyled menu
|
|
86
|
+
await page.getByTestId('unstyled-trigger').click()
|
|
87
|
+
await page.waitForTimeout(300)
|
|
88
|
+
|
|
89
|
+
const unstyledItem = page.getByTestId('unstyled-item')
|
|
90
|
+
await expect(unstyledItem).toBeVisible()
|
|
91
|
+
|
|
92
|
+
// focus the item to trigger focusStyle
|
|
93
|
+
await unstyledItem.focus()
|
|
94
|
+
await page.waitForTimeout(100)
|
|
95
|
+
|
|
96
|
+
// check that the custom focusStyle is applied
|
|
97
|
+
const focusedStyles = await unstyledItem.evaluate((el) => {
|
|
98
|
+
const computed = window.getComputedStyle(el)
|
|
99
|
+
return {
|
|
100
|
+
backgroundColor: computed.backgroundColor,
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
// user specified rgb(255, 0, 0)
|
|
105
|
+
expect(focusedStyles.backgroundColor).toBe('rgb(255, 0, 0)')
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
test('default item uses variant default pseudo styles', async ({ page }) => {
|
|
109
|
+
// open the menu
|
|
110
|
+
await page.getByTestId('custom-trigger').click()
|
|
111
|
+
await page.waitForTimeout(300)
|
|
112
|
+
|
|
113
|
+
const defaultItem = page.getByTestId('default-item')
|
|
114
|
+
await expect(defaultItem).toBeVisible()
|
|
115
|
+
|
|
116
|
+
// focus the item to trigger focusStyle
|
|
117
|
+
await defaultItem.focus()
|
|
118
|
+
await page.waitForTimeout(100)
|
|
119
|
+
|
|
120
|
+
// check that the default focusStyle is applied (not red, but the theme's $backgroundHover)
|
|
121
|
+
const focusedStyles = await defaultItem.evaluate((el) => {
|
|
122
|
+
const computed = window.getComputedStyle(el)
|
|
123
|
+
return {
|
|
124
|
+
backgroundColor: computed.backgroundColor,
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
// should NOT be red (255, 0, 0) - should be the default variant's $backgroundHover
|
|
129
|
+
expect(focusedStyles.backgroundColor).not.toBe('rgb(255, 0, 0)')
|
|
130
|
+
// should have some background color applied
|
|
131
|
+
expect(focusedStyles.backgroundColor).not.toBe('rgba(0, 0, 0, 0)')
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
test('shorthands: pseudo styles should override variant defaults', async ({ page }) => {
|
|
135
|
+
// open the menu with shorthand styles (no unstyled)
|
|
136
|
+
await page.getByTestId('shorthand-trigger').click()
|
|
137
|
+
await page.waitForTimeout(300)
|
|
138
|
+
|
|
139
|
+
const shorthandItem = page.getByTestId('shorthand-item')
|
|
140
|
+
await expect(shorthandItem).toBeVisible()
|
|
141
|
+
|
|
142
|
+
// focus the item to trigger focusStyle
|
|
143
|
+
await shorthandItem.focus()
|
|
144
|
+
await page.waitForTimeout(100)
|
|
145
|
+
|
|
146
|
+
// check that the custom focusStyle is applied (red)
|
|
147
|
+
const focusedStyles = await shorthandItem.evaluate((el) => {
|
|
148
|
+
const computed = window.getComputedStyle(el)
|
|
149
|
+
return {
|
|
150
|
+
backgroundColor: computed.backgroundColor,
|
|
151
|
+
}
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
// user specified bg: 'rgb(255, 0, 0)' (shorthand) which should override default
|
|
155
|
+
expect(focusedStyles.backgroundColor).toBe('rgb(255, 0, 0)')
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
test('shorthands with unstyled: works correctly', async ({ page }) => {
|
|
159
|
+
// open the menu with shorthand styles + unstyled
|
|
160
|
+
await page.getByTestId('shorthand-unstyled-trigger').click()
|
|
161
|
+
await page.waitForTimeout(300)
|
|
162
|
+
|
|
163
|
+
const shorthandUnstyledItem = page.getByTestId('shorthand-unstyled-item')
|
|
164
|
+
await expect(shorthandUnstyledItem).toBeVisible()
|
|
165
|
+
|
|
166
|
+
// focus the item to trigger focusStyle
|
|
167
|
+
await shorthandUnstyledItem.focus()
|
|
168
|
+
await page.waitForTimeout(100)
|
|
169
|
+
|
|
170
|
+
// check that the custom focusStyle is applied
|
|
171
|
+
const focusedStyles = await shorthandUnstyledItem.evaluate((el) => {
|
|
172
|
+
const computed = window.getComputedStyle(el)
|
|
173
|
+
return {
|
|
174
|
+
backgroundColor: computed.backgroundColor,
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
// user specified bg: 'rgb(255, 0, 0)' (shorthand)
|
|
179
|
+
expect(focusedStyles.backgroundColor).toBe('rgb(255, 0, 0)')
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
test('styled() component: pseudo styles should override variant defaults', async ({
|
|
183
|
+
page,
|
|
184
|
+
}) => {
|
|
185
|
+
// open the menu with styled() component (no unstyled)
|
|
186
|
+
await page.getByTestId('styled-trigger').click()
|
|
187
|
+
await page.waitForTimeout(300)
|
|
188
|
+
|
|
189
|
+
const styledItem = page.getByTestId('styled-item')
|
|
190
|
+
await expect(styledItem).toBeVisible()
|
|
191
|
+
|
|
192
|
+
// focus the item to trigger focusStyle
|
|
193
|
+
await styledItem.focus()
|
|
194
|
+
await page.waitForTimeout(100)
|
|
195
|
+
|
|
196
|
+
// check that the custom focusStyle is applied (red)
|
|
197
|
+
const focusedStyles = await styledItem.evaluate((el) => {
|
|
198
|
+
const computed = window.getComputedStyle(el)
|
|
199
|
+
return {
|
|
200
|
+
backgroundColor: computed.backgroundColor,
|
|
201
|
+
}
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
// styled component specified backgroundColor: 'rgb(255, 0, 0)' in focusStyle
|
|
205
|
+
// this should override the variant's default $backgroundHover
|
|
206
|
+
expect(focusedStyles.backgroundColor).toBe('rgb(255, 0, 0)')
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
test('styled() component with unstyled: works correctly', async ({ page }) => {
|
|
210
|
+
// open the menu with styled() component + unstyled
|
|
211
|
+
await page.getByTestId('styled-unstyled-trigger').click()
|
|
212
|
+
await page.waitForTimeout(300)
|
|
213
|
+
|
|
214
|
+
const styledUnstyledItem = page.getByTestId('styled-unstyled-item')
|
|
215
|
+
await expect(styledUnstyledItem).toBeVisible()
|
|
216
|
+
|
|
217
|
+
// focus the item to trigger focusStyle
|
|
218
|
+
await styledUnstyledItem.focus()
|
|
219
|
+
await page.waitForTimeout(100)
|
|
220
|
+
|
|
221
|
+
// check that the custom focusStyle is applied
|
|
222
|
+
const focusedStyles = await styledUnstyledItem.evaluate((el) => {
|
|
223
|
+
const computed = window.getComputedStyle(el)
|
|
224
|
+
return {
|
|
225
|
+
backgroundColor: computed.backgroundColor,
|
|
226
|
+
}
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
// styled component specified backgroundColor: 'rgb(255, 0, 0)' in focusStyle
|
|
230
|
+
expect(focusedStyles.backgroundColor).toBe('rgb(255, 0, 0)')
|
|
231
|
+
})
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { getBoundingRect, setupPage } from './test-utils'
|
|
3
|
+
|
|
4
|
+
test.describe('Menu Multi-Trigger', () => {
|
|
5
|
+
test.beforeEach(async ({ page }) => {
|
|
6
|
+
await setupPage(page, {
|
|
7
|
+
name: 'MenuMultiTriggerCase',
|
|
8
|
+
type: 'useCase',
|
|
9
|
+
waitExtra: true,
|
|
10
|
+
})
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
test('clicking trigger A opens content near trigger A', async ({ page }) => {
|
|
14
|
+
const triggerA = page.getByTestId('trigger-a')
|
|
15
|
+
await triggerA.click()
|
|
16
|
+
await page.waitForTimeout(300)
|
|
17
|
+
|
|
18
|
+
const content = page.getByTestId('menu-content')
|
|
19
|
+
await expect(content).toBeVisible()
|
|
20
|
+
|
|
21
|
+
const triggerBox = await getBoundingRect(page, '[data-testid="trigger-a"]')
|
|
22
|
+
const contentBox = await getBoundingRect(page, '[data-testid="menu-content"]')
|
|
23
|
+
expect(triggerBox).not.toBeNull()
|
|
24
|
+
expect(contentBox).not.toBeNull()
|
|
25
|
+
|
|
26
|
+
// content should be horizontally near trigger A
|
|
27
|
+
expect(Math.abs(contentBox!.x - triggerBox!.x)).toBeLessThan(50)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
test('clicking trigger B re-anchors content to trigger B', async ({ page }) => {
|
|
31
|
+
// open via A first
|
|
32
|
+
const triggerA = page.getByTestId('trigger-a')
|
|
33
|
+
await triggerA.click()
|
|
34
|
+
await page.waitForTimeout(300)
|
|
35
|
+
await expect(page.getByTestId('menu-content')).toBeVisible()
|
|
36
|
+
|
|
37
|
+
// close
|
|
38
|
+
await page.keyboard.press('Escape')
|
|
39
|
+
await page.waitForTimeout(300)
|
|
40
|
+
|
|
41
|
+
// open via B
|
|
42
|
+
const triggerB = page.getByTestId('trigger-b')
|
|
43
|
+
await triggerB.click()
|
|
44
|
+
await page.waitForTimeout(300)
|
|
45
|
+
|
|
46
|
+
const content = page.getByTestId('menu-content')
|
|
47
|
+
await expect(content).toBeVisible()
|
|
48
|
+
|
|
49
|
+
const triggerBBox = await getBoundingRect(page, '[data-testid="trigger-b"]')
|
|
50
|
+
const contentBox = await getBoundingRect(page, '[data-testid="menu-content"]')
|
|
51
|
+
expect(triggerBBox).not.toBeNull()
|
|
52
|
+
expect(contentBox).not.toBeNull()
|
|
53
|
+
|
|
54
|
+
// content should be near trigger B, not trigger A
|
|
55
|
+
expect(Math.abs(contentBox!.x - triggerBBox!.x)).toBeLessThan(50)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test('only the active trigger has data-state=open', async ({ page }) => {
|
|
59
|
+
const triggerA = page.getByTestId('trigger-a')
|
|
60
|
+
const triggerB = page.getByTestId('trigger-b')
|
|
61
|
+
const triggerC = page.getByTestId('trigger-c')
|
|
62
|
+
|
|
63
|
+
await triggerB.click()
|
|
64
|
+
await page.waitForTimeout(300)
|
|
65
|
+
await expect(page.getByTestId('menu-content')).toBeVisible()
|
|
66
|
+
|
|
67
|
+
await expect(triggerA).toHaveAttribute('data-state', 'closed')
|
|
68
|
+
await expect(triggerB).toHaveAttribute('data-state', 'open')
|
|
69
|
+
await expect(triggerC).toHaveAttribute('data-state', 'closed')
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
test('keyboard open via Enter re-anchors to focused trigger', async ({ page }) => {
|
|
73
|
+
const triggerC = page.getByTestId('trigger-c')
|
|
74
|
+
await triggerC.focus()
|
|
75
|
+
await page.keyboard.press('Enter')
|
|
76
|
+
await page.waitForTimeout(300)
|
|
77
|
+
|
|
78
|
+
const content = page.getByTestId('menu-content')
|
|
79
|
+
await expect(content).toBeVisible()
|
|
80
|
+
|
|
81
|
+
const triggerCBox = await getBoundingRect(page, '[data-testid="trigger-c"]')
|
|
82
|
+
const contentBox = await getBoundingRect(page, '[data-testid="menu-content"]')
|
|
83
|
+
expect(triggerCBox).not.toBeNull()
|
|
84
|
+
expect(contentBox).not.toBeNull()
|
|
85
|
+
|
|
86
|
+
// content should be near trigger C
|
|
87
|
+
expect(Math.abs(contentBox!.x - triggerCBox!.x)).toBeLessThan(50)
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
test('close returns focus to the trigger that opened the menu', async ({ page }) => {
|
|
91
|
+
const triggerB = page.getByTestId('trigger-b')
|
|
92
|
+
await triggerB.click()
|
|
93
|
+
await page.waitForTimeout(300)
|
|
94
|
+
await expect(page.getByTestId('menu-content')).toBeVisible()
|
|
95
|
+
|
|
96
|
+
await page.keyboard.press('Escape')
|
|
97
|
+
await page.waitForTimeout(300)
|
|
98
|
+
|
|
99
|
+
await expect(triggerB).toBeFocused()
|
|
100
|
+
})
|
|
101
|
+
})
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
|
|
4
|
+
// Use smaller viewport to ensure menu needs to scroll
|
|
5
|
+
test.use({ viewport: { width: 800, height: 600 } })
|
|
6
|
+
|
|
7
|
+
test.describe('Menu Overflow', () => {
|
|
8
|
+
test.beforeEach(async ({ page }) => {
|
|
9
|
+
await setupPage(page, { name: 'MenuOverflowCase', type: 'useCase' })
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
test('menu content is constrained to max height', async ({ page }) => {
|
|
13
|
+
await page.waitForLoadState('networkidle')
|
|
14
|
+
|
|
15
|
+
const trigger = page.getByTestId('menu-trigger')
|
|
16
|
+
await trigger.click()
|
|
17
|
+
await page.waitForTimeout(300)
|
|
18
|
+
|
|
19
|
+
const menuContent = page.getByTestId('menu-content')
|
|
20
|
+
await expect(menuContent).toBeVisible()
|
|
21
|
+
|
|
22
|
+
// get menu content bounding box and viewport dimensions
|
|
23
|
+
const boundingBox = await menuContent.boundingBox()
|
|
24
|
+
const viewportSize = page.viewportSize()
|
|
25
|
+
|
|
26
|
+
expect(boundingBox).not.toBeNull()
|
|
27
|
+
expect(viewportSize).not.toBeNull()
|
|
28
|
+
|
|
29
|
+
if (boundingBox && viewportSize) {
|
|
30
|
+
// menu should not extend beyond viewport
|
|
31
|
+
expect(boundingBox.y).toBeGreaterThanOrEqual(0)
|
|
32
|
+
expect(boundingBox.y + boundingBox.height).toBeLessThanOrEqual(viewportSize.height)
|
|
33
|
+
// menu height should be constrained (less than total items would need)
|
|
34
|
+
expect(boundingBox.height).toBeLessThan(1000) // 30 items at ~33px each would be ~1000px
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('menu scroll view is scrollable', async ({ page }) => {
|
|
39
|
+
await page.waitForLoadState('networkidle')
|
|
40
|
+
|
|
41
|
+
const trigger = page.getByTestId('menu-trigger')
|
|
42
|
+
await trigger.click()
|
|
43
|
+
await page.waitForTimeout(300)
|
|
44
|
+
|
|
45
|
+
const menuScrollView = page.getByTestId('menu-scroll-view')
|
|
46
|
+
await expect(menuScrollView).toBeVisible()
|
|
47
|
+
|
|
48
|
+
// check that scroll view has overflow (is scrollable)
|
|
49
|
+
const isScrollable = await menuScrollView.evaluate((el) => {
|
|
50
|
+
return el.scrollHeight > el.clientHeight
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
expect(isScrollable).toBe(true)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
test('scrollbars are hidden', async ({ page }) => {
|
|
57
|
+
await page.waitForLoadState('networkidle')
|
|
58
|
+
|
|
59
|
+
const trigger = page.getByTestId('menu-trigger')
|
|
60
|
+
await trigger.click()
|
|
61
|
+
await page.waitForTimeout(300)
|
|
62
|
+
|
|
63
|
+
const menuScrollView = page.getByTestId('menu-scroll-view')
|
|
64
|
+
await expect(menuScrollView).toBeVisible()
|
|
65
|
+
|
|
66
|
+
// check that scrollbar-width is none (Firefox/modern browsers)
|
|
67
|
+
const scrollbarWidth = await menuScrollView.evaluate((el) => {
|
|
68
|
+
return window.getComputedStyle(el).scrollbarWidth
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
expect(scrollbarWidth).toBe('none')
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
test('first item is visible and last item requires scrolling', async ({ page }) => {
|
|
75
|
+
await page.waitForLoadState('networkidle')
|
|
76
|
+
|
|
77
|
+
const trigger = page.getByTestId('menu-trigger')
|
|
78
|
+
await trigger.click()
|
|
79
|
+
await page.waitForTimeout(300)
|
|
80
|
+
|
|
81
|
+
const menuScrollView = page.getByTestId('menu-scroll-view')
|
|
82
|
+
await expect(menuScrollView).toBeVisible()
|
|
83
|
+
|
|
84
|
+
// first item should be visible
|
|
85
|
+
const firstItem = page.getByTestId('menu-item-1')
|
|
86
|
+
await expect(firstItem).toBeVisible()
|
|
87
|
+
|
|
88
|
+
// last item should exist but not be in view (requires scrolling)
|
|
89
|
+
const lastItem = page.getByTestId('menu-item-30')
|
|
90
|
+
await expect(lastItem).toBeAttached()
|
|
91
|
+
await expect(lastItem).not.toBeInViewport()
|
|
92
|
+
})
|
|
93
|
+
})
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
|
|
3
|
+
test.describe('Menu stayInFrame', () => {
|
|
4
|
+
test('Menu bottom placement should not cover trigger', async ({ page }) => {
|
|
5
|
+
// Small viewport to test constraint behavior
|
|
6
|
+
await page.setViewportSize({ width: 400, height: 300 })
|
|
7
|
+
|
|
8
|
+
await page.goto('/?test=MenuBottomCase')
|
|
9
|
+
await page.waitForTimeout(500)
|
|
10
|
+
|
|
11
|
+
const trigger = page.getByTestId('menu-trigger')
|
|
12
|
+
const triggerBox = await trigger.boundingBox()
|
|
13
|
+
await trigger.click()
|
|
14
|
+
await page.waitForTimeout(300)
|
|
15
|
+
|
|
16
|
+
const menuContent = page.getByTestId('menu-content')
|
|
17
|
+
await expect(menuContent).toBeVisible()
|
|
18
|
+
|
|
19
|
+
const menuBox = await menuContent.boundingBox()
|
|
20
|
+
const viewport = page.viewportSize()!
|
|
21
|
+
const padding = 10
|
|
22
|
+
|
|
23
|
+
// Menu should be BELOW the trigger (placement="bottom-start", allowFlip={false})
|
|
24
|
+
// Menu top should be >= trigger bottom (with some tolerance for offset)
|
|
25
|
+
expect(menuBox!.y).toBeGreaterThanOrEqual(triggerBox!.y + triggerBox!.height - 5)
|
|
26
|
+
|
|
27
|
+
// Menu should fit within viewport with padding
|
|
28
|
+
expect(menuBox!.y + menuBox!.height).toBeLessThanOrEqual(
|
|
29
|
+
viewport.height - padding + 2
|
|
30
|
+
)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test('menu should not overflow viewport when near bottom edge', async ({ page }) => {
|
|
34
|
+
// Set a small viewport to make it easier to test overflow
|
|
35
|
+
await page.setViewportSize({ width: 400, height: 300 })
|
|
36
|
+
|
|
37
|
+
await page.goto('/?test=MenuOverflowCase')
|
|
38
|
+
await page.waitForTimeout(500)
|
|
39
|
+
|
|
40
|
+
// Click the menu trigger (it's at the bottom of the page in this test case)
|
|
41
|
+
const trigger = page.getByTestId('menu-trigger')
|
|
42
|
+
await trigger.click()
|
|
43
|
+
await page.waitForTimeout(300)
|
|
44
|
+
|
|
45
|
+
// Get the menu content element
|
|
46
|
+
const menuContent = page.getByTestId('menu-content')
|
|
47
|
+
await expect(menuContent).toBeVisible()
|
|
48
|
+
|
|
49
|
+
// Get the bounding box of the menu
|
|
50
|
+
const menuBox = await menuContent.boundingBox()
|
|
51
|
+
expect(menuBox).not.toBeNull()
|
|
52
|
+
|
|
53
|
+
// Get viewport size
|
|
54
|
+
const viewport = page.viewportSize()
|
|
55
|
+
expect(viewport).not.toBeNull()
|
|
56
|
+
|
|
57
|
+
// Menu should not overflow the viewport with 10px padding
|
|
58
|
+
const padding = 10
|
|
59
|
+
|
|
60
|
+
// Check that menu has at least 10px padding from top
|
|
61
|
+
expect(menuBox!.y).toBeGreaterThanOrEqual(padding - 2) // 2px tolerance
|
|
62
|
+
|
|
63
|
+
// Check that menu has at least 10px padding from bottom
|
|
64
|
+
expect(menuBox!.y + menuBox!.height).toBeLessThanOrEqual(
|
|
65
|
+
viewport!.height - padding + 2
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
// Check that menu right doesn't exceed viewport right
|
|
69
|
+
expect(menuBox!.x + menuBox!.width).toBeLessThanOrEqual(viewport!.width - padding + 5)
|
|
70
|
+
|
|
71
|
+
// Check that menu left doesn't go past viewport left
|
|
72
|
+
expect(menuBox!.x).toBeGreaterThanOrEqual(padding - 5)
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
test('menu should flip when not enough space below', async ({ page }) => {
|
|
76
|
+
await page.setViewportSize({ width: 400, height: 250 })
|
|
77
|
+
|
|
78
|
+
await page.goto('/?test=MenuOverflowCase')
|
|
79
|
+
await page.waitForTimeout(500)
|
|
80
|
+
|
|
81
|
+
const trigger = page.getByTestId('menu-trigger')
|
|
82
|
+
const triggerBox = await trigger.boundingBox()
|
|
83
|
+
|
|
84
|
+
await trigger.click()
|
|
85
|
+
await page.waitForTimeout(300)
|
|
86
|
+
|
|
87
|
+
const menuContent = page.getByTestId('menu-content')
|
|
88
|
+
await expect(menuContent).toBeVisible()
|
|
89
|
+
|
|
90
|
+
const menuBox = await menuContent.boundingBox()
|
|
91
|
+
expect(menuBox).not.toBeNull()
|
|
92
|
+
expect(triggerBox).not.toBeNull()
|
|
93
|
+
|
|
94
|
+
// Since trigger is at bottom and viewport is small, menu should flip to appear above
|
|
95
|
+
// OR stay within bounds via shift
|
|
96
|
+
const viewport = page.viewportSize()!
|
|
97
|
+
|
|
98
|
+
// The key assertion: menu should be fully visible within viewport
|
|
99
|
+
expect(menuBox!.y).toBeGreaterThanOrEqual(0)
|
|
100
|
+
expect(menuBox!.y + menuBox!.height).toBeLessThanOrEqual(viewport.height)
|
|
101
|
+
})
|
|
102
|
+
})
|