Prechádzať zdrojové kódy

Merge branch 'main' into reflex-0.4.0

Nikhil Rao 1 rok pred
rodič
commit
27b9a10233

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

@@ -27,3 +27,5 @@ jobs:
       - run: |
           poetry run pip install pre-commit
           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
     rev: 22.10.0
     hooks:
-    - id: black
-      args: [integration, reflex, tests]
+      - id: black
+        args: [integration, reflex, tests]
 
   - repo: https://github.com/charliermarsh/ruff-pre-commit
     rev: v0.0.244
     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
     rev: v1.1.313
     hooks:
-    - id: pyright
-      args: [integration, reflex, tests]
-      language: system
+      - id: pyright
+        args: [integration, reflex, tests]
+        language: system
 
   - repo: https://github.com/terrencepreilly/darglint
     rev: v1.8.1
     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.
     panel_id: Var[str]
 
+    _valid_parents: List[str] = ["TabList"]
+
 
 class TabList(ChakraComponent):
     """Wrapper for the Tab components."""
 
     tag = "TabList"
 
+    _valid_parents: List[str] = ["Tabs"]
+
 
 class TabPanels(ChakraComponent):
     """Wrapper for the Tab components."""
 
     tag = "TabPanels"
 
+    _valid_parents: List[str] = ["Tabs"]
+
 
 class TabPanel(ChakraComponent):
     """An element that contains the content associated with a tab."""
 
     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
     _valid_children: List[str] = []
 
+    # only components that are allowed as parent
+    _valid_parents: List[str] = []
+
     # custom attribute
     custom_attrs: Dict[str, Union[Var, str]] = {}
 
@@ -651,7 +654,8 @@ class Component(BaseComponent, ABC):
             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
 
         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."
                 )
 
+        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:
             name = type(child).__name__
 
@@ -680,6 +693,9 @@ class Component(BaseComponent, ABC):
             if self._valid_children:
                 validate_valid_child(name)
 
+            if child._valid_parents:
+                validate_vaild_parent(name, child._valid_parents)
+
     @staticmethod
     def _get_vars_from_event_triggers(
         event_triggers: dict[str, EventChain | Var],

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

@@ -1,5 +1,6 @@
 """Core Reflex components."""
 
+from . import layout as layout
 from .banner import ConnectionBanner, ConnectionModal
 from .cond import Cond, cond
 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])}, ..."
                 "\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']}"
         return super().create(*children, **props)
 
-    def _apply_theme(self, theme: Component | None):
+    def _apply_theme(self, theme: Component):
         self.style = Style(
             {
-                "color": f"var(--accent-12)",
+                "color": f"var(--current-color)",
                 **self.style,
             }
         )

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

@@ -2,5 +2,15 @@
 
 from .accordion import accordion
 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 .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.core import cond, match
+from reflex.components.lucide.icon import Icon
 from reflex.components.radix.primitives.base import RadixPrimitiveComponent
-from reflex.components.radix.themes.components.icons import Icon
 from reflex.style import (
     Style,
     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 reflex.components.component import Component
 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.themes.components.icons import Icon
 from reflex.style import (
     Style,
     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)
         return form_refs
 
-    def _apply_theme(self, theme: Component | None):
+    def _apply_theme(self, theme: Component):
         return {
             "width": "260px",
             **self.style,
@@ -179,7 +179,7 @@ class FormField(FormComponent):
     # Flag to mark the form field as invalid, for server side validation.
     server_invalid: Var[bool]
 
-    def _apply_theme(self, theme: Component | None):
+    def _apply_theme(self, theme: Component):
         return {
             "display": "grid",
             "margin_bottom": "10px",
@@ -194,7 +194,7 @@ class FormLabel(FormComponent):
 
     alias = "RadixFormLabel"
 
-    def _apply_theme(self, theme: Component | None):
+    def _apply_theme(self, theme: Component):
         return {
             "font_size": "15px",
             "font_weight": "500",
@@ -267,7 +267,7 @@ class FormMessage(FormComponent):
     # Forces the message to be shown. This is useful when using server-side validation.
     force_match: Var[bool]
 
-    def _apply_theme(self, theme: Component | None):
+    def _apply_theme(self, theme: Component):
         return {
             "font_size": "13px",
             "opacity": "0.8",

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

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

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

@@ -114,6 +114,21 @@ class RadixThemesComponent(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
     def _get_app_wrap_components() -> dict[tuple[int, str], Component]:
         return {

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

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

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

@@ -1,13 +1,20 @@
 """Layout components."""
 
 from .box import Box
+from .center import Center
 from .container import Container
 from .flex import Flex
 from .grid import Grid
 from .section import Section
+from .spacer import Spacer
+from .stack import HStack, VStack
 
 box = Box.create
+center = Center.create
 container = Container.create
 flex = Flex.create
 grid = Grid.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_OVER = "on_mouse_over"
     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_SUBMIT = "on_submit"
     ON_MOUNT = "on_mount"

+ 18 - 9
reflex/testing.py

@@ -102,7 +102,7 @@ class AppHarness:
     """AppHarness executes a reflex app in-process for testing."""
 
     app_name: str
-    app_source: Optional[types.FunctionType | types.ModuleType]
+    app_source: Optional[types.FunctionType | types.ModuleType] | str
     app_path: pathlib.Path
     app_module_path: pathlib.Path
     app_module: Optional[types.ModuleType] = None
@@ -119,7 +119,7 @@ class AppHarness:
     def create(
         cls,
         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,
     ) -> "AppHarness":
         """Create an AppHarness instance at root.
@@ -127,10 +127,13 @@ class AppHarness:
         Args:
             root: the directory that will contain the app under test.
             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.
 
+        Raises:
+            ValueError: when app_source is a string and app_name is not provided.
+
         Returns:
             AppHarness instance
         """
@@ -139,6 +142,10 @@ class AppHarness:
                 app_name = root.name.lower()
             elif isinstance(app_source, functools.partial):
                 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:
                 app_name = app_source.__name__.lower()
         return cls(
@@ -170,16 +177,18 @@ class AppHarness:
         glbs.update(overrides)
         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:
-            func: function or module object
+            app_source: function or module or str
 
         Returns:
             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)
         return textwrap.dedent(source)
 
@@ -194,7 +203,7 @@ class AppHarness:
             source_code = "\n".join(
                 [
                     "\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):

+ 35 - 7
reflex/utils/types.py

@@ -18,9 +18,10 @@ from typing import (
     get_type_hints,
 )
 
+import sqlalchemy
 from pydantic.fields import ModelField
 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.utils import serializers
@@ -105,6 +106,21 @@ def is_optional(cls: GenericType) -> bool:
     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:
     """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
 
+    attr = getattr(cls, name, None)
+    if hint := get_property_hint(attr):
+        return hint
     if hasattr(cls, "__fields__") and name in cls.__fields__:
         # pydantic models
         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.
             type_ = Optional[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)
         hints = get_type_hints(cls)
         if name in hints:
@@ -140,11 +173,6 @@ def get_attribute_access_type(cls: GenericType, name: str) -> GenericType | None
             if isinstance(type_, ModelField):
                 return type_.type_  # SQLAlchemy v1.4
             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):
         # Check in each arg of the annotation.
         for arg in get_args(cls):

+ 1 - 0
scripts/pyi_generator.py

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

+ 16 - 0
tests/components/test_component.py

@@ -137,6 +137,8 @@ def component5() -> Type[Component]:
 
         _valid_children: List[str] = ["Text"]
 
+        _valid_parents: List[str] = ["Text"]
+
     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"])
 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