@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,195 @@
|
|
|
1
|
+
import { expect, test, type Page } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ANIMATION TIMING BUG FIX TESTS
|
|
6
|
+
*
|
|
7
|
+
* Tests for two bugs:
|
|
8
|
+
* 1. Enter/exit timing not respected - enter: '50ms' should actually be 50ms
|
|
9
|
+
* 2. Duration normalization - duration: 1 should be 1ms, not 1 second
|
|
10
|
+
*
|
|
11
|
+
* These tests run across all animation drivers (css, native, reanimated, motion).
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
async function getOpacity(page: Page, testId: string): Promise<number> {
|
|
15
|
+
return page.evaluate((id) => {
|
|
16
|
+
const el = document.querySelector(`[data-testid="${id}"]`)
|
|
17
|
+
if (!el) return -1
|
|
18
|
+
return Number.parseFloat(getComputedStyle(el).opacity)
|
|
19
|
+
}, testId)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function elementExists(page: Page, testId: string): Promise<boolean> {
|
|
23
|
+
return page.evaluate((id) => !!document.querySelector(`[data-testid="${id}"]`), testId)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
test.describe('Animation Timing Bug Fixes', () => {
|
|
27
|
+
// animation timing tests are flaky in CI due to timing variations - add retries
|
|
28
|
+
test.describe.configure({ retries: 3 })
|
|
29
|
+
|
|
30
|
+
test.beforeEach(async ({ page }) => {
|
|
31
|
+
const driver = (test.info().project?.metadata as any)?.animationDriver
|
|
32
|
+
test.skip(driver === 'native', 'native driver has element detection issues on web')
|
|
33
|
+
|
|
34
|
+
await setupPage(page, {
|
|
35
|
+
name: 'AnimationComprehensiveCase',
|
|
36
|
+
type: 'useCase',
|
|
37
|
+
})
|
|
38
|
+
// wait for initial render - CI can be slow, allow more time
|
|
39
|
+
await page.waitForTimeout(1500)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
test('scenario 50: enter timing (200ms) should be faster than exit timing (1000ms)', async ({
|
|
43
|
+
page,
|
|
44
|
+
}) => {
|
|
45
|
+
// first hide element (exit with 1000ms)
|
|
46
|
+
expect(await elementExists(page, 'scenario-50-target'), 'Initially visible').toBe(
|
|
47
|
+
true
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
// trigger exit and measure how long it takes
|
|
51
|
+
const exitStart = Date.now()
|
|
52
|
+
await page.getByTestId('scenario-50-trigger').click()
|
|
53
|
+
|
|
54
|
+
// wait for exit to complete (element disappears)
|
|
55
|
+
await page.waitForFunction(
|
|
56
|
+
(testId) => !document.querySelector(`[data-testid="${testId}"]`),
|
|
57
|
+
'scenario-50-target',
|
|
58
|
+
{ timeout: 3000 }
|
|
59
|
+
)
|
|
60
|
+
const exitDuration = Date.now() - exitStart
|
|
61
|
+
|
|
62
|
+
// exit animation is 1000ms - should take at least 800ms (allowing some tolerance)
|
|
63
|
+
// this verifies it's using the slow exit timing, not fast enter timing
|
|
64
|
+
expect(
|
|
65
|
+
exitDuration,
|
|
66
|
+
`Exit should take ~1000ms (got ${exitDuration}ms)`
|
|
67
|
+
).toBeGreaterThan(700)
|
|
68
|
+
|
|
69
|
+
// trigger enter and measure how long it takes
|
|
70
|
+
const enterStart = Date.now()
|
|
71
|
+
await page.getByTestId('scenario-50-trigger').click()
|
|
72
|
+
|
|
73
|
+
// wait for element to appear and reach full opacity
|
|
74
|
+
await page.waitForFunction(
|
|
75
|
+
(testId) => {
|
|
76
|
+
const el = document.querySelector(`[data-testid="${testId}"]`)
|
|
77
|
+
if (!el) return false
|
|
78
|
+
const opacity = Number.parseFloat(getComputedStyle(el).opacity)
|
|
79
|
+
return opacity > 0.9
|
|
80
|
+
},
|
|
81
|
+
'scenario-50-target',
|
|
82
|
+
{ timeout: 2000 }
|
|
83
|
+
)
|
|
84
|
+
const enterDuration = Date.now() - enterStart
|
|
85
|
+
|
|
86
|
+
// enter animation is 200ms - should complete in under 500ms (with overhead)
|
|
87
|
+
// more importantly, it should be significantly faster than exit
|
|
88
|
+
expect(
|
|
89
|
+
enterDuration,
|
|
90
|
+
`Enter should complete quickly (~200ms), got ${enterDuration}ms`
|
|
91
|
+
).toBeLessThan(600)
|
|
92
|
+
|
|
93
|
+
// the key assertion: enter should be significantly faster than exit
|
|
94
|
+
expect(
|
|
95
|
+
enterDuration,
|
|
96
|
+
`Enter (${enterDuration}ms) should be faster than exit (${exitDuration}ms)`
|
|
97
|
+
).toBeLessThan(exitDuration * 0.8)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
test('scenario 51: duration: 1 should be 1ms (instant), not 1 second', async ({
|
|
101
|
+
page,
|
|
102
|
+
}) => {
|
|
103
|
+
expect(await elementExists(page, 'scenario-51-target'), 'Initially visible').toBe(
|
|
104
|
+
true
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
// trigger exit with duration: 1 (should be 1ms = instant)
|
|
108
|
+
await page.getByTestId('scenario-51-trigger').click()
|
|
109
|
+
|
|
110
|
+
// if duration is correctly 1ms, element should be gone almost immediately
|
|
111
|
+
// wait just 50ms - if it's treating 1 as 1 second, element would still exist
|
|
112
|
+
await page.waitForTimeout(50)
|
|
113
|
+
|
|
114
|
+
// BUG CHECK: element should be gone by now if duration is 1ms
|
|
115
|
+
// if duration is being treated as 1 second, element would still be visible
|
|
116
|
+
const stillExists = await elementExists(page, 'scenario-51-target')
|
|
117
|
+
|
|
118
|
+
// if element still exists, check opacity - should be near 0 if 1ms animation
|
|
119
|
+
if (stillExists) {
|
|
120
|
+
const opacity = await getOpacity(page, 'scenario-51-target')
|
|
121
|
+
// if duration is 1ms, opacity should be at 0 (animation complete)
|
|
122
|
+
// if duration is 1s, opacity would be ~0.95 at 50ms
|
|
123
|
+
expect(
|
|
124
|
+
opacity,
|
|
125
|
+
`Opacity should be near 0 at 50ms if duration is 1ms (got ${opacity})`
|
|
126
|
+
).toBeLessThan(0.2)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// definitely should be gone by 200ms
|
|
130
|
+
await page.waitForTimeout(200)
|
|
131
|
+
expect(
|
|
132
|
+
await elementExists(page, 'scenario-51-target'),
|
|
133
|
+
'Should be gone by 200ms'
|
|
134
|
+
).toBe(false)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
test('scenario 51: verify animation is fast (not 1 second)', async ({ page }) => {
|
|
138
|
+
expect(await elementExists(page, 'scenario-51-target'), 'Initially visible').toBe(
|
|
139
|
+
true
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
const startTime = Date.now()
|
|
143
|
+
|
|
144
|
+
// trigger exit
|
|
145
|
+
await page.getByTestId('scenario-51-trigger').click()
|
|
146
|
+
|
|
147
|
+
// wait for element to disappear
|
|
148
|
+
await page.waitForFunction(
|
|
149
|
+
(testId) => !document.querySelector(`[data-testid="${testId}"]`),
|
|
150
|
+
'scenario-51-target',
|
|
151
|
+
{ timeout: 3000 }
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
const exitDuration = Date.now() - startTime
|
|
155
|
+
|
|
156
|
+
// BUG CHECK: if duration is 1ms, exit should complete well under 1 second
|
|
157
|
+
// if duration is 1 second, it would take > 1000ms
|
|
158
|
+
// CI environments can have 500-800ms+ overhead, so use generous threshold
|
|
159
|
+
const threshold = process.env.CI ? 2000 : 1000
|
|
160
|
+
expect(
|
|
161
|
+
exitDuration,
|
|
162
|
+
`Exit with duration:1 should complete quickly, not take ${exitDuration}ms`
|
|
163
|
+
).toBeLessThan(threshold)
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
test('scenario 52: inline duration override should be in milliseconds', async ({
|
|
167
|
+
page,
|
|
168
|
+
}) => {
|
|
169
|
+
// base is 100ms, override is duration: 50 (should be 50ms)
|
|
170
|
+
expect(await elementExists(page, 'scenario-52-target'), 'Initially visible').toBe(
|
|
171
|
+
true
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
const startTime = Date.now()
|
|
175
|
+
|
|
176
|
+
// trigger exit
|
|
177
|
+
await page.getByTestId('scenario-52-trigger').click()
|
|
178
|
+
|
|
179
|
+
// wait for exit
|
|
180
|
+
await page.waitForFunction(
|
|
181
|
+
(testId) => !document.querySelector(`[data-testid="${testId}"]`),
|
|
182
|
+
'scenario-52-target',
|
|
183
|
+
{ timeout: 3000 }
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
const exitDuration = Date.now() - startTime
|
|
187
|
+
|
|
188
|
+
// animation is 50ms + overhead, CI can add 500-800ms+ overhead
|
|
189
|
+
const threshold = process.env.CI ? 2000 : 1000
|
|
190
|
+
expect(
|
|
191
|
+
exitDuration,
|
|
192
|
+
`Exit with duration:50 should complete in well under 1s (got ${exitDuration}ms)`
|
|
193
|
+
).toBeLessThan(threshold)
|
|
194
|
+
})
|
|
195
|
+
})
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { expect, test, type Page } from '@playwright/test'
|
|
2
|
+
import { setupPage } from './test-utils'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Tests for animated properties responding to media query changes.
|
|
6
|
+
*
|
|
7
|
+
* This tests the useStyleEmitter path which allows style updates without re-renders.
|
|
8
|
+
* When media queries change, the animation driver receives new styles and must
|
|
9
|
+
* update the DOM accordingly.
|
|
10
|
+
*
|
|
11
|
+
* Note: The 'native' driver (animations-react-native) doesn't support avoidReRenders/useStyleEmitter,
|
|
12
|
+
* so these tests are skipped for that driver.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
async function getScale(page: Page, testId: string): Promise<number> {
|
|
16
|
+
return page.evaluate((id) => {
|
|
17
|
+
const el = document.querySelector(`[data-testid="${id}"]`)
|
|
18
|
+
if (!el) return -1
|
|
19
|
+
const transform = getComputedStyle(el).transform
|
|
20
|
+
if (transform === 'none') return 1
|
|
21
|
+
// matrix(a, b, c, d, tx, ty) - scaleX is in the 'a' position
|
|
22
|
+
const match = transform.match(/matrix\(([^,]+),/)
|
|
23
|
+
return match ? Number.parseFloat(match[1]) : 1
|
|
24
|
+
}, testId)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// poll until scale reaches expected value (spring animations may be slow in CI)
|
|
28
|
+
async function waitForScale(
|
|
29
|
+
page: Page,
|
|
30
|
+
testId: string,
|
|
31
|
+
expected: number,
|
|
32
|
+
tolerance = 0.05,
|
|
33
|
+
timeoutMs = process.env.CI ? 5000 : 2000
|
|
34
|
+
): Promise<number> {
|
|
35
|
+
const start = Date.now()
|
|
36
|
+
let last = -1
|
|
37
|
+
while (Date.now() - start < timeoutMs) {
|
|
38
|
+
last = await getScale(page, testId)
|
|
39
|
+
if (Math.abs(last - expected) <= tolerance) return last
|
|
40
|
+
await page.waitForTimeout(50)
|
|
41
|
+
}
|
|
42
|
+
return last
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function getTranslateX(page: Page, testId: string): Promise<number> {
|
|
46
|
+
return page.evaluate((id) => {
|
|
47
|
+
const el = document.querySelector(`[data-testid="${id}"]`)
|
|
48
|
+
if (!el) return NaN
|
|
49
|
+
const transform = getComputedStyle(el).transform
|
|
50
|
+
if (transform === 'none') return 0
|
|
51
|
+
// matrix(a, b, c, d, tx, ty)
|
|
52
|
+
const matrixMatch = transform.match(/matrix\(([^)]+)\)/)
|
|
53
|
+
if (matrixMatch) {
|
|
54
|
+
const values = matrixMatch[1].split(',').map((v: string) => parseFloat(v.trim()))
|
|
55
|
+
return values[4] || 0
|
|
56
|
+
}
|
|
57
|
+
return 0
|
|
58
|
+
}, testId)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
test.describe('Animations With Media Queries', () => {
|
|
62
|
+
test.beforeEach(async ({ page }, testInfo) => {
|
|
63
|
+
// Skip native driver - it doesn't support useStyleEmitter (avoidReRenders)
|
|
64
|
+
test.skip(
|
|
65
|
+
testInfo.project.name === 'animated-native',
|
|
66
|
+
'Native driver does not support avoidReRenders/useStyleEmitter'
|
|
67
|
+
)
|
|
68
|
+
await setupPage(page, { name: 'AnimationsWithMediaQueriesCase', type: 'useCase' })
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test('scale applies at large viewport', async ({ page }) => {
|
|
72
|
+
await page.setViewportSize({ width: 1200, height: 800 })
|
|
73
|
+
const scale = await waitForScale(page, 'test-scale', 1)
|
|
74
|
+
expect(scale, 'scale should be 1 at large viewport').toBeCloseTo(1, 1)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('scale applies at small viewport', async ({ page }) => {
|
|
78
|
+
await page.setViewportSize({ width: 600, height: 800 })
|
|
79
|
+
const scale = await waitForScale(page, 'test-scale', 0.75)
|
|
80
|
+
expect(scale, 'scale should be 0.75 at $sm').toBeCloseTo(0.75, 1)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
test('scale updates when resizing from large to small', async ({ page }) => {
|
|
84
|
+
await page.setViewportSize({ width: 1200, height: 800 })
|
|
85
|
+
let scale = await waitForScale(page, 'test-scale', 1)
|
|
86
|
+
expect(scale, 'large viewport: scale=1').toBeCloseTo(1, 1)
|
|
87
|
+
|
|
88
|
+
await page.setViewportSize({ width: 600, height: 800 })
|
|
89
|
+
scale = await waitForScale(page, 'test-scale', 0.75)
|
|
90
|
+
expect(scale, 'small viewport: scale=0.75').toBeCloseTo(0.75, 1)
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
test('scale updates when resizing from small to large', async ({ page }) => {
|
|
94
|
+
await page.setViewportSize({ width: 600, height: 800 })
|
|
95
|
+
let scale = await waitForScale(page, 'test-scale', 0.75)
|
|
96
|
+
expect(scale, 'small viewport: scale=0.75').toBeCloseTo(0.75, 1)
|
|
97
|
+
|
|
98
|
+
await page.setViewportSize({ width: 1200, height: 800 })
|
|
99
|
+
scale = await waitForScale(page, 'test-scale', 1)
|
|
100
|
+
expect(scale, 'large viewport: scale=1').toBeCloseTo(1, 1)
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
test('scale updates on multiple resize cycles', async ({ page }) => {
|
|
104
|
+
await page.setViewportSize({ width: 1200, height: 800 })
|
|
105
|
+
await waitForScale(page, 'test-scale', 1)
|
|
106
|
+
|
|
107
|
+
// cycle 1: large -> small -> large
|
|
108
|
+
await page.setViewportSize({ width: 600, height: 800 })
|
|
109
|
+
let scale = await waitForScale(page, 'test-scale', 0.75)
|
|
110
|
+
expect(scale, 'cycle 1 small: scale=0.75').toBeCloseTo(0.75, 1)
|
|
111
|
+
|
|
112
|
+
await page.setViewportSize({ width: 1200, height: 800 })
|
|
113
|
+
scale = await waitForScale(page, 'test-scale', 1)
|
|
114
|
+
expect(scale, 'cycle 1 large: scale=1').toBeCloseTo(1, 1)
|
|
115
|
+
|
|
116
|
+
// cycle 2
|
|
117
|
+
await page.setViewportSize({ width: 600, height: 800 })
|
|
118
|
+
scale = await waitForScale(page, 'test-scale', 0.75)
|
|
119
|
+
expect(scale, 'cycle 2 small: scale=0.75').toBeCloseTo(0.75, 1)
|
|
120
|
+
|
|
121
|
+
await page.setViewportSize({ width: 1200, height: 800 })
|
|
122
|
+
scale = await waitForScale(page, 'test-scale', 1)
|
|
123
|
+
expect(scale, 'cycle 2 large: scale=1').toBeCloseTo(1, 1)
|
|
124
|
+
|
|
125
|
+
// cycle 3
|
|
126
|
+
await page.setViewportSize({ width: 600, height: 800 })
|
|
127
|
+
scale = await waitForScale(page, 'test-scale', 0.75)
|
|
128
|
+
expect(scale, 'cycle 3 small: scale=0.75').toBeCloseTo(0.75, 1)
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
test('translateX updates on resize', async ({ page }) => {
|
|
132
|
+
await page.setViewportSize({ width: 1200, height: 800 })
|
|
133
|
+
await page.waitForTimeout(1000)
|
|
134
|
+
|
|
135
|
+
let x = await getTranslateX(page, 'test-translate')
|
|
136
|
+
expect(x, 'large viewport: x=10').toBeCloseTo(10, 0)
|
|
137
|
+
|
|
138
|
+
await page.setViewportSize({ width: 600, height: 800 })
|
|
139
|
+
await page.waitForTimeout(1000)
|
|
140
|
+
|
|
141
|
+
x = await getTranslateX(page, 'test-translate')
|
|
142
|
+
expect(x, 'small viewport: x=50').toBeCloseTo(50, -1) // precision -1 allows ±5
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
test('combined scale + translate updates on resize', async ({ page }) => {
|
|
146
|
+
await page.setViewportSize({ width: 1200, height: 800 })
|
|
147
|
+
let scale = await waitForScale(page, 'test-combined', 1)
|
|
148
|
+
expect(scale, 'large viewport: scale=1').toBeCloseTo(1, 1)
|
|
149
|
+
|
|
150
|
+
await page.setViewportSize({ width: 600, height: 800 })
|
|
151
|
+
scale = await waitForScale(page, 'test-combined', 0.75)
|
|
152
|
+
expect(scale, 'small viewport: scale=0.75').toBeCloseTo(0.75, 1)
|
|
153
|
+
})
|
|
154
|
+
})
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { getSize, getSpace } from '@hanzogui/get-token'
|
|
2
|
+
import type { SizeTokens } from '@hanzogui/web'
|
|
3
|
+
import {
|
|
4
|
+
GetProps,
|
|
5
|
+
View,
|
|
6
|
+
Text,
|
|
7
|
+
createStyledContext,
|
|
8
|
+
styled,
|
|
9
|
+
useTheme,
|
|
10
|
+
withStaticProperties,
|
|
11
|
+
} from '@hanzogui/web'
|
|
12
|
+
import { cloneElement, useContext } from 'react'
|
|
13
|
+
|
|
14
|
+
export const ButtonContext = createStyledContext({
|
|
15
|
+
size: '$md' as SizeTokens,
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
export const ButtonFrame = styled(View, {
|
|
19
|
+
name: 'Button',
|
|
20
|
+
context: ButtonContext,
|
|
21
|
+
backgroundColor: '$background',
|
|
22
|
+
alignItems: 'center',
|
|
23
|
+
flexDirection: 'row',
|
|
24
|
+
|
|
25
|
+
hoverStyle: {
|
|
26
|
+
backgroundColor: '$backgroundHover',
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
pressStyle: {
|
|
30
|
+
backgroundColor: '$backgroundPress',
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
variants: {
|
|
34
|
+
size: {
|
|
35
|
+
'...size': (name, { tokens }) => {
|
|
36
|
+
return {
|
|
37
|
+
height: tokens.size[name],
|
|
38
|
+
borderRadius: tokens.radius[name],
|
|
39
|
+
// note the getSpace and getSize helpers will let you shift down/up token sizes
|
|
40
|
+
// whereas with gap we just multiply by 0.2
|
|
41
|
+
// this is a stylistic choice, and depends on your design system values
|
|
42
|
+
gap: tokens.space[name].val * 0.2,
|
|
43
|
+
paddingHorizontal: getSpace(name, {
|
|
44
|
+
shift: -1,
|
|
45
|
+
}),
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
} as const,
|
|
50
|
+
|
|
51
|
+
defaultVariants: {
|
|
52
|
+
size: '$true',
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
export const ButtonText = styled(Text, {
|
|
57
|
+
name: 'ButtonText',
|
|
58
|
+
context: ButtonContext,
|
|
59
|
+
color: '$color',
|
|
60
|
+
userSelect: 'none',
|
|
61
|
+
|
|
62
|
+
variants: {
|
|
63
|
+
size: {
|
|
64
|
+
'...fontSize': (name, { font }) => ({
|
|
65
|
+
fontSize: font?.size[name],
|
|
66
|
+
}),
|
|
67
|
+
},
|
|
68
|
+
} as const,
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
const ButtonIcon = (props: { children: any }) => {
|
|
72
|
+
const { size } = useContext(ButtonContext.context)
|
|
73
|
+
const smaller = getSize(size, {
|
|
74
|
+
shift: -2,
|
|
75
|
+
})
|
|
76
|
+
const theme = useTheme()
|
|
77
|
+
return cloneElement(props.children, {
|
|
78
|
+
size: smaller.val * 0.5,
|
|
79
|
+
color: theme.color.get(),
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export const Button = withStaticProperties(ButtonFrame, {
|
|
84
|
+
Props: ButtonContext.Provider,
|
|
85
|
+
Text: ButtonText,
|
|
86
|
+
Icon: ButtonIcon,
|
|
87
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
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: 'ButtonCircular', type: 'useCase' })
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
test(`tag button + circular prop works`, async ({ page }) => {
|
|
10
|
+
const styles = await page.locator('button#circular').evaluate((el) => {
|
|
11
|
+
return window.getComputedStyle(el)
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
expect(styles.width).toBe(`44px`)
|
|
15
|
+
expect(styles.height).toBe(styles.width)
|
|
16
|
+
expect(styles.borderRadius).toBe(`100000px`)
|
|
17
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
|
|
3
|
+
import { setupPage } from './test-utils'
|
|
4
|
+
import { getStyles } from './utils'
|
|
5
|
+
|
|
6
|
+
test.beforeEach(async ({ page }) => {
|
|
7
|
+
await setupPage(page, { name: 'ButtonCustom', type: 'useCase' })
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
test(`keeps flex direction for styled(Button)`, async ({ page }) => {
|
|
11
|
+
const styles1 = await getStyles(page.getByTestId('button').first())
|
|
12
|
+
const styles2 = await getStyles(page.getByTestId('button-styled').first())
|
|
13
|
+
|
|
14
|
+
// should match
|
|
15
|
+
expect(styles1.flexDirection).toBe('row')
|
|
16
|
+
expect(styles2.flexDirection).toBe('row')
|
|
17
|
+
})
|
|
@@ -0,0 +1,23 @@
|
|
|
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: 'ButtonIconColor', type: 'useCase' })
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
test(`button icon receives color from theme`, async ({ page }) => {
|
|
10
|
+
const button = page.getByTestId('button-themed')
|
|
11
|
+
const path = button.locator('svg path').first()
|
|
12
|
+
const stroke = await path.evaluate((el) => getComputedStyle(el).stroke)
|
|
13
|
+
expect(stroke).toBeTruthy()
|
|
14
|
+
expect(stroke).not.toBe('none')
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
test(`listitem icon receives color from theme`, async ({ page }) => {
|
|
18
|
+
const listitem = page.getByTestId('listitem-themed')
|
|
19
|
+
const path = listitem.locator('svg path').first()
|
|
20
|
+
const stroke = await path.evaluate((el) => getComputedStyle(el).stroke)
|
|
21
|
+
expect(stroke).toBeTruthy()
|
|
22
|
+
expect(stroke).not.toBe('none')
|
|
23
|
+
})
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { expect, test } from '@playwright/test'
|
|
2
|
+
|
|
3
|
+
import { setupPage } from './test-utils'
|
|
4
|
+
import { getStyles, whilePressed } from './utils'
|
|
5
|
+
|
|
6
|
+
test.beforeEach(async ({ page }) => {
|
|
7
|
+
await setupPage(page, { name: 'ButtonUnstyled', type: 'useCase' })
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
function expectEmptyStyles(styles: any) {
|
|
11
|
+
expect(styles.backgroundColor).toBe(`rgba(0, 0, 0, 0)`)
|
|
12
|
+
expect(styles.padding).toBe(`0px`)
|
|
13
|
+
expect(styles.borderWidth).toBe(`0px`)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
test(`unstyled prop works when used with styled()`, async ({ page }) => {
|
|
17
|
+
const button = page.locator('#unstyled-inline')
|
|
18
|
+
const styles = await getStyles(button)
|
|
19
|
+
|
|
20
|
+
expectEmptyStyles(styles)
|
|
21
|
+
|
|
22
|
+
await whilePressed(button, async () => {
|
|
23
|
+
const pressStyles = await getStyles(button)
|
|
24
|
+
expectEmptyStyles(pressStyles)
|
|
25
|
+
})
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
test(`unstyled prop works when used with styled() + merges when its own variant unstyled is also set`, async ({
|
|
29
|
+
page,
|
|
30
|
+
}) => {
|
|
31
|
+
const button = page.locator('#unstyled-merged')
|
|
32
|
+
const styles = await getStyles(button)
|
|
33
|
+
|
|
34
|
+
expect(styles.backgroundColor).toBe(`rgba(0, 0, 0, 0)`)
|
|
35
|
+
expect(styles.borderLeftWidth).toBe('2px')
|
|
36
|
+
expect(styles.borderColor).toBe('rgb(0, 128, 0)')
|
|
37
|
+
|
|
38
|
+
await whilePressed(button, async () => {
|
|
39
|
+
const pressStyles = await getStyles(button)
|
|
40
|
+
expect(styles.backgroundColor).toBe(`rgba(0, 0, 0, 0)`)
|
|
41
|
+
expect(pressStyles.borderLeftWidth).toBe('2px')
|
|
42
|
+
expect(pressStyles.borderColor).toBe('rgb(0, 128, 0)')
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test(`unstyled prop works when used inline`, async ({ page }) => {
|
|
47
|
+
const button = page.locator('#unstyled-styled')
|
|
48
|
+
const styles = await getStyles(button)
|
|
49
|
+
|
|
50
|
+
expectEmptyStyles(styles)
|
|
51
|
+
|
|
52
|
+
await whilePressed(button, async () => {
|
|
53
|
+
const pressStyles = await getStyles(button)
|
|
54
|
+
expectEmptyStyles(pressStyles)
|
|
55
|
+
})
|
|
56
|
+
})
|