Browse Source

Merge branch 'main' into reflex-0.4.0

Nikhil Rao 1 year ago
parent
commit
27b9a10233

+ 2 - 0
.github/workflows/pre-commit.yml

@@ -27,3 +27,5 @@ jobs:
       - run: |
       - run: |
           poetry run pip install pre-commit
           poetry run pip install pre-commit
           poetry run pre-commit run --all-files
           poetry run pre-commit run --all-files
+        env:
+          SKIP: update-pyi-files

+ 18 - 9
.pre-commit-config.yaml

@@ -2,24 +2,33 @@ repos:
   - repo: https://github.com/psf/black
   - repo: https://github.com/psf/black
     rev: 22.10.0
     rev: 22.10.0
     hooks:
     hooks:
-    - id: black
-      args: [integration, reflex, tests]
+      - id: black
+        args: [integration, reflex, tests]
 
 
   - repo: https://github.com/charliermarsh/ruff-pre-commit
   - repo: https://github.com/charliermarsh/ruff-pre-commit
     rev: v0.0.244
     rev: v0.0.244
     hooks:
     hooks:
-    - id: ruff
-      args: [--fix, --exit-non-zero-on-fix]
+      - id: ruff
+        args: [--fix, --exit-non-zero-on-fix]
 
 
   - repo: https://github.com/RobertCraigie/pyright-python
   - repo: https://github.com/RobertCraigie/pyright-python
     rev: v1.1.313
     rev: v1.1.313
     hooks:
     hooks:
-    - id: pyright
-      args: [integration, reflex, tests]
-      language: system
+      - id: pyright
+        args: [integration, reflex, tests]
+        language: system
 
 
   - repo: https://github.com/terrencepreilly/darglint
   - repo: https://github.com/terrencepreilly/darglint
     rev: v1.8.1
     rev: v1.8.1
     hooks:
     hooks:
-    - id: darglint
-      exclude: '^reflex/reflex.py'
+      - id: darglint
+        exclude: '^reflex/reflex.py'
+
+  - repo: local
+    hooks:
+      - id: update-pyi-files
+        name: update-pyi-files
+        always_run: true
+        language: system
+        description: 'Update pyi files as needed'
+        entry: python scripts/pyi_generator.py

+ 90 - 0
integration/test_large_state.py

@@ -0,0 +1,90 @@
+"""Test large state."""
+import time
+
+import jinja2
+import pytest
+from selenium.webdriver.common.by import By
+
+from reflex.testing import AppHarness, WebDriver
+
+LARGE_STATE_APP_TEMPLATE = """
+import reflex as rx
+
+class State(rx.State):
+    var0: int = 0
+    {% for i in range(1, var_count) %}
+    var{{ i }}: str = "{{ i }}" * 10000
+    {% endfor %}
+
+    def increment_var0(self):
+        self.var0 += 1
+
+
+def index() -> rx.Component:
+    return rx.box(rx.button(State.var0, on_click=State.increment_var0, id="button"))
+
+app = rx.App()
+app.add_page(index)
+"""
+
+
+def get_driver(large_state) -> WebDriver:
+    """Get an instance of the browser open to the large_state app.
+
+    Args:
+        large_state: harness for LargeState app
+
+    Returns:
+        WebDriver instance.
+    """
+    assert large_state.app_instance is not None, "app is not running"
+    return large_state.frontend()
+
+
+@pytest.mark.parametrize("var_count", [1, 10, 100, 1000, 10000])
+def test_large_state(var_count: int, tmp_path_factory, benchmark):
+    """Measure how long it takes for button click => state update to round trip.
+
+    Args:
+        var_count: number of variables to store in the state
+        tmp_path_factory: pytest fixture
+        benchmark: pytest fixture
+
+    Raises:
+        TimeoutError: if the state doesn't update within 30 seconds
+    """
+    template = jinja2.Template(LARGE_STATE_APP_TEMPLATE)
+    large_state_rendered = template.render(var_count=var_count)
+
+    with AppHarness.create(
+        root=tmp_path_factory.mktemp(f"large_state"),
+        app_source=large_state_rendered,
+        app_name="large_state",
+    ) as large_state:
+        driver = get_driver(large_state)
+        try:
+            assert large_state.app_instance is not None
+            button = driver.find_element(By.ID, "button")
+
+            t = time.time()
+            while button.text != "0":
+                time.sleep(0.1)
+                if time.time() - t > 30.0:
+                    raise TimeoutError("Timeout waiting for initial state")
+
+            times_clicked = 0
+
+            def round_trip(clicks: int, timeout: float):
+                t = time.time()
+                for _ in range(clicks):
+                    button.click()
+                nonlocal times_clicked
+                times_clicked += clicks
+                while button.text != str(times_clicked):
+                    time.sleep(0.005)
+                    if time.time() - t > timeout:
+                        raise TimeoutError("Timeout waiting for state update")
+
+            benchmark(round_trip, clicks=10, timeout=30.0)
+        finally:
+            driver.quit()

+ 8 - 0
reflex/components/chakra/disclosure/tabs.py

@@ -90,20 +90,28 @@ class Tab(ChakraComponent):
     # The id of the panel.
     # The id of the panel.
     panel_id: Var[str]
     panel_id: Var[str]
 
 
+    _valid_parents: List[str] = ["TabList"]
+
 
 
 class TabList(ChakraComponent):
 class TabList(ChakraComponent):
     """Wrapper for the Tab components."""
     """Wrapper for the Tab components."""
 
 
     tag = "TabList"
     tag = "TabList"
 
 
+    _valid_parents: List[str] = ["Tabs"]
+
 
 
 class TabPanels(ChakraComponent):
 class TabPanels(ChakraComponent):
     """Wrapper for the Tab components."""
     """Wrapper for the Tab components."""
 
 
     tag = "TabPanels"
     tag = "TabPanels"
 
 
+    _valid_parents: List[str] = ["Tabs"]
+
 
 
 class TabPanel(ChakraComponent):
 class TabPanel(ChakraComponent):
     """An element that contains the content associated with a tab."""
     """An element that contains the content associated with a tab."""
 
 
     tag = "TabPanel"
     tag = "TabPanel"
+
+    _valid_parents: List[str] = ["TabPanels"]

+ 17 - 1
reflex/components/component.py

@@ -155,6 +155,9 @@ class Component(BaseComponent, ABC):
     # only components that are allowed as children
     # only components that are allowed as children
     _valid_children: List[str] = []
     _valid_children: List[str] = []
 
 
+    # only components that are allowed as parent
+    _valid_parents: List[str] = []
+
     # custom attribute
     # custom attribute
     custom_attrs: Dict[str, Union[Var, str]] = {}
     custom_attrs: Dict[str, Union[Var, str]] = {}
 
 
@@ -651,7 +654,8 @@ class Component(BaseComponent, ABC):
             children: The children of the component.
             children: The children of the component.
 
 
         """
         """
-        if not self._invalid_children and not self._valid_children:
+        skip_parentable = all(child._valid_parents == [] for child in children)
+        if not self._invalid_children and not self._valid_children and skip_parentable:
             return
             return
 
 
         comp_name = type(self).__name__
         comp_name = type(self).__name__
@@ -671,6 +675,15 @@ class Component(BaseComponent, ABC):
                     f"The component `{comp_name}` only allows the components: {valid_child_list} as children. Got `{child_name}` instead."
                     f"The component `{comp_name}` only allows the components: {valid_child_list} as children. Got `{child_name}` instead."
                 )
                 )
 
 
+        def validate_vaild_parent(child_name, valid_parents):
+            if comp_name not in valid_parents:
+                valid_parent_list = ", ".join(
+                    [f"`{v_parent}`" for v_parent in valid_parents]
+                )
+                raise ValueError(
+                    f"The component `{child_name}` can only be a child of the components: {valid_parent_list}. Got `{comp_name}` instead."
+                )
+
         for child in children:
         for child in children:
             name = type(child).__name__
             name = type(child).__name__
 
 
@@ -680,6 +693,9 @@ class Component(BaseComponent, ABC):
             if self._valid_children:
             if self._valid_children:
                 validate_valid_child(name)
                 validate_valid_child(name)
 
 
