@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.
Files changed (431) hide show
  1. package/.detoxrc.js +130 -0
  2. package/.env.production +2 -0
  3. package/.maestro/config.yaml +4 -0
  4. package/.maestro/flows/shorthand-variables.yaml +23 -0
  5. package/.watchmanconfig +1 -0
  6. package/LICENSE +21 -0
  7. package/README.md +11 -0
  8. package/app.json +43 -0
  9. package/assets/adaptive-icon.png +0 -0
  10. package/assets/favicon.png +0 -0
  11. package/assets/icon.png +0 -0
  12. package/assets/splash.png +0 -0
  13. package/babel.config.js +25 -0
  14. package/e2e/CompilerExtraction.test.ts +147 -0
  15. package/e2e/GroupPressNative.test.ts +167 -0
  16. package/e2e/MediaQueryGtMd.test.ts +71 -0
  17. package/e2e/NativePortal.test.ts +113 -0
  18. package/e2e/PointerEvents.test.ts +116 -0
  19. package/e2e/PressStyleNative.noRngh.test.ts +191 -0
  20. package/e2e/PressStyleNative.test.ts +231 -0
  21. package/e2e/SafeArea.test.ts +57 -0
  22. package/e2e/SelectAndroidOnPress.test.ts +181 -0
  23. package/e2e/SelectRemount.test.ts +137 -0
  24. package/e2e/SheetDragResist.test.ts +370 -0
  25. package/e2e/SheetKeyboardDrag.test.ts +249 -0
  26. package/e2e/SheetScrollableDrag.test.ts +560 -0
  27. package/e2e/ShorthandVariables.test.ts +53 -0
  28. package/e2e/ThemeChangeBasic.test.ts +123 -0
  29. package/e2e/ThemeMutation.test.ts +80 -0
  30. package/e2e/check-rngh-status.test.ts +31 -0
  31. package/e2e/jest.config.js +19 -0
  32. package/e2e/utils/colors.ts +75 -0
  33. package/e2e/utils/navigation.ts +53 -0
  34. package/eas.json +22 -0
  35. package/flows/AlertDialog.yaml +17 -0
  36. package/flows/OpenApp.yaml +25 -0
  37. package/flows/Select.yaml +13 -0
  38. package/flows/Sheet.yaml +12 -0
  39. package/flows/Tabs.yaml +13 -0
  40. package/flows/Toast.yaml +14 -0
  41. package/flows/WarmUp.yaml +24 -0
  42. package/index.html +21 -0
  43. package/index.js +17 -0
  44. package/metro.config.js +64 -0
  45. package/next-router-shim.ts +9 -0
  46. package/package.json +118 -0
  47. package/plans/toast-2.md +471 -0
  48. package/playwright.config.ts +71 -0
  49. package/plugins/expo-modules-core-swift6.js +76 -0
  50. package/pod-install.sh +7 -0
  51. package/public/favicon.svg +70 -0
  52. package/public/fonts/inter.css +15 -0
  53. package/public/fonts/noto-cn.otf +0 -0
  54. package/public/gui-icon.svg +68 -0
  55. package/run-detox.sh +230 -0
  56. package/run-native-tests.sh +4 -0
  57. package/run-tests-parallel.ts +195 -0
  58. package/screenshots/Screenshotter.test.tsx +48 -0
  59. package/src/AnimationDemos.tsx +131 -0
  60. package/src/App.native.tsx +121 -0
  61. package/src/App.tsx +121 -0
  62. package/src/Navigation.tsx +98 -0
  63. package/src/Sandbox.tsx +87 -0
  64. package/src/TestDynamicEval.tsx +33 -0
  65. package/src/TestNativeSheet.tsx +100 -0
  66. package/src/components/TimedRender.tsx +18 -0
  67. package/src/constants/test-ids.ts +52 -0
  68. package/src/features/demos/demo-screen.tsx +72 -0
  69. package/src/features/home/ColorSchemeListItem.tsx +41 -0
  70. package/src/features/home/TestBuildAButton.tsx +102 -0
  71. package/src/features/home/TestSeparator.tsx +0 -0
  72. package/src/features/home/screen.tsx +285 -0
  73. package/src/features/testcases/screen.tsx +59 -0
  74. package/src/features/testcases/test-screen.tsx +50 -0
  75. package/src/generatedV5Theme.ts +112 -0
  76. package/src/gui.config.ts +411 -0
  77. package/src/guy.png +0 -0
  78. package/src/index.tsx +6 -0
  79. package/src/provider/index.tsx +18 -0
  80. package/src/test-gui-stack.tsx +11 -0
  81. package/src/test.tsx +3 -0
  82. package/src/useKitchenSinkTheme.tsx +15 -0
  83. package/src/usecases/ActionsSheetComparison.tsx +194 -0
  84. package/src/usecases/AnimatePresenceEnterExitCase.tsx +255 -0
  85. package/src/usecases/AnimatePresenceExitTest.tsx +69 -0
  86. package/src/usecases/AnimatedByProp.tsx +39 -0
  87. package/src/usecases/AnimationComprehensiveCase.tsx +2515 -0
  88. package/src/usecases/AnimationValueLoggingCase.tsx +526 -0
  89. package/src/usecases/AnimationsWithMediaQueriesCase.tsx +110 -0
  90. package/src/usecases/Benchmark.tsx +148 -0
  91. package/src/usecases/BenchmarkSelect.tsx +34 -0
  92. package/src/usecases/ButtonCircular.tsx +3 -0
  93. package/src/usecases/ButtonCustom.tsx +33 -0
  94. package/src/usecases/ButtonIconColor.tsx +18 -0
  95. package/src/usecases/ButtonInverse.tsx +30 -0
  96. package/src/usecases/ButtonUnstyled.tsx +31 -0
  97. package/src/usecases/CheckboxDisabledOnPress.tsx +62 -0
  98. package/src/usecases/ClickDuringEnterCase.tsx +59 -0
  99. package/src/usecases/CodeExamplesInput.tsx +9 -0
  100. package/src/usecases/ColorTokenFallback.tsx +52 -0
  101. package/src/usecases/CompilerExtraction.tsx +380 -0
  102. package/src/usecases/ComplexVariants.tsx +164 -0
  103. package/src/usecases/CrashAdaptSheet.tsx +98 -0
  104. package/src/usecases/CustomStyledAnimatedPopover.tsx +42 -0
  105. package/src/usecases/CustomStyledAnimatedTooltip.tsx +72 -0
  106. package/src/usecases/DOMNodeAPIs.tsx +154 -0
  107. package/src/usecases/DialogFocusScopeCase.tsx +277 -0
  108. package/src/usecases/DialogFocusScopeDebug.tsx +85 -0
  109. package/src/usecases/DialogNestedCase.tsx +121 -0
  110. package/src/usecases/DialogOpenControlled.tsx +49 -0
  111. package/src/usecases/DialogPointerEventsCase.tsx +58 -0
  112. package/src/usecases/DialogScopedCase.tsx +106 -0
  113. package/src/usecases/DialogSheetAdaptCase.tsx +178 -0
  114. package/src/usecases/DialogSheetAdaptResizeCase.tsx +98 -0
  115. package/src/usecases/DismissLayerStackingCase.tsx +223 -0
  116. package/src/usecases/DriverDisableAnimationPropsCase.tsx +44 -0
  117. package/src/usecases/Example.tsx +10 -0
  118. package/src/usecases/ExitCompletionCase.tsx +713 -0
  119. package/src/usecases/FocusVisibleButton.tsx +14 -0
  120. package/src/usecases/FocusVisibleButtonPointer.tsx +13 -0
  121. package/src/usecases/FocusVisibleButtonWithFocusStyle.tsx +16 -0
  122. package/src/usecases/FocusWithinCase.tsx +55 -0
  123. package/src/usecases/FontTokensInVariants.tsx +14 -0
  124. package/src/usecases/FormButtonTypeCase.tsx +34 -0
  125. package/src/usecases/GlobalScopedTriggerIsolationCase.tsx +178 -0
  126. package/src/usecases/GroupHoverMobile.tsx +39 -0
  127. package/src/usecases/GroupPressInVariant.tsx +92 -0
  128. package/src/usecases/GroupPressNative.tsx +200 -0
  129. package/src/usecases/GroupProp.tsx +96 -0
  130. package/src/usecases/GroupPseudoVariantOverride.tsx +56 -0
  131. package/src/usecases/GroupUseCases.tsx +94 -0
  132. package/src/usecases/HeightMediaQueryOverrideCase.tsx +183 -0
  133. package/src/usecases/InputAutoFocusAfterMenuCase.tsx +105 -0
  134. package/src/usecases/InputAutoFocusStyledCase.tsx +39 -0
  135. package/src/usecases/KeyboardControllerTest.tsx +146 -0
  136. package/src/usecases/ListItem.tsx +123 -0
  137. package/src/usecases/MediaQueriesV5.tsx +137 -0
  138. package/src/usecases/MediaQueryGtMd.tsx +73 -0
  139. package/src/usecases/MenuAboveDialogCase.tsx +75 -0
  140. package/src/usecases/MenuAccessibilityCase.tsx +133 -0
  141. package/src/usecases/MenuAnimatePositionCase.tsx +41 -0
  142. package/src/usecases/MenuArrowAnimatePresenceCase.tsx +98 -0
  143. package/src/usecases/MenuAsChildPositionCase.tsx +24 -0
  144. package/src/usecases/MenuAutoResizeCase.tsx +57 -0
  145. package/src/usecases/MenuBottomCase.tsx +55 -0
  146. package/src/usecases/MenuFocusLeaveCase.tsx +135 -0
  147. package/src/usecases/MenuHighlightCase.tsx +44 -0
  148. package/src/usecases/MenuItemFocusCase.tsx +79 -0
  149. package/src/usecases/MenuItemPseudoOverrideCase.tsx +270 -0
  150. package/src/usecases/MenuMultiTriggerCase.tsx +47 -0
  151. package/src/usecases/MenuOverflowCase.tsx +60 -0
  152. package/src/usecases/MenuSubCase.tsx +223 -0
  153. package/src/usecases/MenuSubLeftCase.tsx +178 -0
  154. package/src/usecases/MenuSubNestedPositionCase.tsx +171 -0
  155. package/src/usecases/MenuSubStyledCase.tsx +145 -0
  156. package/src/usecases/MenuThemeCase.tsx +50 -0
  157. package/src/usecases/MenuUnstyledCase.tsx +52 -0
  158. package/src/usecases/MultiDriverAnimation.tsx +118 -0
  159. package/src/usecases/NativePortalTest.tsx +179 -0
  160. package/src/usecases/NewInputBasic.tsx +16 -0
  161. package/src/usecases/NewInputEvents.tsx +29 -0
  162. package/src/usecases/NonGuiTextStyledType.tsx +23 -0
  163. package/src/usecases/OnLayoutCase.tsx +134 -0
  164. package/src/usecases/OnLayoutScaleCase.tsx +88 -0
  165. package/src/usecases/OnLayoutStressCase.tsx +353 -0
  166. package/src/usecases/OpacityModifierCase.tsx +113 -0
  167. package/src/usecases/OverlayStyled.tsx +66 -0
  168. package/src/usecases/ParagraphSpanFontInheritance.tsx +53 -0
  169. package/src/usecases/PlaceholderTextColor.tsx +20 -0
  170. package/src/usecases/PointerEventsCase.tsx +100 -0
  171. package/src/usecases/PopoverAndMenuMultiTriggerCase.tsx +138 -0
  172. package/src/usecases/PopoverCase.tsx +222 -0
  173. package/src/usecases/PopoverContentStyledPlusAnimations.tsx +44 -0
  174. package/src/usecases/PopoverFocusScopeCase.tsx +171 -0
  175. package/src/usecases/PopoverHoverableCase.tsx +167 -0
  176. package/src/usecases/PopoverHoverableDisableClickCase.tsx +118 -0
  177. package/src/usecases/PopoverHoverableRapidCase.tsx +103 -0
  178. package/src/usecases/PopoverHoverableScopedCase.tsx +135 -0
  179. package/src/usecases/PopoverScopedCase.tsx +76 -0
  180. package/src/usecases/PopoverTriggerIsolationCase.tsx +80 -0
  181. package/src/usecases/PressStyleNative.tsx +143 -0
  182. package/src/usecases/PseudoStyleMerge.tsx +25 -0
  183. package/src/usecases/PseudoTransitionCase.tsx +174 -0
  184. package/src/usecases/RawAnimatedValueCase.tsx +231 -0
  185. package/src/usecases/RemoveScrollCase.tsx +66 -0
  186. package/src/usecases/RenderPropCase.tsx +263 -0
  187. package/src/usecases/SafeAreaCase.tsx +236 -0
  188. package/src/usecases/ScrollViewRefCase.tsx +88 -0
  189. package/src/usecases/SecondPage.tsx +5 -0
  190. package/src/usecases/SelectAndroidOnPress.tsx +129 -0
  191. package/src/usecases/SelectFocusScopeCase.tsx +270 -0
  192. package/src/usecases/SelectRemount.tsx +136 -0
  193. package/src/usecases/Shadows.tsx +5 -0
  194. package/src/usecases/SheetAnimationCase.tsx +155 -0
  195. package/src/usecases/SheetDragCase.tsx +183 -0
  196. package/src/usecases/SheetDragResistCase.tsx +433 -0
  197. package/src/usecases/SheetDragResistCase.web.tsx +359 -0
  198. package/src/usecases/SheetKeyboardDragCase.tsx +328 -0
  199. package/src/usecases/SheetKeyboardFitContentCase.tsx +165 -0
  200. package/src/usecases/SheetOnAnimationCompleteCase.tsx +54 -0
  201. package/src/usecases/SheetScrollLockCase.tsx +166 -0
  202. package/src/usecases/SheetScrollableDrag.tsx +249 -0
  203. package/src/usecases/SheetSnapPointsFitCase.tsx +393 -0
  204. package/src/usecases/ShorthandVariables.tsx +49 -0
  205. package/src/usecases/SlowThemeReRender.tsx +48 -0
  206. package/src/usecases/SpinnerCustomColors.tsx +34 -0
  207. package/src/usecases/StackZIndex.tsx +82 -0
  208. package/src/usecases/StressPage.tsx +301 -0
  209. package/src/usecases/StylePlatform.tsx +30 -0
  210. package/src/usecases/StyleProp.tsx +29 -0
  211. package/src/usecases/StyledAnchor.tsx +27 -0
  212. package/src/usecases/StyledButtonAnimationAuto.tsx +99 -0
  213. package/src/usecases/StyledButtonTheme.tsx +63 -0
  214. package/src/usecases/StyledButtonVariantPseudo.tsx +25 -0
  215. package/src/usecases/StyledButtonVariantPseudoMerge.tsx +77 -0
  216. package/src/usecases/StyledCheckboxTheme.tsx +23 -0
  217. package/src/usecases/StyledContextColor.tsx +246 -0
  218. package/src/usecases/StyledContextTokens.tsx +147 -0
  219. package/src/usecases/StyledHOCNamed.tsx +20 -0
  220. package/src/usecases/StyledHtmlCase.tsx +144 -0
  221. package/src/usecases/StyledIconColor.tsx +19 -0
  222. package/src/usecases/StyledInputFocusStyle.tsx +21 -0
  223. package/src/usecases/StyledInputOnFocus.tsx +30 -0
  224. package/src/usecases/StyledMediaQueryMerge.tsx +95 -0
  225. package/src/usecases/StyledOverridePsuedo.tsx +26 -0
  226. package/src/usecases/StyledRNW.tsx +61 -0
  227. package/src/usecases/StyledStyleableInputOnFocus.tsx +34 -0
  228. package/src/usecases/StyledStyleableInputVariant.tsx +48 -0
  229. package/src/usecases/StyledStyledStyleableInputOnFocus.tsx +36 -0
  230. package/src/usecases/StyledVariantTextColor.tsx +25 -0
  231. package/src/usecases/StyledViewOnFocus.tsx +32 -0
  232. package/src/usecases/TabHoverAnimationCase.tsx +212 -0
  233. package/src/usecases/TextNestedInheritance.tsx +80 -0
  234. package/src/usecases/ThemeChange.tsx +100 -0
  235. package/src/usecases/ThemeChangeBasic.tsx +52 -0
  236. package/src/usecases/ThemeComponentResolution.tsx +119 -0
  237. package/src/usecases/ThemeConditionalName.tsx +31 -0
  238. package/src/usecases/ThemeMediaAnimationCase.tsx +39 -0
  239. package/src/usecases/ThemeMutation.tsx +86 -0
  240. package/src/usecases/ThemeNested.tsx +103 -0
  241. package/src/usecases/ThemeReset.tsx +62 -0
  242. package/src/usecases/ThemeShallowCase.tsx +83 -0
  243. package/src/usecases/ToastCase.tsx +46 -0
  244. package/src/usecases/ToggleGroupActiveProps.tsx +40 -0
  245. package/src/usecases/ToggleGroupXGroupCase.tsx +104 -0
  246. package/src/usecases/TooltipAnimationCase.tsx +99 -0
  247. package/src/usecases/TooltipCase.tsx +32 -0
  248. package/src/usecases/TooltipGlobalPatternCase.tsx +83 -0
  249. package/src/usecases/TooltipGroupCase.tsx +102 -0
  250. package/src/usecases/TooltipMultiTriggerCase.tsx +88 -0
  251. package/src/usecases/TooltipPositionJumpCase.tsx +91 -0
  252. package/src/usecases/TooltipTriggerInlineCase.tsx +60 -0
  253. package/src/usecases/TransformMediaQueryMerge.tsx +98 -0
  254. package/src/usecases/UseCases.tsx +409 -0
  255. package/src/usecases/UseTheme.tsx +41 -0
  256. package/src/usecases/V5ThemeBuilderOutput.tsx +231 -0
  257. package/src/usecases/VariantFontFamily.tsx +25 -0
  258. package/src/usecases/VariantsOrder.tsx +117 -0
  259. package/src/usecases/ZIndex.tsx +155 -0
  260. package/src/usecases/helpers.tsx +44 -0
  261. package/src/usecases/index.native.ts +122 -0
  262. package/src/usecases/index.ts +3 -0
  263. package/src/usecases/index.web.ts +177 -0
  264. package/tests/AnimatePresenceEnterExit.animated.test.tsx +176 -0
  265. package/tests/AnimatedByProp.animated.test.tsx +138 -0
  266. package/tests/AnimationBehavior.animated.test.tsx +543 -0
  267. package/tests/AnimationTiming.animated.test.tsx +195 -0
  268. package/tests/AnimationsWithMediaQueries.animated.test.tsx +154 -0
  269. package/tests/BuildAButton.test.tsx +87 -0
  270. package/tests/ButtonCircular.test.tsx +17 -0
  271. package/tests/ButtonCustom.test.tsx +17 -0
  272. package/tests/ButtonIconColor.test.tsx +23 -0
  273. package/tests/ButtonUnstyled.test.tsx +56 -0
  274. package/tests/ClickDuringEnter.animated.test.tsx +174 -0
  275. package/tests/ColorTokenFallback.test.tsx +45 -0
  276. package/tests/DOMNodeAPIs.test.tsx +161 -0
  277. package/tests/DialogFocusScope.animated.test.tsx +309 -0
  278. package/tests/DialogNested.test.tsx +128 -0
  279. package/tests/DialogOpenControlled.test.tsx +42 -0
  280. package/tests/DialogPointerEvents.animated.test.tsx +108 -0
  281. package/tests/DialogScoped.test.tsx +137 -0
  282. package/tests/DialogSheetAdapt.test.tsx +68 -0
  283. package/tests/DialogSheetAdaptResize.test.tsx +161 -0
  284. package/tests/DismissLayerStacking.test.tsx +292 -0
  285. package/tests/DriverDisableAnimationProps.animated.test.tsx +157 -0
  286. package/tests/ExitCompletion.animated.test.tsx +425 -0
  287. package/tests/ExitTimingCheck.animated.test.ts +34 -0
  288. package/tests/FocusVisibleButton.test.tsx +41 -0
  289. package/tests/FocusVisibleButtonPointerFocus.test.tsx +23 -0
  290. package/tests/FocusVisibleButtonPointerFocusWithFocusStyle.test.tsx +40 -0
  291. package/tests/FocusWithinStyle.animated.test.tsx +66 -0
  292. package/tests/FocusWithinStyle.test.tsx +60 -0
  293. package/tests/FormButtonType.test.tsx +42 -0
  294. package/tests/GlobalScopedTriggerIsolation.test.tsx +89 -0
  295. package/tests/GroupHoverMobile.test.tsx +52 -0
  296. package/tests/GroupPressInVariant.test.tsx +82 -0
  297. package/tests/GroupProp.test.tsx +30 -0
  298. package/tests/GroupPseudoVariantOverride.test.tsx +57 -0
  299. package/tests/GroupUseCases.test.tsx +111 -0
  300. package/tests/GuiSiteMotion.test.ts +481 -0
  301. package/tests/HeightMediaQueryOverride.test.tsx +112 -0
  302. package/tests/InputAutoFocusAfterMenu.test.tsx +55 -0
  303. package/tests/InputAutoFocusStyled.test.tsx +22 -0
  304. package/tests/ListItem.test.tsx +129 -0
  305. package/tests/MediaQueriesV5.test.tsx +113 -0
  306. package/tests/MediaQueryGtMd.test.tsx +84 -0
  307. package/tests/MenuAboveDialog.test.tsx +108 -0
  308. package/tests/MenuAccessibility.test.tsx +346 -0
  309. package/tests/MenuAnimatePosition.animated.test.tsx +57 -0
  310. package/tests/MenuArrowAnimatePresence.animated.test.tsx +71 -0
  311. package/tests/MenuAsChildPosition.test.tsx +16 -0
  312. package/tests/MenuAutoResize.test.tsx +54 -0
  313. package/tests/MenuFocusLeave.test.tsx +181 -0
  314. package/tests/MenuHighlight.test.tsx +165 -0
  315. package/tests/MenuHoverKeyboardBugs.test.tsx +252 -0
  316. package/tests/MenuItemFocus.test.tsx +59 -0
  317. package/tests/MenuItemPseudoOverride.test.tsx +231 -0
  318. package/tests/MenuMultiTrigger.test.tsx +101 -0
  319. package/tests/MenuOverflow.test.tsx +93 -0
  320. package/tests/MenuStayInFrame.test.tsx +102 -0
  321. package/tests/MenuSubKeyboardFocus.test.tsx +220 -0
  322. package/tests/MenuSubLeftSafePolygon.test.tsx +88 -0
  323. package/tests/MenuSubNestedPosition.test.tsx +48 -0
  324. package/tests/MenuSubSafePolygon.test.tsx +97 -0
  325. package/tests/MenuSubStyled.test.tsx +40 -0
  326. package/tests/MenuTheme.test.tsx +34 -0
  327. package/tests/MenuUnstyled.test.tsx +56 -0
  328. package/tests/MultiDriverAnimation.test.tsx +207 -0
  329. package/tests/NewInputBasic.test.tsx +50 -0
  330. package/tests/NewInputEvents.test.tsx +55 -0
  331. package/tests/OnLayout.test.tsx +163 -0
  332. package/tests/OnLayoutScale.test.tsx +100 -0
  333. package/tests/OnLayoutStress.test.tsx +304 -0
  334. package/tests/ParagraphSpanFontInheritance.test.tsx +73 -0
  335. package/tests/PointerEvents.test.tsx +123 -0
  336. package/tests/Popover.animated.test.tsx +234 -0
  337. package/tests/PopoverAndMenuMultiTrigger.test.tsx +184 -0
  338. package/tests/PopoverAnimatePosition.animated.test.tsx +51 -0
  339. package/tests/PopoverClickDuringEnter.animated.test.tsx +197 -0
  340. package/tests/PopoverFocusScope.test.tsx +242 -0
  341. package/tests/PopoverHoverable.test.tsx +383 -0
  342. package/tests/PopoverHoverableDisableClick.test.tsx +106 -0
  343. package/tests/PopoverHoverableRapid.test.tsx +129 -0
  344. package/tests/PopoverHoverableReposition.test.tsx +111 -0
  345. package/tests/PopoverHoverableScoped.animated.test.tsx +103 -0
  346. package/tests/PopoverHoverableStress.test.tsx +169 -0
  347. package/tests/PopoverInitialPosition.animated.test.tsx +82 -0
  348. package/tests/PopoverMiddlewareSkipRegression.animated.test.tsx +221 -0
  349. package/tests/PopoverScoped.test.tsx +128 -0
  350. package/tests/PopoverScopedPositionGlitch.animated.test.tsx +184 -0
  351. package/tests/PopoverTriggerIsolation.test.tsx +62 -0
  352. package/tests/PseudoTransition.animated.test.tsx +319 -0
  353. package/tests/RawAnimatedValue.test.tsx +147 -0
  354. package/tests/RemoveScroll.test.tsx +223 -0
  355. package/tests/RenderProp.test.tsx +293 -0
  356. package/tests/ScrollViewRef.test.tsx +39 -0
  357. package/tests/SelectClickHold.test.tsx +147 -0
  358. package/tests/SelectFocusScope.test.tsx +176 -0
  359. package/tests/SelectInnerPositioning.test.tsx +82 -0
  360. package/tests/SelectKeyboardNav.test.tsx +173 -0
  361. package/tests/SelectPositioning.test.tsx +56 -0
  362. package/tests/SelectTypeahead.test.tsx +63 -0
  363. package/tests/Shadows.test.tsx +14 -0
  364. package/tests/SheetAnimation.animated.test.tsx +413 -0
  365. package/tests/SheetDrag.animated.test.tsx +223 -0
  366. package/tests/SheetDragResist.animated.test.tsx +393 -0
  367. package/tests/SheetOnAnimationComplete.animated.test.tsx +62 -0
  368. package/tests/SheetScrollLock.animated.test.tsx +287 -0
  369. package/tests/SheetScrollableDrag.animated.test.tsx +1264 -0
  370. package/tests/SheetSnapPointsFit.animated.test.tsx +259 -0
  371. package/tests/ShorthandVariables.test.tsx +44 -0
  372. package/tests/SpinnerCustomColors.test.tsx +67 -0
  373. package/tests/StackZIndex.test.tsx +51 -0
  374. package/tests/StressPagePerf.test.tsx +76 -0
  375. package/tests/StylePlatform.test.tsx +38 -0
  376. package/tests/StyleProp.test.tsx +20 -0
  377. package/tests/StyledAnchor.test.tsx +17 -0
  378. package/tests/StyledButtonTheme.test.tsx +22 -0
  379. package/tests/StyledButtonVariantPseudo.test.tsx +20 -0
  380. package/tests/StyledButtonVariantPseudoMerge.animated.test.tsx +33 -0
  381. package/tests/StyledCheckboxTheme.test.tsx +16 -0
  382. package/tests/StyledContextColor.test.tsx +119 -0
  383. package/tests/StyledContextTokens.test.tsx +56 -0
  384. package/tests/StyledHOCNamed.test.tsx +16 -0
  385. package/tests/StyledHtml.test.tsx +161 -0
  386. package/tests/StyledIconColor.test.tsx +32 -0
  387. package/tests/StyledInputFocusStyle.test.tsx +19 -0
  388. package/tests/StyledInputOnFocus.test.tsx +27 -0
  389. package/tests/StyledMediaQueryMerge.test.tsx +66 -0
  390. package/tests/StyledRNW.test.tsx +17 -0
  391. package/tests/StyledStyleableInputOnFocus.test.tsx +27 -0
  392. package/tests/StyledStyleableInputVariant.test.tsx +22 -0
  393. package/tests/StyledStyledStyleableInputOnFocus.test.tsx +27 -0
  394. package/tests/StyledVariantTextColor.test.tsx +24 -0
  395. package/tests/StyledViewOnFocus.test.tsx +27 -0
  396. package/tests/TabHoverAnimation.animated.test.tsx +468 -0
  397. package/tests/TabHoverPositionSmooth.animated.test.tsx +129 -0
  398. package/tests/TextNestedInheritance.test.tsx +93 -0
  399. package/tests/ThemeChange.test.tsx +70 -0
  400. package/tests/ThemeComponentResolution.test.tsx +82 -0
  401. package/tests/ThemeConditionalName.test.tsx +34 -0
  402. package/tests/ThemeMediaAnimation.test.tsx +65 -0
  403. package/tests/ThemeNested.test.tsx +141 -0
  404. package/tests/ThemeReset.test.tsx +63 -0
  405. package/tests/ThemeShallow.test.tsx +95 -0
  406. package/tests/Toast.test.tsx +106 -0
  407. package/tests/ToggleGroup.test.tsx +61 -0
  408. package/tests/ToggleGroupActiveProps.test.tsx +38 -0
  409. package/tests/ToggleGroupXGroup.test.tsx +172 -0
  410. package/tests/TooltipAnimation.animated.test.tsx +260 -0
  411. package/tests/TooltipEnterInterrupt.animated.test.tsx +76 -0
  412. package/tests/TooltipGlobalPattern.animated.test.tsx +208 -0
  413. package/tests/TooltipGroup.animated.test.tsx +79 -0
  414. package/tests/TooltipMultiTrigger.test.tsx +116 -0
  415. package/tests/TooltipPositionJump.animated.test.tsx +229 -0
  416. package/tests/TooltipPositionJumpNotes.md +219 -0
  417. package/tests/TooltipRapidSwitch.animated.test.tsx +399 -0
  418. package/tests/TooltipTriggerInline.test.tsx +65 -0
  419. package/tests/TransformMediaQueryMerge.test.tsx +104 -0
  420. package/tests/TransitionEnterExit.animated.test.tsx +311 -0
  421. package/tests/UseTheme.test.tsx +16 -0
  422. package/tests/V5ThemeBuilderOutput.test.tsx +164 -0
  423. package/tests/VariantFontFamily.test.tsx +11 -0
  424. package/tests/VariantsOrder.test.tsx +53 -0
  425. package/tests/_debug_position.mjs +52 -0
  426. package/tests/test-utils.ts +106 -0
  427. package/tests/utils.tsx +54 -0
  428. package/tsconfig.json +45 -0
  429. package/vite-env.d.ts +1 -0
  430. package/vite.config.ts +14 -0
  431. package/webpack.config.js +139 -0
