@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,104 @@
1
+ import { expect, test } from '@playwright/test'
2
+ import { setupPage } from './test-utils'
3
+
4
+ /**
5
+ * Regression tests for transform media query merging bug
6
+ *
7
+ * Bug: When a media query sets transform props like `x`, it should OVERWRITE
8
+ * the base value, not be CUMULATIVE (added together).
9
+ *
10
+ * Example:
11
+ * - Base: x={-100}
12
+ * - $sm: { x: 50 }
13
+ * - Expected at $sm: x = 50 (overwrite)
14
+ * - Bug behavior: x = -50 (cumulative: -100 + 50)
15
+ */
16
+
17
+ test.describe('Transform Media Query Merge', () => {
18
+ test.beforeEach(async ({ page }) => {
19
+ await setupPage(page, { name: 'TransformMediaQueryMerge', type: 'useCase' })
20
+ })
21
+
22
+ // Helper to extract translateX from transform
23
+ async function getTranslateX(page: any, testId: string): Promise<number> {
24
+ return page.evaluate((id: string) => {
25
+ const el = document.querySelector(`[data-testid="${id}"]`)
26
+ if (!el) return NaN
27
+ const transform = getComputedStyle(el).transform
28
+ if (transform === 'none') return 0
29
+
30
+ // Handle matrix(a, b, c, d, tx, ty) format
31
+ const matrixMatch = transform.match(/matrix\(([^)]+)\)/)
32
+ if (matrixMatch) {
33
+ const values = matrixMatch[1].split(',').map((v: string) => parseFloat(v.trim()))
34
+ return values[4] || 0
35
+ }
36
+ return 0
37
+ }, testId)
38
+ }
39
+
40
+ test('base transform values apply at large viewport', async ({ page }) => {
41
+ await page.setViewportSize({ width: 1200, height: 800 })
42
+ await page.waitForTimeout(300)
43
+
44
+ // Test 1: styled() component with x=-100 base
45
+ const x1 = await getTranslateX(page, 'test1')
46
+ expect(x1, 'styled component base x=-100').toBeCloseTo(-100, 0)
47
+
48
+ // Test 3: runtime prop with x=-75 base
49
+ const x3 = await getTranslateX(page, 'test3')
50
+ expect(x3, 'runtime prop base x=-75').toBeCloseTo(-75, 0)
51
+ })
52
+
53
+ test('media query x OVERWRITES base value (not cumulative)', async ({ page }) => {
54
+ // Set viewport to $sm breakpoint
55
+ await page.setViewportSize({ width: 600, height: 800 })
56
+ await page.waitForTimeout(300)
57
+
58
+ // Test 1: styled() with base x=-100, $sm: x=50
59
+ // If cumulative (bug): x = -100 + 50 = -50
60
+ // If overwrite (correct): x = 50
61
+ const x1 = await getTranslateX(page, 'test1')
62
+ expect(x1, 'styled $sm x should OVERWRITE to 50, not cumulate to -50').toBeCloseTo(
63
+ 50,
64
+ 0
65
+ )
66
+ })
67
+
68
+ test('runtime prop media query x OVERWRITES base value', async ({ page }) => {
69
+ await page.setViewportSize({ width: 600, height: 800 })
70
+ await page.waitForTimeout(300)
71
+
72
+ // Test 3: runtime prop with base x=-75, $sm: x=75
73
+ // If cumulative (bug): x = -75 + 75 = 0
74
+ // If overwrite (correct): x = 75
75
+ const x3 = await getTranslateX(page, 'test3')
76
+ expect(x3, 'runtime $sm x should OVERWRITE to 75, not cumulate to 0').toBeCloseTo(
77
+ 75,
78
+ 0
79
+ )
80
+ })
81
+
82
+ test('viewport resize updates transform correctly', async ({ page }) => {
83
+ // Start large - should have base value
84
+ await page.setViewportSize({ width: 1200, height: 800 })
85
+ await page.waitForTimeout(300)
86
+
87
+ let x1 = await getTranslateX(page, 'test1')
88
+ expect(x1, 'large viewport: x=-100').toBeCloseTo(-100, 0)
89
+
90
+ // Resize to small - should overwrite to media query value
91
+ await page.setViewportSize({ width: 600, height: 800 })
92
+ await page.waitForTimeout(300)
93
+
94
+ x1 = await getTranslateX(page, 'test1')
95
+ expect(x1, 'small viewport: x should be 50 (overwrite)').toBeCloseTo(50, 0)
96
+
97
+ // Resize back to large - should return to base value
98
+ await page.setViewportSize({ width: 1200, height: 800 })
99
+ await page.waitForTimeout(300)
100
+
101
+ x1 = await getTranslateX(page, 'test1')
102
+ expect(x1, 'back to large: x=-100').toBeCloseTo(-100, 0)
103
+ })
104
+ })
@@ -0,0 +1,311 @@
1
+ import { expect, test, type Page } from '@playwright/test'
2
+ import { setupPage } from './test-utils'
3
+
4
+ /**
5
+ * ENTER/EXIT TRANSITION TESTS
6
+ *
7
+ * Tests the transition prop's enter/exit-specific animations using timing animations.
8
+ * Supports syntax like: transition={{ enter: '500ms', exit: '100ms' }}
9
+ *
10
+ * These tests run across all animation drivers (css, native, reanimated, motion).
11
+ */
12
+
13
+ const TOLERANCE = 0.2
14
+
15
+ async function getOpacity(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
+ return Number.parseFloat(getComputedStyle(el).opacity)
20
+ }, testId)
21
+ }
22
+
23
+ async function elementExists(page: Page, testId: string): Promise<boolean> {
24
+ return page.evaluate((id) => !!document.querySelector(`[data-testid="${id}"]`), testId)
25
+ }
26
+
27
+ function isIntermediate(
28
+ value: number,
29
+ start: number,
30
+ end: number,
31
+ tolerance = TOLERANCE
32
+ ): boolean {
33
+ const notAtStart = Math.abs(value - start) > tolerance
34
+ const notAtEnd = Math.abs(value - end) > tolerance
35
+ const min = Math.min(start, end)
36
+ const max = Math.max(start, end)
37
+ const inRange = value >= min - tolerance && value <= max + tolerance
38
+ return notAtStart && notAtEnd && inRange
39
+ }
40
+
41
+ // works in ci, flaky on local
42
+ test.fixme('Enter/Exit Transition Props', () => {
43
+ test.beforeEach(async ({ page }) => {
44
+ const driver = (test.info().project?.metadata as any)?.animationDriver
45
+ test.skip(driver === 'native', 'native driver has element detection issues on web')
46
+
47
+ await setupPage(page, {
48
+ name: 'AnimationComprehensiveCase',
49
+ type: 'useCase',
50
+ })
51
+ // wait for initial render and any enter animations to complete
52
+ // use longer timeout for CI environments which can be slower
53
+ await page.waitForTimeout(1500)
54
+ })
55
+
56
+ test('scenario 42: different enter/exit transitions - enter uses slow animation', async ({
57
+ page,
58
+ }) => {
59
+ expect(await elementExists(page, 'scenario-42-target'), 'Initially visible').toBe(
60
+ true
61
+ )
62
+ // wait for initial enter animation to complete (500ms animation + settling time)
63
+ await page.waitForFunction(
64
+ (testId) => {
65
+ const el = document.querySelector(`[data-testid="${testId}"]`)
66
+ return el && Number.parseFloat(getComputedStyle(el).opacity) >= 0.95
67
+ },
68
+ 'scenario-42-target',
69
+ { timeout: 3000 }
70
+ )
71
+ expect(await getOpacity(page, 'scenario-42-target'), 'Initial opacity').toBeCloseTo(
72
+ 1,
73
+ 1
74
+ )
75
+
76
+ // hide then show to test enter animation (enter=500ms)
77
+ await page.getByTestId('scenario-42-trigger').click()
78
+ await page.waitForTimeout(300) // exit=100ms + buffer
79
+
80
+ expect(await elementExists(page, 'scenario-42-target'), 'Hidden').toBe(false)
81
+
82
+ await page.getByTestId('scenario-42-trigger').click()
83
+ await page.waitForTimeout(50)
84
+ expect(await elementExists(page, 'scenario-42-target'), 'Should appear').toBe(true)
85
+
86
+ await page.waitForTimeout(150)
87
+ const midEnterOpacity = await getOpacity(page, 'scenario-42-target')
88
+
89
+ expect(
90
+ isIntermediate(midEnterOpacity, 0, 1),
91
+ `Mid-enter opacity (${midEnterOpacity.toFixed(2)}) should be intermediate at 200ms into 500ms`
92
+ ).toBe(true)
93
+
94
+ await page.waitForTimeout(500)
95
+ expect(await getOpacity(page, 'scenario-42-target'), 'Final opacity').toBeCloseTo(
96
+ 1,
97
+ 1
98
+ )
99
+ })
100
+
101
+ test('scenario 42: different enter/exit transitions - exit uses fast animation', async ({
102
+ page,
103
+ }) => {
104
+ expect(await elementExists(page, 'scenario-42-target'), 'Initially visible').toBe(
105
+ true
106
+ )
107
+
108
+ // trigger exit (exit=100ms - fast)
109
+ await page.getByTestId('scenario-42-trigger').click()
110
+ await page.waitForTimeout(300) // 100ms + buffer
111
+
112
+ expect(await elementExists(page, 'scenario-42-target'), 'Gone after fast exit').toBe(
113
+ false
114
+ )
115
+ })
116
+
117
+ test('scenario 43: enter-only transition - enter uses specified, exit uses default', async ({
118
+ page,
119
+ }) => {
120
+ // enter=500ms, exit uses default=100ms
121
+ expect(await elementExists(page, 'scenario-43-target'), 'Initially visible').toBe(
122
+ true
123
+ )
124
+
125
+ // hide - uses default=100ms (fast)
126
+ await page.getByTestId('scenario-43-trigger').click()
127
+ await page.waitForTimeout(300)
128
+ expect(await elementExists(page, 'scenario-43-target'), 'Hidden').toBe(false)
129
+
130
+ // show - uses enter=500ms (slow)
131
+ await page.getByTestId('scenario-43-trigger').click()
132
+ await page.waitForTimeout(200)
133
+ const midOpacity = await getOpacity(page, 'scenario-43-target')
134
+
135
+ expect(
136
+ isIntermediate(midOpacity, 0, 1),
137
+ `Enter opacity (${midOpacity.toFixed(2)}) should be intermediate at 200ms into 500ms`
138
+ ).toBe(true)
139
+
140
+ await page.waitForTimeout(500)
141
+ expect(await getOpacity(page, 'scenario-43-target'), 'Final').toBeCloseTo(1, 1)
142
+ })
143
+
144
+ test('scenario 44: exit-only transition - exit uses specified 500ms (slow)', async ({
145
+ page,
146
+ }) => {
147
+ // exit=500ms, enter uses default=100ms
148
+ expect(await elementExists(page, 'scenario-44-target'), 'Initially visible').toBe(
149
+ true
150
+ )
151
+
152
+ // trigger exit - uses 500ms (slow)
153
+ await page.getByTestId('scenario-44-trigger').click()
154
+
155
+ // at 200ms into a 500ms animation, should still be in progress
156
+ await page.waitForTimeout(200)
157
+
158
+ expect(
159
+ await elementExists(page, 'scenario-44-target'),
160
+ 'Still exists during 500ms exit'
161
+ ).toBe(true)
162
+ const midOpacity = await getOpacity(page, 'scenario-44-target')
163
+
164
+ // with 500ms exit, opacity should still be intermediate at 200ms
165
+ expect(
166
+ isIntermediate(midOpacity, 1, 0),
167
+ `Mid-exit opacity (${midOpacity.toFixed(2)}) should be intermediate at 200ms into 500ms`
168
+ ).toBe(true)
169
+
170
+ // wait for completion (500ms + buffer)
171
+ await page.waitForTimeout(500)
172
+ expect(await elementExists(page, 'scenario-44-target'), 'Gone after 500ms exit').toBe(
173
+ false
174
+ )
175
+ })
176
+
177
+ test('scenario 45: enter/exit/default - property changes use default animation', async ({
178
+ page,
179
+ }) => {
180
+ // enter=300ms, exit=100ms, default=500ms for property changes
181
+ expect(await elementExists(page, 'scenario-45-target'), 'Initially visible').toBe(
182
+ true
183
+ )
184
+ const initialOpacity = await getOpacity(page, 'scenario-45-target')
185
+ expect(initialOpacity, 'Initial opacity').toBeCloseTo(1, 1)
186
+
187
+ // click prop button to change opacity (not enter/exit, so uses default=500ms)
188
+ await page.getByTestId('scenario-45-trigger-prop').click()
189
+
190
+ // at 150ms into 500ms animation, should be animating (not yet at final 0.5)
191
+ await page.waitForTimeout(150)
192
+ const midOpacity = await getOpacity(page, 'scenario-45-target')
193
+
194
+ // should still be above final value since animation takes 500ms
195
+ expect(
196
+ midOpacity,
197
+ `Mid opacity (${midOpacity.toFixed(2)}) should still be above 0.6`
198
+ ).toBeGreaterThan(0.6)
199
+
200
+ // wait for completion (500ms animation + buffer)
201
+ await page.waitForTimeout(500)
202
+ expect(await getOpacity(page, 'scenario-45-target'), 'Final opacity').toBeCloseTo(
203
+ 0.5,
204
+ 1
205
+ )
206
+ })
207
+
208
+ test('scenario 46: enter/exit with per-property config - opacity uses its own animation', async ({
209
+ page,
210
+ }) => {
211
+ // enter=300ms for scale, exit=100ms for scale, but opacity always=500ms
212
+ // hide first
213
+ await page.getByTestId('scenario-46-trigger').click()
214
+ await page.waitForTimeout(700) // opacity=500ms + buffer
215
+
216
+ expect(await elementExists(page, 'scenario-46-target'), 'Hidden').toBe(false)
217
+
218
+ // show - opacity should use 500ms even though enter=300ms for other props
219
+ await page.getByTestId('scenario-46-trigger').click()
220
+ await page.waitForTimeout(200)
221
+
222
+ const midOpacity = await getOpacity(page, 'scenario-46-target')
223
+
224
+ // at 200ms into 500ms opacity animation, should be intermediate
225
+ expect(
226
+ isIntermediate(midOpacity, 0, 1),
227
+ `Mid-enter opacity (${midOpacity.toFixed(2)}) should be intermediate at 200ms into 500ms`
228
+ ).toBe(true)
229
+
230
+ await page.waitForTimeout(500)
231
+ expect(await getOpacity(page, 'scenario-46-target'), 'Final').toBeCloseTo(1, 1)
232
+ })
233
+
234
+ test('scenario 47: enter/exit with delay - animations start after delay', async ({
235
+ page,
236
+ }) => {
237
+ // enter=300ms, exit=100ms, delay=200ms
238
+ // hide first to test enter animation with delay
239
+ await page.getByTestId('scenario-47-trigger').click()
240
+ await page.waitForTimeout(600) // 200ms delay + 100ms exit + buffer
241
+
242
+ expect(await elementExists(page, 'scenario-47-target'), 'Hidden').toBe(false)
243
+
244
+ // show - should have 200ms delay before enter animation starts
245
+ await page.getByTestId('scenario-47-trigger').click()
246
+
247
+ // element appears but at 100ms (during delay), should still be at enterStyle values
248
+ await page.waitForTimeout(100)
249
+ expect(
250
+ await elementExists(page, 'scenario-47-target'),
251
+ 'Should appear immediately'
252
+ ).toBe(true)
253
+
254
+ const duringDelayOpacity = await getOpacity(page, 'scenario-47-target')
255
+ // during 200ms delay, opacity should be near 0 (enterStyle)
256
+ expect(duringDelayOpacity, 'During delay, should be at enterStyle').toBeLessThan(0.3)
257
+
258
+ // after delay + some animation time (200ms delay + ~150ms into 300ms animation)
259
+ await page.waitForTimeout(250)
260
+ const afterDelayOpacity = await getOpacity(page, 'scenario-47-target')
261
+ // should be animating or completed by now
262
+ expect(afterDelayOpacity, 'After delay, should be animating').toBeGreaterThan(0.3)
263
+
264
+ // wait for full completion
265
+ await page.waitForTimeout(500)
266
+ expect(await getOpacity(page, 'scenario-47-target'), 'Final').toBeCloseTo(1, 1)
267
+ })
268
+
269
+ test('enter animation timing differs from exit timing', async ({ page }) => {
270
+ // scenario 42 uses enter=500ms, exit=100ms
271
+ const startTime = Date.now()
272
+
273
+ // trigger exit
274
+ await page.getByTestId('scenario-42-trigger').click()
275
+
276
+ // wait for element to disappear
277
+ await page.waitForFunction(
278
+ (testId) => !document.querySelector(`[data-testid="${testId}"]`),
279
+ 'scenario-42-target',
280
+ { timeout: 5000 }
281
+ )
282
+
283
+ const exitDuration = Date.now() - startTime
284
+
285
+ // exit should be fast (100ms + overhead)
286
+ expect(exitDuration, 'Exit should be fast').toBeLessThan(500)
287
+
288
+ // now trigger enter
289
+ const enterStart = Date.now()
290
+ await page.getByTestId('scenario-42-trigger').click()
291
+
292
+ // wait for element to fully appear
293
+ await page.waitForTimeout(100)
294
+ await page.waitForFunction(
295
+ (testId) => {
296
+ const el = document.querySelector(`[data-testid="${testId}"]`)
297
+ if (!el) return false
298
+ return Number.parseFloat(getComputedStyle(el).opacity) > 0.9
299
+ },
300
+ 'scenario-42-target',
301
+ { timeout: 5000 }
302
+ )
303
+
304
+ const enterDuration = Date.now() - enterStart
305
+
306
+ // enter should be slower than exit
307
+ expect(enterDuration, 'Enter should be slower than exit').toBeGreaterThan(
308
+ exitDuration
309
+ )
310
+ })
311
+ })
@@ -0,0 +1,16 @@
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: 'UseTheme', type: 'useCase' })
7
+ })
8
+
9
+ test(`useTheme() returns right values`, async ({ page }) => {
10
+ expect(await page.locator('#theme-get').innerText()).toBe(`var(--background)`)
11
+ // themeDev uses hsla format
12
+ expect(await page.locator('#theme-val').innerText()).toBe(`hsla(0, 0%, 100%, 1)`)
13
+ expect(await page.locator('#token-get').innerText()).toBe(`var(--blue1)`)
14
+ // Updated for Radix v3 hex format
15
+ expect(await page.locator('#token-val').innerText()).toBe(`#fbfdff`)
16
+ })
@@ -0,0 +1,164 @@
1
+ import { expect, test } from '@playwright/test'
2
+ import { TEST_IDS } from '../src/constants/test-ids'
3
+
4
+ import { setupPage } from './test-utils'
5
+ import { getStyles } from './utils'
6
+
7
+ /**
8
+ * Tests for the v5 theme builder output, covering the documented accent usage patterns:
9
+ *
10
+ * 1. <Theme name="accent"> - theme-builder.mdx, how-to-upgrade.mdx
11
+ * 2. <Button theme="accent"> - config-v5.mdx, ButtonDemo.tsx
12
+ * 3. $accentBackground / $accentColor - config-v5.mdx
13
+ * 4. $accent1-$accent12 raw tokens
14
+ */
15
+
16
+ test.beforeEach(async ({ page }) => {
17
+ await setupPage(page, {
18
+ name: 'V5ThemeBuilderOutput',
19
+ type: 'useCase',
20
+ searchParams: { generatedV5: 'true' },
21
+ })
22
+ })
23
+
24
+ // --- <Theme name="accent"> ---
25
+
26
+ test('<Theme name="accent"> $background differs from base $background', async ({
27
+ page,
28
+ }) => {
29
+ const baseEl = page.getByTestId(TEST_IDS.baseBackground)
30
+ const accentEl = page.getByTestId(TEST_IDS.accentThemeBackground)
31
+
32
+ await expect(baseEl).toBeVisible()
33
+ await expect(accentEl).toBeVisible()
34
+
35
+ const baseStyles = await getStyles(baseEl)
36
+ const accentStyles = await getStyles(accentEl)
37
+
38
+ // The accent theme should produce a visually different background from the base theme
39
+ expect(accentStyles.backgroundColor).not.toBe(baseStyles.backgroundColor)
40
+ })
41
+
42
+ test('<Theme name="accent"> $background is not gray (has color)', async ({ page }) => {
43
+ const accentEl = page.getByTestId(TEST_IDS.accentThemeBackground)
44
+ await expect(accentEl).toBeVisible()
45
+
46
+ const styles = await getStyles(accentEl)
47
+
48
+ // The generated theme has a purple accent (hue 250). Verify it's not a pure gray.
49
+ // In a gray color, r === g === b. A colored accent will have channel differences.
50
+ const match = styles.backgroundColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/)
51
+ expect(match).toBeTruthy()
52
+
53
+ if (match) {
54
+ const [, r, g, b] = match.map(Number)
55
+ const isGray = r === g && g === b
56
+ expect(isGray).toBe(false)
57
+ }
58
+ })
59
+
60
+ test('<Theme name="accent"> $color is defined', async ({ page }) => {
61
+ const textEl = page.getByTestId(TEST_IDS.accentThemeColor)
62
+ await expect(textEl).toBeVisible()
63
+
64
+ const styles = await getStyles(textEl)
65
+ expect(styles.color).toBeDefined()
66
+ expect(styles.color).not.toBe('')
67
+ })
68
+
69
+ // --- <Button theme="accent"> ---
70
+
71
+ test('<Button theme="accent"> has different background than base button', async ({
72
+ page,
73
+ }) => {
74
+ const baseBtn = page.getByTestId(TEST_IDS.baseButton)
75
+ const accentBtn = page.getByTestId(TEST_IDS.accentPropButton)
76
+
77
+ await expect(baseBtn).toBeVisible()
78
+ await expect(accentBtn).toBeVisible()
79
+
80
+ const baseStyles = await getStyles(baseBtn)
81
+ const accentStyles = await getStyles(accentBtn)
82
+
83
+ // Accent button should look different from the default button
84
+ expect(accentStyles.backgroundColor).not.toBe(baseStyles.backgroundColor)
85
+ })
86
+
87
+ test('<Button theme="accent"> background is not gray', async ({ page }) => {
88
+ const accentBtn = page.getByTestId(TEST_IDS.accentPropButton)
89
+ await expect(accentBtn).toBeVisible()
90
+
91
+ const styles = await getStyles(accentBtn)
92
+
93
+ const match = styles.backgroundColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/)
94
+ expect(match).toBeTruthy()
95
+
96
+ if (match) {
97
+ const [, r, g, b] = match.map(Number)
98
+ const isGray = r === g && g === b
99
+ expect(isGray).toBe(false)
100
+ }
101
+ })
102
+
103
+ // --- $accentBackground token ---
104
+
105
+ test('$accentBackground token resolves to a non-gray color', async ({ page }) => {
106
+ const el = page.getByTestId(TEST_IDS.accentBgToken)
107
+ await expect(el).toBeVisible()
108
+
109
+ const styles = await getStyles(el)
110
+ expect(styles.backgroundColor).toBeDefined()
111
+ expect(styles.backgroundColor).not.toBe('')
112
+
113
+ const match = styles.backgroundColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/)
114
+ expect(match).toBeTruthy()
115
+
116
+ if (match) {
117
+ const [, r, g, b] = match.map(Number)
118
+ const isGray = r === g && g === b
119
+ expect(isGray).toBe(false)
120
+ }
121
+ })
122
+
123
+ // --- $accent1-12 raw tokens ---
124
+
125
+ test('$accent1-12 palette tokens render a gradient (not all identical)', async ({
126
+ page,
127
+ }) => {
128
+ const colors: string[] = []
129
+
130
+ for (let i = 1; i <= 12; i++) {
131
+ const swatch = page.getByTestId(`palette-accent-${i}`)
132
+ await expect(swatch).toBeVisible()
133
+
134
+ const styles = await getStyles(swatch)
135
+ expect(styles.backgroundColor).toBeDefined()
136
+ colors.push(styles.backgroundColor)
137
+ }
138
+
139
+ // Palette should have multiple distinct values (a gradient, not flat)
140
+ const uniqueColors = new Set(colors)
141
+ expect(uniqueColors.size).toBeGreaterThan(1)
142
+ })
143
+
144
+ // --- Color child themes ---
145
+
146
+ test('color child themes (yellow, red, green, blue) have distinct backgrounds', async ({
147
+ page,
148
+ }) => {
149
+ const yellowBtn = page.getByTestId('button-yellow')
150
+ const redBtn = page.getByTestId('button-red')
151
+ const greenBtn = page.getByTestId('button-green')
152
+
153
+ await expect(yellowBtn).toBeVisible()
154
+ await expect(redBtn).toBeVisible()
155
+ await expect(greenBtn).toBeVisible()
156
+
157
+ const yellowStyles = await getStyles(yellowBtn)
158
+ const redStyles = await getStyles(redBtn)
159
+ const greenStyles = await getStyles(greenBtn)
160
+
161
+ expect(yellowStyles.backgroundColor).not.toBe(redStyles.backgroundColor)
162
+ expect(redStyles.backgroundColor).not.toBe(greenStyles.backgroundColor)
163
+ expect(yellowStyles.backgroundColor).not.toBe(greenStyles.backgroundColor)
164
+ })
@@ -0,0 +1,11 @@
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: 'VariantFontFamily', type: 'useCase' })
7
+ })
8
+
9
+ test(`testing things...`, async ({ page }) => {
10
+ await expect(page.getByTestId('heading').first()).toHaveCSS('font-size', '11px')
11
+ })
@@ -0,0 +1,53 @@
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: 'VariantsOrder', type: 'useCase' })
8
+ })
9
+
10
+ test(`variants apply below default props but above parent defaultvariants/props as you nest styled()`, async ({
11
+ page,
12
+ }) => {
13
+ expect(await getStyles(page.getByTestId('button').first())).toMatchObject({
14
+ flexDirection: 'row',
15
+ })
16
+
17
+ expect(await getStyles(page.getByTestId('text1').first())).toMatchObject({
18
+ fontSize: '16px',
19
+ })
20
+
21
+ expect(await getStyles(page.getByTestId('text2').first())).toMatchObject({
22
+ fontSize: '15px',
23
+ })
24
+
25
+ expect(await getStyles(page.getByTestId('text3').first())).toMatchObject({
26
+ fontSize: '30px',
27
+ })
28
+
29
+ expect(await getStyles(page.getByTestId('text4').first())).toMatchObject({
30
+ fontSize: '40px',
31
+ })
32
+ })
33
+
34
+ // Issue #3669: https://github.com/hanzoai/gui/issues/3669
35
+ test(`variant chaining: child variant (test2) translates to parent variant (test) and propagates via context`, async ({
36
+ page,
37
+ }) => {
38
+ // Direct test=true on ButtonFrame
39
+ const directFrame = await getStyles(page.getByTestId('frame-test-direct').first())
40
+ expect(directFrame.backgroundColor).toBe('rgb(255, 0, 0)') // red
41
+
42
+ // test2=true on ButtonFrame2 should translate to test=true
43
+ const chainedFrame = await getStyles(page.getByTestId('frame-test2-chained').first())
44
+ expect(chainedFrame.backgroundColor).toBe('rgb(255, 0, 0)') // same red
45
+
46
+ // ButtonText inside direct test should get white color via context
47
+ const directText = await getStyles(page.getByTestId('text-test-direct').first())
48
+ expect(directText.color).toBe('rgb(255, 255, 255)') // white
49
+
50
+ // ButtonText inside chained test2 should also get white via context
51
+ const chainedText = await getStyles(page.getByTestId('text-test2-chained').first())
52
+ expect(chainedText.color).toBe('rgb(255, 255, 255)') // white - this is the regression
53
+ })