+            if child._valid_parents:
+                validate_vaild_parent(name, child._valid_parents)
+
     @staticmethod
     @staticmethod
     def _get_vars_from_event_triggers(
     def _get_vars_from_event_triggers(
         event_triggers: dict[str, EventChain | Var],
         event_triggers: dict[str, EventChain | Var],

+ 1 - 0
reflex/components/core/__init__.py

@@ -1,5 +1,6 @@
 """Core Reflex components."""
 """Core Reflex components."""
 
 
+from . import layout as layout
 from .banner import ConnectionBanner, ConnectionModal
 from .banner import ConnectionBanner, ConnectionModal
 from .cond import Cond, cond
 from .cond import Cond, cond
 from .debounce import DebounceInput
 from .debounce import DebounceInput

+ 1 - 0
reflex/components/core/layout/__init__.py

@@ -0,0 +1 @@
+"""Core layout components."""

+ 4 - 3
reflex/components/lucide/icon.py

@@ -55,14 +55,15 @@ class Icon(LucideIconComponent):
                 f"Invalid icon tag: {props['tag']}. Please use one of the following: {', '.join(LUCIDE_ICON_LIST[0:25])}, ..."
                 f"Invalid icon tag: {props['tag']}. Please use one of the following: {', '.join(LUCIDE_ICON_LIST[0:25])}, ..."
                 "\nSee full list at https://lucide.dev/icons."
                 "\nSee full list at https://lucide.dev/icons."
             )
             )
-        props["tag"] = format.to_title_case(props["tag"]) + "Icon"
+
+        props["tag"] = format.to_title_case(format.to_snake_case(props["tag"])) + "Icon"
         props["alias"] = f"Lucide{props['tag']}"
         props["alias"] = f"Lucide{props['tag']}"
         return super().create(*children, **props)
         return super().create(*children, **props)
 
 
-    def _apply_theme(self, theme: Component | None):
+    def _apply_theme(self, theme: Component):
         self.style = Style(
         self.style = Style(
             {
             {
-                "color": f"var(--accent-12)",
+                "color": f"var(--current-color)",
                 **self.style,
                 **self.style,
             }
             }
         )
         )

+ 10 - 0
reflex/components/radix/primitives/__init__.py

@@ -2,5 +2,15 @@
 
 
 from .accordion import accordion
 from .accordion import accordion
 from .form import form
 from .form import form
+from .drawer import (
+    drawer_close,
+    drawer_content,
+    drawer_description,
+    drawer_overlay,
+    drawer_portal,
+    drawer_root,
+    drawer_title,
+    drawer_trigger,
+)
 from .progress import progress
 from .progress import progress
 from .slider import slider
 from .slider import slider

+ 1 - 1
reflex/components/radix/primitives/accordion.py

@@ -7,8 +7,8 @@ from typing import Any, Dict, Literal
 
 
 from reflex.components.component import Component
 from reflex.components.component import Component
 from reflex.components.core import cond, match
 from reflex.components.core import cond, match
+from reflex.components.lucide.icon import Icon
 from reflex.components.radix.primitives.base import RadixPrimitiveComponent
 from reflex.components.radix.primitives.base import RadixPrimitiveComponent