@@ -0,0 +1,128 @@
1
+ import { expect, test } from '@playwright/test'
2
+ import { setupPage } from './test-utils'
3
+
4
+ test.describe('Dialog Nested Stacking', () => {
5
+ test.beforeEach(async ({ page }) => {
6
+ await setupPage(page, { name: 'DialogNestedCase', type: 'useCase' })
7
+ })
8
+
9
+ test('nested dialog appears above parent dialog (z-index stacking)', async ({
10
+ page,
11
+ }) => {
12
+ await page.waitForLoadState('networkidle')
13
+
14
+ // Open parent dialog
15
+ const parentTrigger = page.getByTestId('parent-dialog-trigger')
16
+ await parentTrigger.click()
17
+
18
+ const parentDialog = page.getByTestId('parent-dialog-content')
19
+ await expect(parentDialog).toBeVisible({ timeout: 5000 })
20
+
21
+ // Wait for animation to complete
22
+ await page.waitForTimeout(300)
23
+
24
+ // Open nested dialog
25
+ const nestedTrigger = page.getByTestId('nested-dialog-trigger')
26
+ await nestedTrigger.click()
27
+
28
+ const nestedDialog = page.getByTestId('nested-dialog-content')
29
+ await expect(nestedDialog).toBeVisible({ timeout: 5000 })
30
+
31
+ // Wait for animation to complete
32
+ await page.waitForTimeout(300)
33
+
34
+ // Get the z-index values of both dialog portal containers
35
+ // GuiRoot wraps portal content in Theme > span, so z-index is on the inner span
36
+ const zIndexInfo = await page.evaluate(() => {
37
+ const portals = document.querySelectorAll('span[style*="z-index"]')
38
+ const zIndices: number[] = []
39
+
40
+ portals.forEach((portal) => {
41
+ const style = window.getComputedStyle(portal)
42
+ const zIndex = parseInt(style.zIndex, 10)
43
+ if (!isNaN(zIndex)) {
44
+ zIndices.push(zIndex)
45
+ }
46
+ })
47
+
48
+ return zIndices.sort((a, b) => a - b)
49
+ })
50
+
51
+ // Should have at least 2 different z-index values
52
+ expect(zIndexInfo.length).toBeGreaterThanOrEqual(2)
53
+
54
+ // The nested dialog should have a higher z-index than the parent
55
+ const parentZIndex = zIndexInfo[0]
56
+ const nestedZIndex = zIndexInfo[zIndexInfo.length - 1]
57
+
58
+ expect(nestedZIndex).toBeGreaterThan(parentZIndex)
59
+
60
+ // Verify the nested dialog is visually on top by checking element at center
61
+ const nestedBounds = await nestedDialog.boundingBox()
62
+ if (nestedBounds) {
63
+ const centerX = nestedBounds.x + nestedBounds.width / 2
64
+ const centerY = nestedBounds.y + nestedBounds.height / 2
65
+
66
+ const elementAtPoint = await page.evaluate(
67
+ ({ x, y }) => {
68
+ const el = document.elementFromPoint(x, y)
69
+ return el?.closest('[data-testid="nested-dialog-content"]') !== null
70
+ },
71
+ { x: centerX, y: centerY }
72
+ )
73
+
74
+ expect(elementAtPoint).toBe(true)
75
+ }
76
+ })
77
+
78
+ test('three levels of nested dialogs stack correctly', async ({ page }) => {
79
+ await page.waitForLoadState('networkidle')
80
+
81
+ // Open level 1 dialog
82
+ const level1Trigger = page.getByTestId('parent-dialog-trigger')
83
+ await level1Trigger.click()
84
+
85
+ const level1Dialog = page.getByTestId('parent-dialog-content')
86
+ await expect(level1Dialog).toBeVisible({ timeout: 5000 })
87
+
88
+ // Wait for animation
89
+ await page.waitForTimeout(300)
90
+
91
+ // Open level 2 dialog
92
+ const level2Trigger = page.getByTestId('nested-dialog-trigger')
93
+ await level2Trigger.click()
94
+
95
+ const level2Dialog = page.getByTestId('nested-dialog-content')
96
+ await expect(level2Dialog).toBeVisible({ timeout: 5000 })
97
+
98
+ // Wait for animation
99
+ await page.waitForTimeout(300)
100
+
101
+ // Open level 3 dialog
102
+ const level3Trigger = page.getByTestId('level-3-dialog-trigger')
103
+ await level3Trigger.click()
104
+
105
+ const level3Dialog = page.getByTestId('level-3-dialog-content')
106
+ await expect(level3Dialog).toBeVisible({ timeout: 5000 })
107
+
108
+ // Wait for animation
109
+ await page.waitForTimeout(300)
110
+
111
+ // Verify level 3 is on top visually
112
+ const level3Bounds = await level3Dialog.boundingBox()
113
+ if (level3Bounds) {
114
+ const centerX = level3Bounds.x + level3Bounds.width / 2
115
+ const centerY = level3Bounds.y + level3Bounds.height / 2
116
+
117
+ const elementAtPoint = await page.evaluate(
118
+ ({ x, y }) => {
119
+ const el = document.elementFromPoint(x, y)
120
+ return el?.closest('[data-testid="level-3-dialog-content"]') !== null
121
+ },
122
+ { x: centerX, y: centerY }
123
+ )
124
+
125
+ expect(elementAtPoint).toBe(true)
126
+ }
127
+ })
128
+ })
@@ -0,0 +1,42 @@
1
+ import { expect, test } from '@playwright/test'
2
+ import { setupPage } from './test-utils'
3
+
4
+ /**
5
+ * Test for issue #3565
6
+ * Verifies that Dialog works when controlled with open={true}
7
+ *
8
+ * In JSDOM (Jest), this fails with "node.show is not a function"
9
+ * because JSDOM doesn't implement HTMLDialogElement.show()
10
+ *
11
+ * This test ensures the dialog renders correctly in a real browser.
12
+ */
13
+ test.describe('Dialog Open Controlled', () => {
14
+ test.beforeEach(async ({ page }) => {
15
+ await setupPage(page, { name: 'DialogOpenControlled', type: 'useCase' })
16
+ })
17
+
18
+ test('dialog renders when controlled with open={true}', async ({ page }) => {
19
+ await page.waitForLoadState('networkidle')
20
+
21
+ // The dialog should be visible immediately since open={true}
22
+ const dialogContent = page.getByTestId('dialog-content')
23
+ await expect(dialogContent).toBeVisible({ timeout: 5000 })
24
+ await expect(dialogContent).toHaveText('Hiya!')
25
+ })
26
+
27
+ test('dialog can be closed via close button', async ({ page }) => {
28
+ await page.waitForLoadState('networkidle')
29
+
30
+ // Dialog should be visible
31
+ const dialogContent = page.getByTestId('dialog-content')
32
+ await expect(dialogContent).toBeVisible({ timeout: 5000 })
33
+
34
+ // Click close button
35
+ const closeButton = page.getByTestId('dialog-close')
36
+ await closeButton.click()
37
+
38
+ // Dialog should still be visible because it's controlled with open={true}
39
+ // (no state management in the component - it's always open)
40
+ await expect(dialogContent).toBeVisible()
41
+ })
42
+ })
@@ -0,0 +1,108 @@
1
+ import { expect, test } from '@playwright/test'
2
+ import { setupPage } from './test-utils'
3
+
4
+ /**
5
+ * Test for dialog pointer events unlock timing
6
+ *
7
+ * Verifies that when a dialog closes, the dialog content gets pointer-events: none
8
+ * immediately, allowing clicks to pass through to elements behind during the
9
+ * exit animation.
10
+ *
11
+ * This is an animated test because the bug only manifests with animations enabled.
12
+ */
13
+ test.describe('Dialog Pointer Events Unlock', () => {
14
+ test.beforeEach(async ({ page }) => {
15
+ await setupPage(page, { name: 'DialogPointerEventsCase', type: 'useCase' })
16
+ })
17
+
18
+ test('dialog content allows click-through during exit animation', async ({ page }) => {
19
+ // get initial click count
20
+ const clickCountEl = page.getByTestId('click-count')
21
+ await expect(clickCountEl).toHaveText('0')
22
+
23
+ // open the dialog
24
+ const triggerButton = page.getByTestId('dialog-trigger')
25
+ await triggerButton.click()
26
+
27
+ // wait for dialog to be visible
28
+ const dialogClose = page.locator('[data-testid="dialog-close"]')
29
+ await expect(dialogClose).toBeVisible({ timeout: 5000 })
30
+
31
+ // wait for enter animation to settle
32
+ await page.waitForTimeout(800)
33
+
34
+ // set up monitoring to check dialog content pointer events after close
35
+ const results = await page.evaluate(async () => {
36
+ return new Promise<{
37
+ contentPointerEvents: string[]
38
+ buttonAccessible: boolean[]
39
+ dialogStillAnimating: boolean
40
+ }>((resolve) => {
41
+ const contentPointerEvents: string[] = []
42
+ const buttonAccessible: boolean[] = []
43
+ const closeButton = document.querySelector(
44
+ '[data-testid="dialog-close"]'
45
+ ) as HTMLElement
46
+ const dialogContent = document.querySelector('[role="dialog"]') as HTMLElement
47
+ const backgroundBtn = document.querySelector(
48
+ '[data-testid="background-button"]'
49
+ ) as HTMLElement
50
+
51
+ // start sampling immediately
52
+ const interval = setInterval(() => {
53
+ if (dialogContent) {
54
+ contentPointerEvents.push(getComputedStyle(dialogContent).pointerEvents)
55
+ }
56
+ // check if the background button is accessible (not blocked by dialog)
57
+ const btnRect = backgroundBtn?.getBoundingClientRect()
58
+ if (btnRect) {
59
+ const elementAtPoint = document.elementFromPoint(
60
+ btnRect.left + btnRect.width / 2,
61
+ btnRect.top + btnRect.height / 2
62
+ )
63
+ buttonAccessible.push(
64
+ elementAtPoint === backgroundBtn || backgroundBtn.contains(elementAtPoint)
65
+ )
66
+ }
67
+ }, 20)
68
+
69
+ // click close button
70
+ closeButton.click()
71
+
72
+ // after 300ms, check state and stop sampling
73
+ setTimeout(() => {
74
+ clearInterval(interval)
75
+ const stillAnimating = dialogContent
76
+ ? getComputedStyle(dialogContent).opacity !== '0'
77
+ : false
78
+ resolve({
79
+ contentPointerEvents,
80
+ buttonAccessible,
81
+ dialogStillAnimating: stillAnimating,
82
+ })
83
+ }, 300)
84
+ })
85
+ })
86
+
87
+ console.log('Content pointer events during exit:', results.contentPointerEvents)
88
+ console.log('Button accessible during exit:', results.buttonAccessible)
89
+ console.log('Dialog still animating at end:', results.dialogStillAnimating)
90
+
91
+ // the key assertion: the background button should become accessible quickly
92
+ // (within first few samples) - this is the actual user-facing behavior we care about
93
+ // note: the dialog portal container gets pointer-events: none, which allows clicks
94
+ // to pass through even if the dialog content itself has pointer-events: auto
95
+ const buttonAccessibleEarly = results.buttonAccessible.some(
96
+ (accessible, i) => i < 8 && accessible
97
+ )
98
+ expect(buttonAccessibleEarly).toBeTruthy()
99
+
100
+ // wait for dialog to fully close (reanimated driver can be much slower in CI)
101
+ await expect(dialogClose).not.toBeVisible({ timeout: 10000 })
102
+
103
+ // verify background button is clickable
104
+ const backgroundButton = page.getByTestId('background-button')
105
+ await backgroundButton.click()
106
+ await expect(clickCountEl).toHaveText('1')
107
+ })
108
+ })
@@ -0,0 +1,137 @@
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: 'DialogScopedCase', type: 'useCase' })
7
+ })
8
+
9
+ test('scoped dialogs work', async ({ page }) => {
10
+ // Wait for page to load
11
+ await page.waitForLoadState('networkidle')
12
+
13
+ async function testDialogScoped(name: string) {
14
+ const triggerTestId = `${name}-trigger`
15
+ const contentTestId = `${name}-dialog-content`
16
+ const trigger = page.getByTestId(triggerTestId)
17
+ const content = page.getByTestId(contentTestId)
18
+ const closeButton = content.getByTestId(`${name}-dialog-close`)
19
+
20
+ // Check initial state
21
+ await expect(trigger).toBeVisible()
22
+ await expect(content).not.toBeVisible()
23
+
24
+ // Click trigger to open dialog
25
+ await trigger.click()
26
+
27
+ // Wait for content to be visible
28
+ await expect(content).toBeVisible({ timeout: 5000 })
29
+
30
+ // Click close button
31
+ await closeButton.click()
32
+
33
+ // Verify dialog is closed
34
+ await expect(content).not.toBeVisible()
35
+ }
36
+
37
+ // Test each scoped dialog
38
+ await testDialogScoped('plain')
39
+ await testDialogScoped('a')
40
+ await testDialogScoped('b')
41
+ })
42
+
43
+ test('dialog scopes are isolated', async ({ page }) => {
44
+ // Wait for page to load
45
+ await page.waitForLoadState('networkidle')
46
+
47
+ const plainTrigger = page.getByTestId('plain-trigger')
48
+ const aTrigger = page.getByTestId('a-trigger')
49
+ const bTrigger = page.getByTestId('b-trigger')
50
+
51
+ const plainContent = page.getByTestId('plain-dialog-content')
52
+ const aContent = page.getByTestId('a-dialog-content')
53
+ const bContent = page.getByTestId('b-dialog-content')
54
+
55
+ // Open dialog A
56
+ await aTrigger.click()
57
+ await expect(aContent).toBeVisible({ timeout: 5000 })
58
+
59
+ // Verify other dialogs are not visible
60
+ await expect(plainContent).not.toBeVisible()
61
+ await expect(bContent).not.toBeVisible()
62
+
63
+ // Close dialog A
64
+ await aContent.getByTestId('a-dialog-close').click()
65
+ await expect(aContent).not.toBeVisible()
66
+
67
+ // Open dialog B
68
+ await bTrigger.click()
69
+ await expect(bContent).toBeVisible({ timeout: 5000 })
70
+
71
+ // Verify other dialogs are not visible
72
+ await expect(plainContent).not.toBeVisible()
73
+ await expect(aContent).not.toBeVisible()
74
+
75
+ // Close dialog B
76
+ await bContent.getByTestId('b-dialog-close').click()
77
+ await expect(bContent).not.toBeVisible()
78
+
79
+ // Open plain dialog
80
+ await plainTrigger.click()
81
+ await expect(plainContent).toBeVisible({ timeout: 5000 })
82
+
83
+ // Verify other dialogs are not visible
84
+ await expect(aContent).not.toBeVisible()
85
+ await expect(bContent).not.toBeVisible()
86
+
87
+ // Close plain dialog
88
+ await plainContent.getByTestId('plain-dialog-close').click()
89
+ await expect(plainContent).not.toBeVisible()
90
+ })
91
+
92
+ test('scoped dialogs adapt to sheets', async ({ page: pageIn }) => {
93
+ const page = await setupPage(pageIn, {
94
+ name: 'DialogScopedCase',
95
+ type: 'useCase',
96
+ adapt: true,
97
+ })
98
+
99
+ // Wait for page to load
100
+ await page.waitForLoadState('networkidle')
101
+
102
+ async function testDialogAdapted(name: string) {
103
+ const trigger = page.getByTestId(`${name}-trigger`)
104
+ const sheetContents = page.getByTestId(`${name}-sheet-contents`).first()
105
+ const dialogContent = page.getByTestId(`${name}-dialog-content`)
106
+
107
+ // Click trigger to open sheet
108
+ await trigger.click()
109
+
110
+ // Wait for sheet to be visible and open
111
+ await expect(sheetContents).toBeVisible({ timeout: 5000 })
112
+ await expect(sheetContents).toHaveAttribute('data-state', 'open', { timeout: 5000 })
113
+
114
+ // Check that dialog content is inside sheet
115
+ await expect(sheetContents.locator(dialogContent)).toBeVisible()
116
+
117
+ // Dialog.Close hides in sheet mode
118
+ const closeButton = sheetContents.getByTestId('dialog-close')
119
+ await expect(closeButton).not.toBeVisible()
120
+
121
+ // Click sheet backdrop (at top of screen to avoid sheet content)
122
+ const overlay = page.locator(`#${name}-sheet-overlay`)
123
+ await expect(overlay).toBeVisible()
124
+ // Click near the top of the overlay where the sheet content doesn't cover
125
+ await overlay.click({ position: { x: 10, y: 10 } })
126
+
127
+ // Wait for sheet to close by checking data-state attribute
128
+ await expect(sheetContents).toHaveAttribute('data-state', 'closed', { timeout: 5000 })
129
+
130
+ // Verify sheet is visually off-screen
131
+ await expect(sheetContents).not.toBeInViewport({ ratio: 0.5 })
132
+ }
133
+
134
+ await testDialogAdapted('plain')
135
+ await testDialogAdapted('a')
136
+ await testDialogAdapted('b')
137
+ })
@@ -0,0 +1,68 @@
1
+ import { expect, test } from '@playwright/test'
2
+ import { setupPage } from './test-utils'
3
+
4
+ /**
5
+ * Test for styled(Dialog.Overlay) with onPress
6
+ *
7
+ * This tests the fix for: "Cannot read property '_internalInstanceHandle' of null"
8
+ * which occurred on Android when using styled(Dialog.Overlay) with onPress.
9
+ *
10
+ * The fix skips GestureDetector wrapping for HOC components and passes press
11
+ * events down via props instead, allowing the inner component to handle gesture
12
+ * detection at the correct level where a native view exists.
13
+ */
14
+ test.describe('Dialog Sheet Adapt - styled(Dialog.Overlay) with onPress', () => {
15
+ test.beforeEach(async ({ page }) => {
16
+ await setupPage(page, { name: 'DialogSheetAdaptCase', type: 'useCase' })
17
+ })
18
+
19
+ test('styled(Dialog.Overlay) with onPress should render without crashing', async ({
20
+ page,
21
+ }) => {
22
+ await page.waitForLoadState('networkidle')
23
+
24
+ // Open the dialog
25
+ const trigger = page.getByTestId('open-dialog')
26
+ await trigger.click()
27
+
28
+ // Wait for dialog overlay to be visible (the styled DialogOverlay)
29
+ // On web, this should work. The fix ensures HOC components pass press events
30
+ // down instead of wrapping with GestureDetector (which would crash on native
31
+ // when the inner component returns null during adapt)
32
+ await page.waitForTimeout(500)
33
+
34
+ // Dialog content should be visible
35
+ const dialogContent = page.locator('text=Dialog with Sheet Adapt')
36
+ await expect(dialogContent).toBeVisible({ timeout: 5000 })
37
+
38
+ // Close button should work
39
+ const closeButton = page.getByTestId('close-dialog')
40
+ await closeButton.click()
41
+
42
+ // Dialog should close
43
+ await expect(dialogContent).not.toBeVisible({ timeout: 5000 })
44
+ })
45
+
46
+ test('can open and close dialog multiple times without errors', async ({ page }) => {
47
+ await page.waitForLoadState('networkidle')
48
+
49
+ // Test multiple open/close cycles to ensure stability
50
+ for (let i = 0; i < 3; i++) {
51
+ // Open the dialog
52
+ const trigger = page.getByTestId('open-dialog')
53
+ await trigger.click()
54
+
55
+ // Wait for dialog to be visible
56
+ await page.waitForTimeout(300)
57
+ const dialogContent = page.locator('text=Dialog with Sheet Adapt')
58
+ await expect(dialogContent).toBeVisible({ timeout: 5000 })
59
+
60
+ // Close via button
61
+ const closeButton = page.getByTestId('close-dialog')
62
+ await closeButton.click()
63
+
64
+ // Wait for dialog to close
65
+ await expect(dialogContent).not.toBeVisible({ timeout: 5000 })
66
+ }
67
+ })
68
+ })
@@ -0,0 +1,161 @@
1
+ import { expect, test } from '@playwright/test'
2
+ import { setupPage } from './test-utils'
3
+
4
+ /**
5
+ * Test for Dialog → Sheet content portaling on viewport resize
6
+ *
7
+ * This tests the fix for: When resizing from wide (Dialog) to narrow (Sheet via Adapt),
8
+ * the Sheet appears empty because the portal content isn't properly transferred.
9
+ */
10
+ test.describe('Dialog Sheet Adapt - viewport resize', () => {
11
+ test.beforeEach(async ({ page }) => {
12
+ await setupPage(page, { name: 'DialogSheetAdaptResizeCase', type: 'useCase' })
13
+ })
14
+
15
+ test('content is visible in dialog at wide viewport', async ({ page }) => {
16
+ // set viewport to wide (above maxMd breakpoint of 768px)
17
+ await page.setViewportSize({ width: 1024, height: 768 })
18
+ await page.waitForTimeout(300)
19
+
20
+ // open the dialog
21
+ const trigger = page.getByTestId('open-dialog')
22
+ await trigger.click({ force: true })
23
+ await page.waitForTimeout(500)
24
+
25
+ // dialog content should be visible
26
+ const title = page.getByTestId('dialog-title')
27
+ await expect(title).toBeVisible({ timeout: 5000 })
28
+
29
+ const content = page.getByTestId('dialog-content')
30
+ await expect(content).toBeVisible({ timeout: 5000 })
31
+
32
+ // close button should work
33
+ const closeButton = page.getByTestId('close-dialog')
34
+ await closeButton.click({ force: true })
35
+ await expect(title).not.toBeVisible({ timeout: 5000 })
36
+ })
37
+
38
+ test('content is visible in sheet at narrow viewport', async ({ page }) => {
39
+ // set viewport to narrow (below maxMd breakpoint of 768px)
40
+ await page.setViewportSize({ width: 600, height: 768 })
41
+ await page.waitForTimeout(300)
42
+
43
+ // open - should show as sheet due to adapt
44
+ const trigger = page.getByTestId('open-dialog')
45
+ await trigger.click({ force: true })
46
+ await page.waitForTimeout(500)
47
+
48
+ // sheet content should be visible
49
+ const title = page.getByTestId('dialog-title')
50
+ await expect(title).toBeVisible({ timeout: 5000 })
51
+
52
+ const content = page.getByTestId('dialog-content')
53
+ await expect(content).toBeVisible({ timeout: 5000 })
54
+
55
+ // extra content should also be visible
56
+ const extra1 = page.getByTestId('extra-content-1')
57
+ await expect(extra1).toBeVisible({ timeout: 5000 })
58
+ })
59
+
60
+ test('content transfers from dialog to sheet on resize narrow', async ({ page }) => {
61
+ // start at wide viewport
62
+ await page.setViewportSize({ width: 1024, height: 768 })
63
+ await page.waitForTimeout(300)
64
+
65
+ // open the dialog at wide width
66
+ const trigger = page.getByTestId('open-dialog')
67
+ await trigger.click({ force: true })
68
+ await page.waitForTimeout(500)
69
+
70
+ // verify content visible in dialog
71
+ const title = page.getByTestId('dialog-title')
72
+ await expect(title).toBeVisible({ timeout: 5000 })
73
+
74
+ const content = page.getByTestId('dialog-content')
75
+ await expect(content).toBeVisible({ timeout: 5000 })
76
+
77
+ // resize to narrow - should adapt to sheet
78
+ await page.setViewportSize({ width: 600, height: 768 })
79
+ await page.waitForTimeout(500) // give time for adapt to trigger and animations
80
+
81
+ // content should still be visible (now in sheet)
82
+ await expect(title).toBeVisible({ timeout: 5000 })
83
+ await expect(content).toBeVisible({ timeout: 5000 })
84
+
85
+ // extra content should also be visible
86
+ const extra1 = page.getByTestId('extra-content-1')
87
+ await expect(extra1).toBeVisible({ timeout: 5000 })
88
+ })
89
+
90
+ test('content transfers from sheet to dialog on resize wide', async ({ page }) => {
91
+ // start at narrow viewport
92
+ await page.setViewportSize({ width: 600, height: 768 })
93
+ await page.waitForTimeout(300)
94
+
95
+ // open at narrow width - should show as sheet
96
+ const trigger = page.getByTestId('open-dialog')
97
+ await trigger.click({ force: true })
98
+ await page.waitForTimeout(500)
99
+
100
+ // verify content visible in sheet
101
+ const title = page.getByTestId('dialog-title')
102
+ await expect(title).toBeVisible({ timeout: 5000 })
103
+
104
+ const content = page.getByTestId('dialog-content')
105
+ await expect(content).toBeVisible({ timeout: 5000 })
106
+
107
+ // resize to wide - should adapt back to dialog
108
+ await page.setViewportSize({ width: 1024, height: 768 })
109
+ await page.waitForTimeout(500) // give time for adapt to trigger and animations
110
+
111
+ // content should still be visible (now in dialog)
112
+ await expect(title).toBeVisible({ timeout: 5000 })
113
+ await expect(content).toBeVisible({ timeout: 5000 })
114
+
115
+ // extra content should also be visible
116
+ const extra1 = page.getByTestId('extra-content-1')
117
+ await expect(extra1).toBeVisible({ timeout: 5000 })
118
+ })
119
+
120
+ test('multiple resize cycles preserve content', async ({ page }) => {
121
+ // start wide
122
+ await page.setViewportSize({ width: 1024, height: 768 })
123
+ await page.waitForTimeout(300)
124
+
125
+ // open dialog
126
+ const trigger = page.getByTestId('open-dialog')
127
+ await trigger.click({ force: true })
128
+ await page.waitForTimeout(500)
129
+
130
+ const title = page.getByTestId('dialog-title')
131
+ const content = page.getByTestId('dialog-content')
132
+
133
+ // verify initial state
134
+ await expect(title).toBeVisible({ timeout: 5000 })
135
+ await expect(content).toBeVisible({ timeout: 5000 })
136
+
137
+ // cycle 1: wide -> narrow
138
+ await page.setViewportSize({ width: 600, height: 768 })
139
+ await page.waitForTimeout(500)
140
+ await expect(title).toBeVisible({ timeout: 5000 })
141
+ await expect(content).toBeVisible({ timeout: 5000 })
142
+
143
+ // cycle 1: narrow -> wide
144
+ await page.setViewportSize({ width: 1024, height: 768 })
145
+ await page.waitForTimeout(500)
146
+ await expect(title).toBeVisible({ timeout: 5000 })
147
+ await expect(content).toBeVisible({ timeout: 5000 })
148
+
149
+ // cycle 2: wide -> narrow
150
+ await page.setViewportSize({ width: 600, height: 768 })
151
+ await page.waitForTimeout(500)
152
+ await expect(title).toBeVisible({ timeout: 5000 })
153
+ await expect(content).toBeVisible({ timeout: 5000 })
154
+
155
+ // cycle 2: narrow -> wide
156
+ await page.setViewportSize({ width: 1024, height: 768 })
157
+ await page.waitForTimeout(500)
158
+ await expect(title).toBeVisible({ timeout: 5000 })
159
+ await expect(content).toBeVisible({ timeout: 5000 })
160
+ })
161
+ })