-from reflex.components.radix.themes.components.icons import Icon
 from reflex.style import (
 from reflex.style import (
     Style,
     Style,
     convert_dict_to_style_and_format_emotion,
     convert_dict_to_style_and_format_emotion,

+ 1 - 1
reflex/components/radix/primitives/accordion.pyi

@@ -11,8 +11,8 @@ from types import SimpleNamespace
 from typing import Any, Dict, Literal
 from typing import Any, Dict, Literal
 from reflex.components.component import Component
 from reflex.components.component import Component
 from reflex.components.core import cond, match
 from reflex.components.core import cond, match
+from reflex.components.lucide.icon import Icon
 from reflex.components.radix.primitives.base import RadixPrimitiveComponent
 from reflex.components.radix.primitives.base import RadixPrimitiveComponent
-from reflex.components.radix.themes.components.icons import Icon
 from reflex.style import (
 from reflex.style import (
     Style,
     Style,
     convert_dict_to_style_and_format_emotion,
     convert_dict_to_style_and_format_emotion,

+ 240 - 0
reflex/components/radix/primitives/drawer.py

@@ -0,0 +1,240 @@
+"""Drawer components based on Radix primitives."""
+# Based on Vaul: https://github.com/emilkowalski/vaul
+# Style based on https://ui.shadcn.com/docs/components/drawer
+from __future__ import annotations
+
+from typing import Any, Dict, List, Literal, Optional, Union
+
+from reflex.components.radix.primitives.base import RadixPrimitiveComponentWithClassName
+from reflex.constants import EventTriggers
+from reflex.vars import Var
+
+
+class DrawerComponent(RadixPrimitiveComponentWithClassName):
+    """A Drawer component."""
+
+    library = "vaul"
+
+    lib_dependencies: List[str] = ["@radix-ui/react-dialog@^1.0.5"]
+
+
+LiteralDirectionType = Literal[
+    "top",
+    "bottom",
+    "left",
+    "right",
+]
+
+
+class DrawerRoot(DrawerComponent):
+    """The Root component of a Drawer, contains all parts of a drawer."""
+
+    tag = "Drawer.Root"
+
+    # Whether the drawer is open or not.
+    open: Var[bool]
+
+    # Enable background scaling,
+    # it requires an element with [vaul-drawer-wrapper] data attribute to scale its background.
+    should_scale_background: Var[bool]
+
+    # Number between 0 and 1 that determines when the drawer should be closed.
+    close_threshold: Var[float]
+
+    # Array of numbers from 0 to 100 that corresponds to % of the screen a given snap point should take up. Should go from least visible.
+    # Also Accept px values, which doesn't take screen height into account.
+    snap_points: Optional[List[Union[str, float]]]
+
+    # Index of a snapPoint from which the overlay fade should be applied.
+    # Defaults to the last snap point.
+    # TODO: will it accept -1 then?
+    fade_from_index: Var[int]
+
+    # Duration for which the drawer is not draggable after scrolling content inside of the drawer. Defaults to 500ms
+    scroll_lock_timeout: Var[int]
+
+    # When `False`, it allows to interact with elements outside of the drawer without closing it.
+    # Defaults to `True`.
+    modal: Var[bool]
+
+    # Direction of the drawer. Defaults to `"bottom"`
+    direction: Var[LiteralDirectionType]
+
+    # When `True`, it prevents scroll restoration
+    # when the drawer is closed after a navigation happens inside of it.
+    # Defaults to `True`.
+    preventScrollRestoration: Var[bool]
+
+    def get_event_triggers(self) -> Dict[str, Any]:
+        """Get the event triggers that pass the component's value to the handler.
+
+        Returns:
+            A dict mapping the event trigger to the var that is passed to the handler.
+        """
+        return {
+            **super().get_event_triggers(),
+            EventTriggers.ON_OPEN_CHANGE: lambda e0: [e0.target.value],
+        }
+
+
+class DrawerTrigger(DrawerComponent):
+    """The button that opens the dialog."""
+
+    tag = "Drawer.Trigger"
+
+    as_child: Var[bool]
+
+
+class DrawerPortal(DrawerComponent):
+    """Portals your drawer into the body."""
+
+    tag = "Drawer.Portal"
+
+
+# Based on https://www.radix-ui.com/primitives/docs/components/dialog#content
+class DrawerContent(DrawerComponent):
+    """Content that should be rendered in the drawer."""
+
+    tag = "Drawer.Content"
+
+    # Style set partially based on the source code at https://ui.shadcn.com/docs/components/drawer
+    def _get_style(self) -> dict:
+        """Get the style for the component.
+
+        Returns:
+            The dictionary of the component style as value and the style notation as key.
+        """
+        base_style = {
+            "left": "0",
+            "right": "0",
+            "bottom": "0",
+            "top": "0",
+            "position": "fixed",
+            "z_index": 50,
+            "display": "flex",
+        }
+        style = self.style or {}
+        base_style.update(style)
+        self.style.update(
+            {
+                "css": base_style,
+            }
+        )
+        return self.style
+
+    def get_event_triggers(self) -> Dict[str, Any]:
+        """Get the events triggers signatures for the component.
+
+        Returns:
+            The signatures of the event triggers.
+        """
+        return {
+            **super().get_event_triggers(),
+            # DrawerContent is based on Radix DialogContent
+            # These are the same triggers as DialogContent
+            EventTriggers.ON_OPEN_AUTO_FOCUS: lambda e0: [e0.target.value],
+            EventTriggers.ON_CLOSE_AUTO_FOCUS: lambda e0: [e0.target.value],
+            EventTriggers.ON_ESCAPE_KEY_DOWN: lambda e0: [e0.target.value],
+            EventTriggers.ON_POINTER_DOWN_OUTSIDE: lambda e0: [e0.target.value],
+            EventTriggers.ON_INTERACT_OUTSIDE: lambda e0: [e0.target.value],
+        }
+
+
+class DrawerOverlay(DrawerComponent):
+    """A layer that covers the inert portion of the view when the dialog is open."""
+
+    tag = "Drawer.Overlay"
+
+    # Style set based on the source code at https://ui.shadcn.com/docs/components/drawer
+    def _get_style(self) -> dict:
+        """Get the style for the component.
+
+        Returns:
+            The dictionary of the component style as value and the style notation as key.
+        """
+        base_style = {
+            "position": "fixed",
+            "left": "0",
+            "right": "0",
+            "bottom": "0",
+            "top": "0",
+            "z_index": 50,
+            "background": "rgba(0, 0, 0, 0.8)",
+        }
+        style = self.style or {}
+        base_style.update(style)
+        self.style.update(
+            {
+                "css": base_style,
+            }
+        )
+        return self.style
+
+
+class DrawerClose(DrawerComponent):
+    """A button that closes the drawer."""
+
+    tag = "Drawer.Close"
+
+
+class DrawerTitle(DrawerComponent):
+    """A title for the drawer."""
+
+    tag = "Drawer.Title"
+
+    # Style set based on the source code at https://ui.shadcn.com/docs/components/drawer
+    def _get_style(self) -> dict:
+        """Get the style for the component.
+
+        Returns:
+            The dictionary of the component style as value and the style notation as key.
+        """
+        base_style = {
+            "font-size": "1.125rem",
+            "font-weight": "600",
+            "line-weight": "1",
+            "letter-spacing": "-0.05em",
+        }
+        style = self.style or {}
+        base_style.update(style)
+        self.style.update(
+            {
+                "css": base_style,
+            }
+        )
+        return self.style
+
+
+class DrawerDescription(DrawerComponent):
+    """A description for the drawer."""
+
+    tag = "Drawer.Description"
+
+    # Style set based on the source code at https://ui.shadcn.com/docs/components/drawer
+    def _get_style(self) -> dict:
+        """Get the style for the component.
+
+        Returns:
+            The dictionary of the component style as value and the style notation as key.
+        """
+        base_style = {
+            "font-size": "0.875rem",
+        }
+        style = self.style or {}
+        base_style.update(style)
+        self.style.update(
+            {
+                "css": base_style,
+            }
+        )
+        return self.style
+
+
+drawer_root = DrawerRoot.create
+drawer_trigger = DrawerTrigger.create
+drawer_portal = DrawerPortal.create
+drawer_content = DrawerContent.create
+drawer_overlay = DrawerOverlay.create
+drawer_close = DrawerClose.create
+drawer_title = DrawerTitle.create
+drawer_description = DrawerDescription.create

+ 796 - 0
reflex/components/radix/primitives/drawer.pyi

@@ -0,0 +1,796 @@
+"""Stub file for reflex/components/radix/primitives/drawer.py"""
+# ------------------- DO NOT EDIT ----------------------
+# This file was generated by `scripts/pyi_generator.py`!
+# ------------------------------------------------------
+
+from typing import Any, Dict, Literal, Optional, Union, overload
+from reflex.vars import Var, BaseVar, ComputedVar
+from reflex.event import EventChain, EventHandler, EventSpec
+from reflex.style import Style
+from typing import Any, Dict, List, Literal, Optional, Union
+from reflex.components.radix.primitives.base import RadixPrimitiveComponentWithClassName
+from reflex.constants import EventTriggers
+from reflex.vars import Var
+
+class DrawerComponent(RadixPrimitiveComponentWithClassName):
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        as_child: Optional[Union[Var[bool], bool]] = None,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "DrawerComponent":
+        """Create the component.
+
+        Args:
+            *children: The children of the component.
+            as_child: Change the default rendered element for the one passed as a child.
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: The props of the component.
+
+        Returns:
+            The component.
+
+        Raises:
+            TypeError: If an invalid child is passed.
+        """
+        ...
+
+LiteralDirectionType = Literal["top", "bottom", "left", "right"]
+
+class DrawerRoot(DrawerComponent):
+    def get_event_triggers(self) -> Dict[str, Any]: ...
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        open: Optional[Union[Var[bool], bool]] = None,
+        should_scale_background: Optional[Union[Var[bool], bool]] = None,
+        close_threshold: Optional[Union[Var[float], float]] = None,
+        snap_points: Optional[List[Union[str, float]]] = None,
+        fade_from_index: Optional[Union[Var[int], int]] = None,
+        scroll_lock_timeout: Optional[Union[Var[int], int]] = None,
+        modal: Optional[Union[Var[bool], bool]] = None,
+        direction: Optional[
+            Union[
+                Var[Literal["top", "bottom", "left", "right"]],
+                Literal["top", "bottom", "left", "right"],
+            ]
+        ] = None,
+        preventScrollRestoration: Optional[Union[Var[bool], bool]] = None,
+        as_child: Optional[Union[Var[bool], bool]] = None,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_open_change: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "DrawerRoot":
+        """Create the component.
+
+        Args:
+            *children: The children of the component.
+            open: Whether the drawer is open or not.
+            should_scale_background: Enable background scaling,  it requires an element with [vaul-drawer-wrapper] data attribute to scale its background.
+            close_threshold: Number between 0 and 1 that determines when the drawer should be closed.
+            snap_points: Array of numbers from 0 to 100 that corresponds to % of the screen a given snap point should take up. Should go from least visible.  Also Accept px values, which doesn't take screen height into account.
+            fade_from_index: Index of a snapPoint from which the overlay fade should be applied.  Defaults to the last snap point.  TODO: will it accept -1 then?
+            scroll_lock_timeout: Duration for which the drawer is not draggable after scrolling content inside of the drawer. Defaults to 500ms
+            modal: When `False`, it allows to interact with elements outside of the drawer without closing it.  Defaults to `True`.
+            direction: Direction of the drawer. Defaults to `"bottom"`
+            preventScrollRestoration: When `True`, it prevents scroll restoration  when the drawer is closed after a navigation happens inside of it.  Defaults to `True`.
+            as_child: Change the default rendered element for the one passed as a child.
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: The props of the component.
+
+        Returns:
+            The component.
+
+        Raises:
+            TypeError: If an invalid child is passed.
+        """
+        ...
+
+class DrawerTrigger(DrawerComponent):
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        as_child: Optional[Union[Var[bool], bool]] = None,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "DrawerTrigger":
+        """Create the component.
+
+        Args:
+            *children: The children of the component.
+            as_child: Change the default rendered element for the one passed as a child.
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: The props of the component.
+
+        Returns:
+            The component.
+
+        Raises:
+            TypeError: If an invalid child is passed.
+        """
+        ...
+
+class DrawerPortal(DrawerComponent):
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        as_child: Optional[Union[Var[bool], bool]] = None,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "DrawerPortal":
+        """Create the component.
+
+        Args:
+            *children: The children of the component.
+            as_child: Change the default rendered element for the one passed as a child.
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: The props of the component.
+
+        Returns:
+            The component.
+
+        Raises:
+            TypeError: If an invalid child is passed.
+        """
+        ...
+
+class DrawerContent(DrawerComponent):
+    def get_event_triggers(self) -> Dict[str, Any]: ...
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        as_child: Optional[Union[Var[bool], bool]] = None,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_close_auto_focus: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_escape_key_down: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_interact_outside: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_open_auto_focus: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_pointer_down_outside: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "DrawerContent":
+        """Create the component.
+
+        Args:
+            *children: The children of the component.
+            as_child: Change the default rendered element for the one passed as a child.
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: The props of the component.
+
+        Returns:
+            The component.
+
+        Raises:
+            TypeError: If an invalid child is passed.
+        """
+        ...
+
+class DrawerOverlay(DrawerComponent):
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        as_child: Optional[Union[Var[bool], bool]] = None,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "DrawerOverlay":
+        """Create the component.
+
+        Args:
+            *children: The children of the component.
+            as_child: Change the default rendered element for the one passed as a child.
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: The props of the component.
+
+        Returns:
+            The component.
+
+        Raises:
+            TypeError: If an invalid child is passed.
+        """
+        ...
+
+class DrawerClose(DrawerComponent):
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        as_child: Optional[Union[Var[bool], bool]] = None,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "DrawerClose":
+        """Create the component.
+
+        Args:
+            *children: The children of the component.
+            as_child: Change the default rendered element for the one passed as a child.
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: The props of the component.
+
+        Returns:
+            The component.
+
+        Raises:
+            TypeError: If an invalid child is passed.
+        """
+        ...
+
+class DrawerTitle(DrawerComponent):
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        as_child: Optional[Union[Var[bool], bool]] = None,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "DrawerTitle":
+        """Create the component.
+
+        Args:
+            *children: The children of the component.
+            as_child: Change the default rendered element for the one passed as a child.
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: The props of the component.
+
+        Returns:
+            The component.
+
+        Raises:
+            TypeError: If an invalid child is passed.
+        """
+        ...
+
+class DrawerDescription(DrawerComponent):
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        as_child: Optional[Union[Var[bool], bool]] = None,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "DrawerDescription":
+        """Create the component.
+
+        Args:
+            *children: The children of the component.
+            as_child: Change the default rendered element for the one passed as a child.
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: The props of the component.
+
+        Returns:
+            The component.
+
+        Raises:
+            TypeError: If an invalid child is passed.
+        """
+        ...
+
+drawer_root = DrawerRoot.create
+drawer_trigger = DrawerTrigger.create
+drawer_portal = DrawerPortal.create
+drawer_content = DrawerContent.create
+drawer_overlay = DrawerOverlay.create
+drawer_close = DrawerClose.create
+drawer_title = DrawerTitle.create
+drawer_description = DrawerDescription.create

+ 4 - 4
reflex/components/radix/primitives/form.py

@@ -155,7 +155,7 @@ class FormRoot(FormComponent):
                 )._replace(merge_var_data=ref_var._var_data)
                 )._replace(merge_var_data=ref_var._var_data)
         return form_refs
         return form_refs
 
 
-    def _apply_theme(self, theme: Component | None):
+    def _apply_theme(self, theme: Component):
         return {
         return {
             "width": "260px",
             "width": "260px",
             **self.style,
             **self.style,
@@ -179,7 +179,7 @@ class FormField(FormComponent):
     # Flag to mark the form field as invalid, for server side validation.
     # Flag to mark the form field as invalid, for server side validation.
     server_invalid: Var[bool]
     server_invalid: Var[bool]
 
 
-    def _apply_theme(self, theme: Component | None):
+    def _apply_theme(self, theme: Component):
         return {
         return {
             "display": "grid",
             "display": "grid",
             "margin_bottom": "10px",
             "margin_bottom": "10px",
@@ -194,7 +194,7 @@ class FormLabel(FormComponent):
 
 
     alias = "RadixFormLabel"
     alias = "RadixFormLabel"
 
 
-    def _apply_theme(self, theme: Component | None):
+    def _apply_theme(self, theme: Component):
         return {
         return {
             "font_size": "15px",
             "font_size": "15px",
             "font_weight": "500",
             "font_weight": "500",
@@ -267,7 +267,7 @@ class FormMessage(FormComponent):
     # Forces the message to be shown. This is useful when using server-side validation.
     # Forces the message to be shown. This is useful when using server-side validation.
     force_match: Var[bool]
     force_match: Var[bool]
 
 
-    def _apply_theme(self, theme: Component | None):
+    def _apply_theme(self, theme: Component):
         return {
         return {
             "font_size": "13px",
             "font_size": "13px",
             "opacity": "0.8",
             "opacity": "0.8",

+ 2 - 2
reflex/components/radix/primitives/progress.py

@@ -29,7 +29,7 @@ class ProgressRoot(ProgressComponent):
     # The maximum progress value.
     # The maximum progress value.
     max: Var[int]
     max: Var[int]
 
 
-    def _apply_theme(self, theme: Component | None):
+    def _apply_theme(self, theme: Component):
         self.style = Style(
         self.style = Style(
             {
             {
                 "position": "relative",
                 "position": "relative",
@@ -53,7 +53,7 @@ class ProgressIndicator(ProgressComponent):
     # The current progress value.
     # The current progress value.
     value: Var[Optional[int]]
     value: Var[Optional[int]]
 
 
-    def _apply_theme(self, theme: Component | None):
+    def _apply_theme(self, theme: Component):
         self.style = Style(
         self.style = Style(
             {
             {
                 "background-color": "white",
                 "background-color": "white",

+ 15 - 0
reflex/components/radix/themes/base.py

@@ -114,6 +114,21 @@ class RadixThemesComponent(Component):
         )
         )
         return component
         return component
 
 
+    @classmethod
+    def get_fields(cls) -> dict[str, Any]:
+        """Get the pydantic fields for the component.
+
+        Returns:
+            Mapping of field name to ModelField instance.
+        """
+        fields = super().get_fields()
+        if "color_scheme" in fields:
+            # Treat "color" as a direct prop, so the translation of reflex "color_scheme"
+            # to "color" does not put the "color_scheme" value into the "style" prop.
+            fields["color"] = fields.pop("color_scheme")
+            fields["color"].required = False
+        return fields
+
     @staticmethod
     @staticmethod
     def _get_app_wrap_components() -> dict[tuple[int, str], Component]:
     def _get_app_wrap_components() -> dict[tuple[int, str], Component]:
         return {
         return {

+ 2 - 0
reflex/components/radix/themes/base.pyi

@@ -322,6 +322,8 @@ class RadixThemesComponent(Component):
             A new component instance.
             A new component instance.
         """
         """
         ...
         ...
+    @classmethod
+    def get_fields(cls) -> dict[str, Any]: ...
 
 
 class Theme(RadixThemesComponent):
 class Theme(RadixThemesComponent):
     @overload
     @overload

+ 7 - 0
reflex/components/radix/themes/layout/__init__.py

@@ -1,13 +1,20 @@
 """Layout components."""
 """Layout components."""
 
 
 from .box import Box
 from .box import Box
+from .center import Center
 from .container import Container
 from .container import Container
 from .flex import Flex
 from .flex import Flex
 from .grid import Grid
 from .grid import Grid
 from .section import Section
 from .section import Section
+from .spacer import Spacer
+from .stack import HStack, VStack
 
 
 box = Box.create
 box = Box.create
+center = Center.create
 container = Container.create
 container = Container.create
 flex = Flex.create
 flex = Flex.create
 grid = Grid.create
 grid = Grid.create
 section = Section.create
 section = Section.create
+spacer = Spacer.create
+hstack = HStack.create
+vstack = VStack.create

+ 19 - 0
reflex/components/radix/themes/layout/center.py

@@ -0,0 +1,19 @@
+"""A center component."""
+from __future__ import annotations
+
+from reflex.components.component import Component
+
+from .flex import Flex
+
+
+class Center(Flex):
+    """A center component."""
+
+    def _apply_theme(self, theme: Component):
+        self.style.update(
+            {
+                "display": "flex",
+                "align_items": "center",
+                "justify_content": "center",
+            }
+        )

+ 361 - 0
reflex/components/radix/themes/layout/center.pyi

@@ -0,0 +1,361 @@
+"""Stub file for reflex/components/radix/themes/layout/center.py"""
+# ------------------- DO NOT EDIT ----------------------
+# This file was generated by `scripts/pyi_generator.py`!
+# ------------------------------------------------------
+
+from typing import Any, Dict, Literal, Optional, Union, overload
+from reflex.vars import Var, BaseVar, ComputedVar
+from reflex.event import EventChain, EventHandler, EventSpec
+from reflex.style import Style
+from reflex.components.component import Component
+from .flex import Flex
+
+class Center(Flex):
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        color: Optional[Union[Var[str], str]] = None,
+        color_scheme: Optional[
+            Union[
+                Var[
+                    Literal[
+                        "tomato",
+                        "red",
+                        "ruby",
+                        "crimson",
+                        "pink",
+                        "plum",
+                        "purple",
+                        "violet",
+                        "iris",
+                        "indigo",
+                        "blue",
+                        "cyan",
+                        "teal",
+                        "jade",
+                        "green",
+                        "grass",
+                        "brown",
+                        "orange",
+                        "sky",
+                        "mint",
+                        "lime",
+                        "yellow",
+                        "amber",
+                        "gold",
+                        "bronze",
+                        "gray",
+                    ]
+                ],
+                Literal[
+                    "tomato",
+                    "red",
+                    "ruby",
+                    "crimson",
+                    "pink",
+                    "plum",
+                    "purple",
+                    "violet",
+                    "iris",
+                    "indigo",
+                    "blue",
+                    "cyan",
+                    "teal",
+                    "jade",
+                    "green",
+                    "grass",
+                    "brown",
+                    "orange",
+                    "sky",
+                    "mint",
+                    "lime",
+                    "yellow",
+                    "amber",
+                    "gold",
+                    "bronze",
+                    "gray",
+                ],
+            ]
+        ] = None,
+        as_child: Optional[Union[Var[bool], bool]] = None,
+        display: Optional[
+            Union[
+                Var[Literal["none", "inline-flex", "flex"]],
+                Literal["none", "inline-flex", "flex"],
+            ]
+        ] = None,
+        direction: Optional[
+            Union[
+                Var[Literal["row", "column", "row-reverse", "column-reverse"]],
+                Literal["row", "column", "row-reverse", "column-reverse"],
+            ]
+        ] = None,
+        align: Optional[
+            Union[
+                Var[Literal["start", "center", "end", "baseline", "stretch"]],
+                Literal["start", "center", "end", "baseline", "stretch"],
+            ]
+        ] = None,
+        justify: Optional[
+            Union[
+                Var[Literal["start", "center", "end", "between"]],
+                Literal["start", "center", "end", "between"],
+            ]
+        ] = None,
+        wrap: Optional[
+            Union[
+                Var[Literal["nowrap", "wrap", "wrap-reverse"]],
+                Literal["nowrap", "wrap", "wrap-reverse"],
+            ]
+        ] = None,
+        gap: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        access_key: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        auto_capitalize: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        content_editable: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        context_menu: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        dir: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        draggable: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        enter_key_hint: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        hidden: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        input_mode: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        item_prop: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        lang: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        role: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        slot: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        spell_check: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        tab_index: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        title: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        translate: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        p: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        px: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        py: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pt: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pr: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pb: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pl: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        shrink: Optional[Union[Var[Literal["0", "1"]], Literal["0", "1"]]] = None,
+        grow: Optional[Union[Var[Literal["0", "1"]], Literal["0", "1"]]] = None,
+        m: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mx: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        my: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mt: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mr: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mb: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        ml: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "Center":
+        """Create a new component instance.
+
+        Will prepend "RadixThemes" to the component tag to avoid conflicts with
+        other UI libraries for common names, like Text and Button.
+
+        Args:
+            *children: Child components.
+            color: map to CSS default color property.
+            color_scheme: map to radix color property.
+            as_child: Change the default rendered element for the one passed as a child, merging their props and behavior.
+            display: How to display the element: "none" | "inline-flex" | "flex"
+            direction: How child items are layed out: "row" | "column" | "row-reverse" | "column-reverse"
+            align: Alignment of children along the main axis: "start" | "center" | "end" | "baseline" | "stretch"
+            justify: Alignment of children along the cross axis: "start" | "center" | "end" | "between"
+            wrap: Whether children should wrap when they reach the end of their container: "nowrap" | "wrap" | "wrap-reverse"
+            gap: Gap between children: "0" - "9"
+            access_key:  Provides a hint for generating a keyboard shortcut for the current element.
+            auto_capitalize: Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
+            content_editable: Indicates whether the element's content is editable.
+            context_menu: Defines the ID of a <menu> element which will serve as the element's context menu.
+            dir: Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)
+            draggable: Defines whether the element can be dragged.
+            enter_key_hint: Hints what media types the media element is able to play.
+            hidden: Defines whether the element is hidden.
+            input_mode: Defines the type of the element.
+            item_prop: Defines the name of the element for metadata purposes.
+            lang: Defines the language used in the element.
+            role: Defines the role of the element.
+            slot: Assigns a slot in a shadow DOM shadow tree to an element.
+            spell_check: Defines whether the element may be checked for spelling errors.
+            tab_index: Defines the position of the current element in the tabbing order.
+            title: Defines a tooltip for the element.
+            translate: Specifies whether the content of an element should be translated or not.
+            p: Padding: "0" - "9"
+            px: Padding horizontal: "0" - "9"
+            py: Padding vertical: "0" - "9"
+            pt: Padding top: "0" - "9"
+            pr: Padding right: "0" - "9"
+            pb: Padding bottom: "0" - "9"
+            pl: Padding left: "0" - "9"
+            shrink: Whether the element will take up the smallest possible space: "0" | "1"
+            grow: Whether the element will take up the largest possible space: "0" | "1"
+            m: Margin: "0" - "9"
+            mx: Margin horizontal: "0" - "9"
+            my: Margin vertical: "0" - "9"
+            mt: Margin top: "0" - "9"
+            mr: Margin right: "0" - "9"
+            mb: Margin bottom: "0" - "9"
+            ml: Margin left: "0" - "9"
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: Component properties.
+
+        Returns:
+            A new component instance.
+        """
+        ...

+ 19 - 0
reflex/components/radix/themes/layout/spacer.py

@@ -0,0 +1,19 @@
+"""A spacer component."""
+from __future__ import annotations
+
+from reflex.components.component import Component
+
+from .flex import Flex
+
+
+class Spacer(Flex):
+    """A spacer component."""
+
+    def _apply_theme(self, theme: Component):
+        self.style.update(
+            {
+                "flex": 1,
+                "justify_self": "stretch",
+                "align_self": "stretch",
+            }
+        )

+ 361 - 0
reflex/components/radix/themes/layout/spacer.pyi

@@ -0,0 +1,361 @@
+"""Stub file for reflex/components/radix/themes/layout/spacer.py"""
+# ------------------- DO NOT EDIT ----------------------
+# This file was generated by `scripts/pyi_generator.py`!
+# ------------------------------------------------------
+
+from typing import Any, Dict, Literal, Optional, Union, overload
+from reflex.vars import Var, BaseVar, ComputedVar
+from reflex.event import EventChain, EventHandler, EventSpec
+from reflex.style import Style
+from reflex.components.component import Component
+from .flex import Flex
+
+class Spacer(Flex):
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        color: Optional[Union[Var[str], str]] = None,
+        color_scheme: Optional[
+            Union[
+                Var[
+                    Literal[
+                        "tomato",
+                        "red",
+                        "ruby",
+                        "crimson",
+                        "pink",
+                        "plum",
+                        "purple",
+                        "violet",
+                        "iris",
+                        "indigo",
+                        "blue",
+                        "cyan",
+                        "teal",
+                        "jade",
+                        "green",
+                        "grass",
+                        "brown",
+                        "orange",
+                        "sky",
+                        "mint",
+                        "lime",
+                        "yellow",
+                        "amber",
+                        "gold",
+                        "bronze",
+                        "gray",
+                    ]
+                ],
+                Literal[
+                    "tomato",
+                    "red",
+                    "ruby",
+                    "crimson",
+                    "pink",
+                    "plum",
+                    "purple",
+                    "violet",
+                    "iris",
+                    "indigo",
+                    "blue",
+                    "cyan",
+                    "teal",
+                    "jade",
+                    "green",
+                    "grass",
+                    "brown",
+                    "orange",
+                    "sky",
+                    "mint",
+                    "lime",
+                    "yellow",
+                    "amber",
+                    "gold",
+                    "bronze",
+                    "gray",
+                ],
+            ]
+        ] = None,
+        as_child: Optional[Union[Var[bool], bool]] = None,
+        display: Optional[
+            Union[
+                Var[Literal["none", "inline-flex", "flex"]],
+                Literal["none", "inline-flex", "flex"],
+            ]
+        ] = None,
+        direction: Optional[
+            Union[
+                Var[Literal["row", "column", "row-reverse", "column-reverse"]],
+                Literal["row", "column", "row-reverse", "column-reverse"],
+            ]
+        ] = None,
+        align: Optional[
+            Union[
+                Var[Literal["start", "center", "end", "baseline", "stretch"]],
+                Literal["start", "center", "end", "baseline", "stretch"],
+            ]
+        ] = None,
+        justify: Optional[
+            Union[
+                Var[Literal["start", "center", "end", "between"]],
+                Literal["start", "center", "end", "between"],
+            ]
+        ] = None,
+        wrap: Optional[
+            Union[
+                Var[Literal["nowrap", "wrap", "wrap-reverse"]],
+                Literal["nowrap", "wrap", "wrap-reverse"],
+            ]
+        ] = None,
+        gap: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        access_key: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        auto_capitalize: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        content_editable: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        context_menu: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        dir: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        draggable: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        enter_key_hint: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        hidden: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        input_mode: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        item_prop: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        lang: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        role: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        slot: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        spell_check: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        tab_index: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        title: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        translate: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        p: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        px: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        py: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pt: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pr: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pb: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pl: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        shrink: Optional[Union[Var[Literal["0", "1"]], Literal["0", "1"]]] = None,
+        grow: Optional[Union[Var[Literal["0", "1"]], Literal["0", "1"]]] = None,
+        m: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mx: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        my: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mt: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mr: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mb: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        ml: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "Spacer":
+        """Create a new component instance.
+
+        Will prepend "RadixThemes" to the component tag to avoid conflicts with
+        other UI libraries for common names, like Text and Button.
+
+        Args:
+            *children: Child components.
+            color: map to CSS default color property.
+            color_scheme: map to radix color property.
+            as_child: Change the default rendered element for the one passed as a child, merging their props and behavior.
+            display: How to display the element: "none" | "inline-flex" | "flex"
+            direction: How child items are layed out: "row" | "column" | "row-reverse" | "column-reverse"
+            align: Alignment of children along the main axis: "start" | "center" | "end" | "baseline" | "stretch"
+            justify: Alignment of children along the cross axis: "start" | "center" | "end" | "between"
+            wrap: Whether children should wrap when they reach the end of their container: "nowrap" | "wrap" | "wrap-reverse"
+            gap: Gap between children: "0" - "9"
+            access_key:  Provides a hint for generating a keyboard shortcut for the current element.
+            auto_capitalize: Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
+            content_editable: Indicates whether the element's content is editable.
+            context_menu: Defines the ID of a <menu> element which will serve as the element's context menu.
+            dir: Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)
+            draggable: Defines whether the element can be dragged.
+            enter_key_hint: Hints what media types the media element is able to play.
+            hidden: Defines whether the element is hidden.
+            input_mode: Defines the type of the element.
+            item_prop: Defines the name of the element for metadata purposes.
+            lang: Defines the language used in the element.
+            role: Defines the role of the element.
+            slot: Assigns a slot in a shadow DOM shadow tree to an element.
+            spell_check: Defines whether the element may be checked for spelling errors.
+            tab_index: Defines the position of the current element in the tabbing order.
+            title: Defines a tooltip for the element.
+            translate: Specifies whether the content of an element should be translated or not.
+            p: Padding: "0" - "9"
+            px: Padding horizontal: "0" - "9"
+            py: Padding vertical: "0" - "9"
+            pt: Padding top: "0" - "9"
+            pr: Padding right: "0" - "9"
+            pb: Padding bottom: "0" - "9"
+            pl: Padding left: "0" - "9"
+            shrink: Whether the element will take up the smallest possible space: "0" | "1"
+            grow: Whether the element will take up the largest possible space: "0" | "1"
+            m: Margin: "0" - "9"
+            mx: Margin horizontal: "0" - "9"
+            my: Margin vertical: "0" - "9"
+            mt: Margin top: "0" - "9"
+            mr: Margin right: "0" - "9"
+            mb: Margin bottom: "0" - "9"
+            ml: Margin left: "0" - "9"
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: Component properties.
+
+        Returns:
+            A new component instance.
+        """
+        ...

+ 60 - 0
reflex/components/radix/themes/layout/stack.py

@@ -0,0 +1,60 @@
+"""Stack components."""
+from __future__ import annotations
+
+from typing import Literal, Optional
+
+from reflex.components.component import Component
+
+from .flex import Flex
+
+LiteralJustify = Literal["start", "center", "end"]
+LiteralAlign = Literal["start", "center", "end", "stretch"]
+
+
+class Stack(Flex):
+    """A stack component."""
+
+    @classmethod
+    def create(
+        cls,
+        *children,
+        justify: Optional[LiteralJustify] = "start",
+        align: Optional[LiteralAlign] = "center",
+        spacing: Optional[str] = "0.5rem",
+        **props,
+    ) -> Component:
+        """Create a new instance of the component.
+
+        Args:
+            *children: The children of the stack.
+            justify: The justify of the stack elements.
+            align: The alignment of the stack elements.
+            spacing: The spacing between each stack item.
+            **props: The properties of the stack.
+
+        Returns:
+            The stack component.
+        """
+        style = props.setdefault("style", {})
+        style.update(
+            {
+                "alignItems": align,
+                "justifyContent": justify,
+                "gap": spacing,
+            }
+        )
+        return super().create(*children, **props)
+
+
+class VStack(Stack):
+    """A vertical stack component."""
+
+    def _apply_theme(self, theme: Component):
+        self.style.update({"flex_direction": "column"})
+
+
+class HStack(Stack):
+    """A horizontal stack component."""
+
+    def _apply_theme(self, theme: Component):
+        self.style.update({"flex_direction": "row"})

+ 837 - 0
reflex/components/radix/themes/layout/stack.pyi

@@ -0,0 +1,837 @@
+"""Stub file for reflex/components/radix/themes/layout/stack.py"""
+# ------------------- DO NOT EDIT ----------------------
+# This file was generated by `scripts/pyi_generator.py`!
+# ------------------------------------------------------
+
+from typing import Any, Dict, Literal, Optional, Union, overload
+from reflex.vars import Var, BaseVar, ComputedVar
+from reflex.event import EventChain, EventHandler, EventSpec
+from reflex.style import Style
+from typing import Literal, Optional
+from reflex.components.component import Component
+from .flex import Flex
+
+LiteralJustify = Literal["start", "center", "end"]
+LiteralAlign = Literal["start", "center", "end", "stretch"]
+
+class Stack(Flex):
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        justify: Optional[LiteralJustify] = "start",
+        align: Optional[LiteralAlign] = "center",
+        spacing: Optional[str] = "0.5rem",
+        as_child: Optional[Union[Var[bool], bool]] = None,
+        display: Optional[
+            Union[
+                Var[Literal["none", "inline-flex", "flex"]],
+                Literal["none", "inline-flex", "flex"],
+            ]
+        ] = None,
+        direction: Optional[
+            Union[
+                Var[Literal["row", "column", "row-reverse", "column-reverse"]],
+                Literal["row", "column", "row-reverse", "column-reverse"],
+            ]
+        ] = None,
+        wrap: Optional[
+            Union[
+                Var[Literal["nowrap", "wrap", "wrap-reverse"]],
+                Literal["nowrap", "wrap", "wrap-reverse"],
+            ]
+        ] = None,
+        gap: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        access_key: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        auto_capitalize: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        content_editable: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        context_menu: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        dir: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        draggable: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        enter_key_hint: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        hidden: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        input_mode: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        item_prop: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        lang: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        role: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        slot: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        spell_check: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        tab_index: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        title: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        translate: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        p: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        px: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        py: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pt: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pr: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pb: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pl: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        shrink: Optional[Union[Var[Literal["0", "1"]], Literal["0", "1"]]] = None,
+        grow: Optional[Union[Var[Literal["0", "1"]], Literal["0", "1"]]] = None,
+        m: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mx: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        my: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mt: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mr: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mb: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        ml: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "Stack":
+        """Create a new instance of the component.
+
+        Args:
+            *children: The children of the stack.
+            justify: The justify of the stack elements.
+            align: The alignment of the stack elements.
+            spacing: The spacing between each stack item.
+            as_child: Change the default rendered element for the one passed as a child, merging their props and behavior.
+            display: How to display the element: "none" | "inline-flex" | "flex"
+            direction: How child items are layed out: "row" | "column" | "row-reverse" | "column-reverse"
+            wrap: Whether children should wrap when they reach the end of their container: "nowrap" | "wrap" | "wrap-reverse"
+            gap: Gap between children: "0" - "9"
+            access_key:  Provides a hint for generating a keyboard shortcut for the current element.
+            auto_capitalize: Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
+            content_editable: Indicates whether the element's content is editable.
+            context_menu: Defines the ID of a <menu> element which will serve as the element's context menu.
+            dir: Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)
+            draggable: Defines whether the element can be dragged.
+            enter_key_hint: Hints what media types the media element is able to play.
+            hidden: Defines whether the element is hidden.
+            input_mode: Defines the type of the element.
+            item_prop: Defines the name of the element for metadata purposes.
+            lang: Defines the language used in the element.
+            role: Defines the role of the element.
+            slot: Assigns a slot in a shadow DOM shadow tree to an element.
+            spell_check: Defines whether the element may be checked for spelling errors.
+            tab_index: Defines the position of the current element in the tabbing order.
+            title: Defines a tooltip for the element.
+            translate: Specifies whether the content of an element should be translated or not.
+            p: Padding: "0" - "9"
+            px: Padding horizontal: "0" - "9"
+            py: Padding vertical: "0" - "9"
+            pt: Padding top: "0" - "9"
+            pr: Padding right: "0" - "9"
+            pb: Padding bottom: "0" - "9"
+            pl: Padding left: "0" - "9"
+            shrink: Whether the element will take up the smallest possible space: "0" | "1"
+            grow: Whether the element will take up the largest possible space: "0" | "1"
+            m: Margin: "0" - "9"
+            mx: Margin horizontal: "0" - "9"
+            my: Margin vertical: "0" - "9"
+            mt: Margin top: "0" - "9"
+            mr: Margin right: "0" - "9"
+            mb: Margin bottom: "0" - "9"
+            ml: Margin left: "0" - "9"
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: The properties of the stack.
+
+        Returns:
+            The stack component.
+        """
+        ...
+
+class VStack(Stack):
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        justify: Optional[LiteralJustify] = "start",
+        align: Optional[LiteralAlign] = "center",
+        spacing: Optional[str] = "0.5rem",
+        as_child: Optional[Union[Var[bool], bool]] = None,
+        display: Optional[
+            Union[
+                Var[Literal["none", "inline-flex", "flex"]],
+                Literal["none", "inline-flex", "flex"],
+            ]
+        ] = None,
+        direction: Optional[
+            Union[
+                Var[Literal["row", "column", "row-reverse", "column-reverse"]],
+                Literal["row", "column", "row-reverse", "column-reverse"],
+            ]
+        ] = None,
+        wrap: Optional[
+            Union[
+                Var[Literal["nowrap", "wrap", "wrap-reverse"]],
+                Literal["nowrap", "wrap", "wrap-reverse"],
+            ]
+        ] = None,
+        gap: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        access_key: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        auto_capitalize: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        content_editable: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        context_menu: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        dir: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        draggable: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        enter_key_hint: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        hidden: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        input_mode: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        item_prop: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        lang: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        role: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        slot: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        spell_check: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        tab_index: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        title: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        translate: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        p: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        px: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        py: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pt: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pr: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pb: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pl: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        shrink: Optional[Union[Var[Literal["0", "1"]], Literal["0", "1"]]] = None,
+        grow: Optional[Union[Var[Literal["0", "1"]], Literal["0", "1"]]] = None,
+        m: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mx: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        my: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mt: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mr: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mb: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        ml: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "VStack":
+        """Create a new instance of the component.
+
+        Args:
+            *children: The children of the stack.
+            justify: The justify of the stack elements.
+            align: The alignment of the stack elements.
+            spacing: The spacing between each stack item.
+            as_child: Change the default rendered element for the one passed as a child, merging their props and behavior.
+            display: How to display the element: "none" | "inline-flex" | "flex"
+            direction: How child items are layed out: "row" | "column" | "row-reverse" | "column-reverse"
+            wrap: Whether children should wrap when they reach the end of their container: "nowrap" | "wrap" | "wrap-reverse"
+            gap: Gap between children: "0" - "9"
+            access_key:  Provides a hint for generating a keyboard shortcut for the current element.
+            auto_capitalize: Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
+            content_editable: Indicates whether the element's content is editable.
+            context_menu: Defines the ID of a <menu> element which will serve as the element's context menu.
+            dir: Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)
+            draggable: Defines whether the element can be dragged.
+            enter_key_hint: Hints what media types the media element is able to play.
+            hidden: Defines whether the element is hidden.
+            input_mode: Defines the type of the element.
+            item_prop: Defines the name of the element for metadata purposes.
+            lang: Defines the language used in the element.
+            role: Defines the role of the element.
+            slot: Assigns a slot in a shadow DOM shadow tree to an element.
+            spell_check: Defines whether the element may be checked for spelling errors.
+            tab_index: Defines the position of the current element in the tabbing order.
+            title: Defines a tooltip for the element.
+            translate: Specifies whether the content of an element should be translated or not.
+            p: Padding: "0" - "9"
+            px: Padding horizontal: "0" - "9"
+            py: Padding vertical: "0" - "9"
+            pt: Padding top: "0" - "9"
+            pr: Padding right: "0" - "9"
+            pb: Padding bottom: "0" - "9"
+            pl: Padding left: "0" - "9"
+            shrink: Whether the element will take up the smallest possible space: "0" | "1"
+            grow: Whether the element will take up the largest possible space: "0" | "1"
+            m: Margin: "0" - "9"
+            mx: Margin horizontal: "0" - "9"
+            my: Margin vertical: "0" - "9"
+            mt: Margin top: "0" - "9"
+            mr: Margin right: "0" - "9"
+            mb: Margin bottom: "0" - "9"
+            ml: Margin left: "0" - "9"
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: The properties of the stack.
+
+        Returns:
+            The stack component.
+        """
+        ...
+
+class HStack(Stack):
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        justify: Optional[LiteralJustify] = "start",
+        align: Optional[LiteralAlign] = "center",
+        spacing: Optional[str] = "0.5rem",
+        as_child: Optional[Union[Var[bool], bool]] = None,
+        display: Optional[
+            Union[
+                Var[Literal["none", "inline-flex", "flex"]],
+                Literal["none", "inline-flex", "flex"],
+            ]
+        ] = None,
+        direction: Optional[
+            Union[
+                Var[Literal["row", "column", "row-reverse", "column-reverse"]],
+                Literal["row", "column", "row-reverse", "column-reverse"],
+            ]
+        ] = None,
+        wrap: Optional[
+            Union[
+                Var[Literal["nowrap", "wrap", "wrap-reverse"]],
+                Literal["nowrap", "wrap", "wrap-reverse"],
+            ]
+        ] = None,
+        gap: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        access_key: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        auto_capitalize: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        content_editable: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        context_menu: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        dir: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        draggable: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        enter_key_hint: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        hidden: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        input_mode: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        item_prop: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        lang: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        role: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        slot: Optional[Union[Var[Union[str, int, bool]], Union[str, int, bool]]] = None,
+        spell_check: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        tab_index: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        title: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        translate: Optional[
+            Union[Var[Union[str, int, bool]], Union[str, int, bool]]
+        ] = None,
+        p: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        px: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        py: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pt: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pr: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pb: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        pl: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        shrink: Optional[Union[Var[Literal["0", "1"]], Literal["0", "1"]]] = None,
+        grow: Optional[Union[Var[Literal["0", "1"]], Literal["0", "1"]]] = None,
+        m: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mx: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        my: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mt: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mr: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        mb: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        ml: Optional[
+            Union[
+                Var[Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"]],
+                Literal["1", "2", "3", "4", "5", "6", "7", "8", "9"],
+            ]
+        ] = None,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "HStack":
+        """Create a new instance of the component.
+
+        Args:
+            *children: The children of the stack.
+            justify: The justify of the stack elements.
+            align: The alignment of the stack elements.
+            spacing: The spacing between each stack item.
+            as_child: Change the default rendered element for the one passed as a child, merging their props and behavior.
+            display: How to display the element: "none" | "inline-flex" | "flex"
+            direction: How child items are layed out: "row" | "column" | "row-reverse" | "column-reverse"
+            wrap: Whether children should wrap when they reach the end of their container: "nowrap" | "wrap" | "wrap-reverse"
+            gap: Gap between children: "0" - "9"
+            access_key:  Provides a hint for generating a keyboard shortcut for the current element.
+            auto_capitalize: Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
+            content_editable: Indicates whether the element's content is editable.
+            context_menu: Defines the ID of a <menu> element which will serve as the element's context menu.
+            dir: Defines the text direction. Allowed values are ltr (Left-To-Right) or rtl (Right-To-Left)
+            draggable: Defines whether the element can be dragged.
+            enter_key_hint: Hints what media types the media element is able to play.
+            hidden: Defines whether the element is hidden.
+            input_mode: Defines the type of the element.
+            item_prop: Defines the name of the element for metadata purposes.
+            lang: Defines the language used in the element.
+            role: Defines the role of the element.
+            slot: Assigns a slot in a shadow DOM shadow tree to an element.
+            spell_check: Defines whether the element may be checked for spelling errors.
+            tab_index: Defines the position of the current element in the tabbing order.
+            title: Defines a tooltip for the element.
+            translate: Specifies whether the content of an element should be translated or not.
+            p: Padding: "0" - "9"
+            px: Padding horizontal: "0" - "9"
+            py: Padding vertical: "0" - "9"
+            pt: Padding top: "0" - "9"
+            pr: Padding right: "0" - "9"
+            pb: Padding bottom: "0" - "9"
+            pl: Padding left: "0" - "9"
+            shrink: Whether the element will take up the smallest possible space: "0" | "1"
+            grow: Whether the element will take up the largest possible space: "0" | "1"
+            m: Margin: "0" - "9"
+            mx: Margin horizontal: "0" - "9"
+            my: Margin vertical: "0" - "9"
+            mt: Margin top: "0" - "9"
+            mr: Margin right: "0" - "9"
+            mb: Margin bottom: "0" - "9"
+            ml: Margin left: "0" - "9"
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: The properties of the stack.
+
+        Returns:
+            The stack component.
+        """
+        ...

+ 6 - 0
reflex/constants/event.py

@@ -80,6 +80,12 @@ class EventTriggers(SimpleNamespace):
     ON_MOUSE_OUT = "on_mouse_out"
     ON_MOUSE_OUT = "on_mouse_out"
     ON_MOUSE_OVER = "on_mouse_over"
     ON_MOUSE_OVER = "on_mouse_over"
     ON_MOUSE_UP = "on_mouse_up"
     ON_MOUSE_UP = "on_mouse_up"
+    ON_OPEN_CHANGE = "on_open_change"
+    ON_OPEN_AUTO_FOCUS = "on_open_auto_focus"
+    ON_CLOSE_AUTO_FOCUS = "on_close_auto_focus"
+    ON_ESCAPE_KEY_DOWN = "on_escape_key_down"
+    ON_POINTER_DOWN_OUTSIDE = "on_pointer_down_outside"
+    ON_INTERACT_OUTSIDE = "on_interact_outside"
     ON_SCROLL = "on_scroll"
     ON_SCROLL = "on_scroll"
     ON_SUBMIT = "on_submit"
     ON_SUBMIT = "on_submit"
     ON_MOUNT = "on_mount"
     ON_MOUNT = "on_mount"

+ 18 - 9
reflex/testing.py

@@ -102,7 +102,7 @@ class AppHarness:
     """AppHarness executes a reflex app in-process for testing."""
     """AppHarness executes a reflex app in-process for testing."""
 
 
     app_name: str
     app_name: str
-    app_source: Optional[types.FunctionType | types.ModuleType]
+    app_source: Optional[types.FunctionType | types.ModuleType] | str
     app_path: pathlib.Path
     app_path: pathlib.Path
     app_module_path: pathlib.Path
     app_module_path: pathlib.Path
     app_module: Optional[types.ModuleType] = None
     app_module: Optional[types.ModuleType] = None
@@ -119,7 +119,7 @@ class AppHarness:
     def create(
     def create(
         cls,
         cls,
         root: pathlib.Path,
         root: pathlib.Path,
-        app_source: Optional[types.FunctionType | types.ModuleType] = None,
+        app_source: Optional[types.FunctionType | types.ModuleType | str] = None,
         app_name: Optional[str] = None,
         app_name: Optional[str] = None,
     ) -> "AppHarness":
     ) -> "AppHarness":
         """Create an AppHarness instance at root.
         """Create an AppHarness instance at root.
@@ -127,10 +127,13 @@ class AppHarness:
         Args:
         Args:
             root: the directory that will contain the app under test.
             root: the directory that will contain the app under test.
             app_source: if specified, the source code from this function or module is used
             app_source: if specified, the source code from this function or module is used
-                as the main module for the app. If unspecified, then root must already
-                contain a working reflex app and will be used directly.
+                as the main module for the app. It may also be the raw source code text, as a str.
+                If unspecified, then root must already contain a working reflex app and will be used directly.
             app_name: provide the name of the app, otherwise will be derived from app_source or root.
             app_name: provide the name of the app, otherwise will be derived from app_source or root.
 
 
+        Raises:
+            ValueError: when app_source is a string and app_name is not provided.
+
         Returns:
         Returns:
             AppHarness instance
             AppHarness instance
         """
         """
@@ -139,6 +142,10 @@ class AppHarness:
                 app_name = root.name.lower()
                 app_name = root.name.lower()
             elif isinstance(app_source, functools.partial):
             elif isinstance(app_source, functools.partial):
                 app_name = app_source.func.__name__.lower()
                 app_name = app_source.func.__name__.lower()
+            elif isinstance(app_source, str):
+                raise ValueError(
+                    "app_name must be provided when app_source is a string."
+                )
             else:
             else:
                 app_name = app_source.__name__.lower()
                 app_name = app_source.__name__.lower()
         return cls(
         return cls(
@@ -170,16 +177,18 @@ class AppHarness:
         glbs.update(overrides)
         glbs.update(overrides)
         return glbs
         return glbs
 
 
-    def _get_source_from_func(self, func: Any) -> str:
-        """Get the source from a function or module object.
+    def _get_source_from_app_source(self, app_source: Any) -> str:
+        """Get the source from app_source.
 
 
         Args:
         Args:
-            func: function or module object
+            app_source: function or module or str
 
 
         Returns:
         Returns:
             source code
             source code
         """
         """
-        source = inspect.getsource(func)
+        if isinstance(app_source, str):
+            return app_source
+        source = inspect.getsource(app_source)
         source = re.sub(r"^\s*def\s+\w+\s*\(.*?\):", "", source, flags=re.DOTALL)
         source = re.sub(r"^\s*def\s+\w+\s*\(.*?\):", "", source, flags=re.DOTALL)
         return textwrap.dedent(source)
         return textwrap.dedent(source)
 
 
@@ -194,7 +203,7 @@ class AppHarness:
             source_code = "\n".join(
             source_code = "\n".join(
                 [
                 [
                     "\n".join(f"{k} = {v!r}" for k, v in app_globals.items()),
                     "\n".join(f"{k} = {v!r}" for k, v in app_globals.items()),
-                    self._get_source_from_func(self.app_source),
+                    self._get_source_from_app_source(self.app_source),
                 ]
                 ]
             )
             )
             with chdir(self.app_path):
             with chdir(self.app_path):

+ 35 - 7
reflex/utils/types.py

@@ -18,9 +18,10 @@ from typing import (
     get_type_hints,
     get_type_hints,
 )
 )
 
 
+import sqlalchemy
 from pydantic.fields import ModelField
 from pydantic.fields import ModelField
 from sqlalchemy.ext.hybrid import hybrid_property
 from sqlalchemy.ext.hybrid import hybrid_property
-from sqlalchemy.orm import DeclarativeBase, Mapped
+from sqlalchemy.orm import DeclarativeBase, Mapped, QueryableAttribute, Relationship
 
 
 from reflex.base import Base
 from reflex.base import Base
 from reflex.utils import serializers
 from reflex.utils import serializers
@@ -105,6 +106,21 @@ def is_optional(cls: GenericType) -> bool:
     return is_union(cls) and type(None) in get_args(cls)
     return is_union(cls) and type(None) in get_args(cls)
 
 
 
 
+def get_property_hint(attr: Any | None) -> GenericType | None:
+    """Check if an attribute is a property and return its type hint.
+
+    Args:
+        attr: The descriptor to check.
+
+    Returns:
+        The type hint of the property, if it is a property, else None.
+    """
+    if not isinstance(attr, (property, hybrid_property)):
+        return None
+    hints = get_type_hints(attr.fget)
+    return hints.get("return", None)
+
+
 def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None:
 def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None:
     """Check if an attribute can be accessed on the cls and return its type.
     """Check if an attribute can be accessed on the cls and return its type.
 
 
@@ -119,6 +135,9 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None
     """
     """
     from reflex.model import Model
     from reflex.model import Model
 
 
+    attr = getattr(cls, name, None)
+    if hint := get_property_hint(attr):
+        return hint
     if hasattr(cls, "__fields__") and name in cls.__fields__:
     if hasattr(cls, "__fields__") and name in cls.__fields__:
         # pydantic models
         # pydantic models
         field = cls.__fields__[name]
         field = cls.__fields__[name]
@@ -129,7 +148,21 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None
             # Ensure frontend uses null coalescing when accessing.
             # Ensure frontend uses null coalescing when accessing.
             type_ = Optional[type_]
             type_ = Optional[type_]
         return type_
         return type_
-    elif isinstance(cls, type) and issubclass(cls, (Model, DeclarativeBase)):
+    elif isinstance(cls, type) and issubclass(cls, DeclarativeBase):
+        insp = sqlalchemy.inspect(cls)
+        if name in insp.columns:
+            return insp.columns[name].type.python_type
+        if name not in insp.all_orm_descriptors.keys():
+            return None
+        descriptor = insp.all_orm_descriptors[name]
+        if hint := get_property_hint(descriptor):
+            return hint
+        if isinstance(descriptor, QueryableAttribute):
+            prop = descriptor.property
+            if not isinstance(prop, Relationship):
+                return None
+            return prop.mapper.class_
+    elif isinstance(cls, type) and issubclass(cls, Model):
         # Check in the annotations directly (for sqlmodel.Relationship)
         # Check in the annotations directly (for sqlmodel.Relationship)
         hints = get_type_hints(cls)
         hints = get_type_hints(cls)
         if name in hints:
         if name in hints:
@@ -140,11 +173,6 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None
             if isinstance(type_, ModelField):
             if isinstance(type_, ModelField):
                 return type_.type_  # SQLAlchemy v1.4
                 return type_.type_  # SQLAlchemy v1.4
             return type_
             return type_
-        if name in cls.__dict__:
-            value = cls.__dict__[name]
-            if isinstance(value, hybrid_property):
-                hints = get_type_hints(value.fget)
-                return hints.get("return", None)
     elif is_union(cls):
     elif is_union(cls):
         # Check in each arg of the annotation.
         # Check in each arg of the annotation.
         for arg in get_args(cls):
         for arg in get_args(cls):

+ 1 - 0
scripts/pyi_generator.py

@@ -55,6 +55,7 @@ EXCLUDED_PROPS = [
     "_invalid_children",
     "_invalid_children",
     "_memoization_mode",
     "_memoization_mode",
     "_valid_children",
     "_valid_children",
+    "_valid_parents",
 ]
 ]
 
 
 DEFAULT_TYPING_IMPORTS = {
 DEFAULT_TYPING_IMPORTS = {

+ 16 - 0
tests/components/test_component.py

@@ -137,6 +137,8 @@ def component5() -> Type[Component]:
 
 
         _valid_children: List[str] = ["Text"]
         _valid_children: List[str] = ["Text"]
 
 
+        _valid_parents: List[str] = ["Text"]
+
     return TestComponent5
     return TestComponent5
 
 
 
 
@@ -569,6 +571,20 @@ def test_unsupported_child_components(fixture, request):
     )
     )
 
 
 
 
+def test_unsupported_parent_components(component5):
+    """Test that a value error is raised when an component is not in _valid_parents of one of its children.
+
+    Args:
+        component5: component with valid parent of "Text" only
+    """
+    with pytest.raises(ValueError) as err:
+        rx.Box(children=[component5.create()])
+    assert (
+        err.value.args[0]
+        == f"The component `{component5.__name__}` can only be a child of the components: `{component5._valid_parents[0]}`. Got `Box` instead."
+    )
+
+
 @pytest.mark.parametrize("fixture", ["component5", "component7"])
 @pytest.mark.parametrize("fixture", ["component5", "component7"])
 def test_component_with_only_valid_children(fixture, request):
 def test_component_with_only_valid_children(fixture, request):
     """Test that a value error is raised when an unsupported component (a child component not found in the
     """Test that a value error is raised when an unsupported component (a child component not found in the