فهرست منبع

Handle component namespaces in global styles (#2630)

Nikhil Rao 1 سال پیش
والد
کامیت
7240f8ee6f
43فایلهای تغییر یافته به همراه135 افزوده شده و 106 حذف شده
  1. 14 5
      reflex/app.py
  2. 32 1
      reflex/components/component.py
  3. 2 3
      reflex/components/radix/primitives/accordion.py
  4. 2 3
      reflex/components/radix/primitives/accordion.pyi
  5. 2 2
      reflex/components/radix/primitives/drawer.py
  6. 2 2
      reflex/components/radix/primitives/drawer.pyi
  7. 2 3
      reflex/components/radix/primitives/form.py
  8. 2 3
      reflex/components/radix/primitives/form.pyi
  9. 2 3
      reflex/components/radix/primitives/progress.py
  10. 2 3
      reflex/components/radix/primitives/progress.pyi
  11. 2 3
      reflex/components/radix/primitives/slider.py
  12. 2 3
      reflex/components/radix/primitives/slider.pyi
  13. 2 2
      reflex/components/radix/themes/components/alert_dialog.py
  14. 2 2
      reflex/components/radix/themes/components/alert_dialog.pyi
  15. 2 3
      reflex/components/radix/themes/components/callout.py
  16. 2 3
      reflex/components/radix/themes/components/callout.pyi
  17. 2 3
      reflex/components/radix/themes/components/checkbox.py
  18. 2 3
      reflex/components/radix/themes/components/checkbox.pyi
  19. 2 2
      reflex/components/radix/themes/components/context_menu.py
  20. 2 2
      reflex/components/radix/themes/components/context_menu.pyi
  21. 2 2
      reflex/components/radix/themes/components/dialog.py
  22. 2 2
      reflex/components/radix/themes/components/dialog.pyi
  23. 2 2
      reflex/components/radix/themes/components/dropdown_menu.py
  24. 2 2
      reflex/components/radix/themes/components/dropdown_menu.pyi
  25. 2 2
      reflex/components/radix/themes/components/hover_card.py
  26. 2 2
      reflex/components/radix/themes/components/hover_card.pyi
  27. 2 2
      reflex/components/radix/themes/components/popover.py
  28. 2 2
      reflex/components/radix/themes/components/popover.pyi
  29. 2 3
      reflex/components/radix/themes/components/radio_group.py
  30. 2 3
      reflex/components/radix/themes/components/radio_group.pyi
  31. 2 3
      reflex/components/radix/themes/components/select.py
  32. 2 3
      reflex/components/radix/themes/components/select.pyi
  33. 2 2
      reflex/components/radix/themes/components/table.py
  34. 2 2
      reflex/components/radix/themes/components/table.pyi
  35. 2 2
      reflex/components/radix/themes/components/tabs.py
  36. 2 2
      reflex/components/radix/themes/components/tabs.pyi
  37. 2 3
      reflex/components/radix/themes/components/text_field.py
  38. 2 3
      reflex/components/radix/themes/components/text_field.pyi
  39. 2 3
      reflex/components/radix/themes/layout/list.py
  40. 2 3
      reflex/components/radix/themes/layout/list.pyi
  41. 2 2
      reflex/components/radix/themes/typography/text.py
  42. 2 2
      reflex/components/radix/themes/typography/text.pyi
  43. 9 0
      tests/test_style.py

+ 14 - 5
reflex/app.py

@@ -39,7 +39,11 @@ from reflex.compiler import utils as compiler_utils
 from reflex.components import connection_modal
 from reflex.components.base.app_wrap import AppWrap
 from reflex.components.base.fragment import Fragment
-from reflex.components.component import Component, ComponentStyle
+from reflex.components.component import (
+    Component,
+    ComponentStyle,
+    evaluate_style_namespaces,
+)
 from reflex.components.core.client_side_routing import (
     Default404Page,
     wait_for_client_redirect,
@@ -682,10 +686,7 @@ class App(Base):
         # Store the compile results.
         compile_results = []
 
-        # Compile the pages in parallel.
-        custom_components = set()
-        # TODO Anecdotally, processes=2 works 10% faster (cpu_count=12)
-        all_imports = {}
+        # Add the app wrappers.
         app_wrappers: Dict[tuple[int, str], Component] = {
             # Default app wrap component renders {children}
             (0, "AppWrap"): AppWrap.create()
@@ -694,6 +695,14 @@ class App(Base):
             # If a theme component was provided, wrap the app with it
             app_wrappers[(20, "Theme")] = self.theme
 
+        # Fix up the style.
+        self.style = evaluate_style_namespaces(self.style)
+
+        # Track imports and custom components found.
+        all_imports = {}
+        custom_components = set()
+
+        # Compile the pages in parallel.
         with progress, concurrent.futures.ThreadPoolExecutor() as thread_pool:
             fixed_pages = 7
             task = progress.add_task("Compiling:", total=len(self.pages) + fixed_pages)

+ 32 - 1
reflex/components/component.py

@@ -7,6 +7,7 @@ import typing
 from abc import ABC, abstractmethod
 from functools import lru_cache, wraps
 from hashlib import md5
+from types import SimpleNamespace
 from typing import (
     Any,
     Callable,
@@ -114,8 +115,38 @@ class BaseComponent(Base, ABC):
         """
 
 
+class ComponentNamespace(SimpleNamespace):
+    """A namespace to manage components with subcomponents."""
+
+    def __hash__(self) -> int:
+        """Get the hash of the namespace.
+
+
+        Returns:
+            The hash of the namespace.
+        """
+        return hash(self.__class__.__name__)
+
+
+def evaluate_style_namespaces(style: ComponentStyle) -> dict:
+    """Evaluate namespaces in the style.
+
+    Args:
+        style: The style to evaluate.
+
+    Returns:
+        The evaluated style.
+    """
+    return {
+        k.__call__ if isinstance(k, ComponentNamespace) else k: v
+        for k, v in style.items()
+    }
+
+
 # Map from component to styling.
-ComponentStyle = Dict[Union[str, Type[BaseComponent], Callable], Any]
+ComponentStyle = Dict[
+    Union[str, Type[BaseComponent], Callable, ComponentNamespace], Any
+]
 ComponentChild = Union[types.PrimitiveType, Var, BaseComponent]
 
 

+ 2 - 3
reflex/components/radix/primitives/accordion.py

@@ -2,10 +2,9 @@
 
 from __future__ import annotations
 
-from types import SimpleNamespace
 from typing import Any, Dict, List, Literal, Optional, Union
 
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.core.match import Match
 from reflex.components.lucide.icon import Icon
 from reflex.components.radix.primitives.base import RadixPrimitiveComponent
@@ -649,7 +648,7 @@ class AccordionContent(AccordionComponent):
     #     }
 
 
-class Accordion(SimpleNamespace):
+class Accordion(ComponentNamespace):
     """Accordion component."""
 
     content = staticmethod(AccordionContent.create)

+ 2 - 3
reflex/components/radix/primitives/accordion.pyi

@@ -7,9 +7,8 @@ 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 types import SimpleNamespace
 from typing import Any, Dict, List, Literal, Optional, Union
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.core.match import Match
 from reflex.components.lucide.icon import Icon
 from reflex.components.radix.primitives.base import RadixPrimitiveComponent
@@ -699,7 +698,7 @@ class AccordionContent(AccordionComponent):
         """
         ...
 
-class Accordion(SimpleNamespace):
+class Accordion(ComponentNamespace):
     content = staticmethod(AccordionContent.create)
     header = staticmethod(AccordionHeader.create)
     item = staticmethod(AccordionItem.create)

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

@@ -3,9 +3,9 @@
 # Style based on https://ui.shadcn.com/docs/components/drawer
 from __future__ import annotations
 
-from types import SimpleNamespace
 from typing import Any, Dict, List, Literal, Optional, Union
 
+from reflex.components.component import ComponentNamespace
 from reflex.components.radix.primitives.base import RadixPrimitiveComponent
 from reflex.components.radix.themes.base import Theme
 from reflex.constants import EventTriggers
@@ -261,7 +261,7 @@ class DrawerDescription(DrawerComponent):
         return self.style
 
 
-class Drawer(SimpleNamespace):
+class Drawer(ComponentNamespace):
     """A namespace for Drawer components."""
 
     root = __call__ = staticmethod(DrawerRoot.create)

+ 2 - 2
reflex/components/radix/primitives/drawer.pyi

@@ -7,8 +7,8 @@ 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 types import SimpleNamespace
 from typing import Any, Dict, List, Literal, Optional, Union
+from reflex.components.component import ComponentNamespace
 from reflex.components.radix.primitives.base import RadixPrimitiveComponent
 from reflex.components.radix.themes.base import Theme
 from reflex.constants import EventTriggers
@@ -789,7 +789,7 @@ class DrawerDescription(DrawerComponent):
         """
         ...
 
-class Drawer(SimpleNamespace):
+class Drawer(ComponentNamespace):
     root = staticmethod(DrawerRoot.create)
     trigger = staticmethod(DrawerTrigger.create)
     portal = staticmethod(DrawerPortal.create)

+ 2 - 3
reflex/components/radix/primitives/form.py

@@ -3,12 +3,11 @@
 from __future__ import annotations
 
 from hashlib import md5
-from types import SimpleNamespace
 from typing import Any, Dict, Iterator, Literal
 
 from jinja2 import Environment
 
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.radix.themes.components.text_field import TextFieldInput
 from reflex.components.tags.tag import Tag
 from reflex.constants.base import Dirs
@@ -297,7 +296,7 @@ class Form(FormRoot):
     pass
 
 
-class FormNamespace(SimpleNamespace):
+class FormNamespace(ComponentNamespace):
     """Form components."""
 
     root = staticmethod(FormRoot.create)

+ 2 - 3
reflex/components/radix/primitives/form.pyi

@@ -8,10 +8,9 @@ from reflex.vars import Var, BaseVar, ComputedVar
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.style import Style
 from hashlib import md5
-from types import SimpleNamespace
 from typing import Any, Dict, Iterator, Literal
 from jinja2 import Environment
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.radix.themes.components.text_field import TextFieldInput
 from reflex.components.tags.tag import Tag
 from reflex.constants.base import Dirs
@@ -826,7 +825,7 @@ class Form(FormRoot):
         """
         ...
 
-class FormNamespace(SimpleNamespace):
+class FormNamespace(ComponentNamespace):
     root = staticmethod(FormRoot.create)
     control = staticmethod(FormControl.create)
     field = staticmethod(FormField.create)

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

@@ -2,10 +2,9 @@
 
 from __future__ import annotations
 
-from types import SimpleNamespace
 from typing import Optional
 
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.radix.primitives.accordion import DEFAULT_ANIMATION_DURATION
 from reflex.components.radix.primitives.base import RadixPrimitiveComponentWithClassName
 from reflex.style import Style
@@ -74,7 +73,7 @@ class ProgressIndicator(ProgressComponent):
         )
 
 
-class Progress(SimpleNamespace):
+class Progress(ComponentNamespace):
     """High level API for progress bar."""
 
     root = staticmethod(ProgressRoot.create)

+ 2 - 3
reflex/components/radix/primitives/progress.pyi

@@ -7,9 +7,8 @@ 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 types import SimpleNamespace
 from typing import Optional
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.radix.primitives.accordion import DEFAULT_ANIMATION_DURATION
 from reflex.components.radix.primitives.base import RadixPrimitiveComponentWithClassName
 from reflex.style import Style
@@ -266,7 +265,7 @@ class ProgressIndicator(ProgressComponent):
         """
         ...
 
-class Progress(SimpleNamespace):
+class Progress(ComponentNamespace):
     root = staticmethod(ProgressRoot.create)
     indicator = staticmethod(ProgressIndicator.create)
 

+ 2 - 3
reflex/components/radix/primitives/slider.py

@@ -2,10 +2,9 @@
 
 from __future__ import annotations
 
-from types import SimpleNamespace
 from typing import Any, Dict, List, Literal
 
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.radix.primitives.base import RadixPrimitiveComponentWithClassName
 from reflex.style import Style
 from reflex.vars import Var
@@ -149,7 +148,7 @@ class SliderThumb(SliderComponent):
         )
 
 
-class Slider(SimpleNamespace):
+class Slider(ComponentNamespace):
     """High level API for slider."""
 
     root = staticmethod(SliderRoot.create)

+ 2 - 3
reflex/components/radix/primitives/slider.pyi

@@ -7,9 +7,8 @@ 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 types import SimpleNamespace
 from typing import Any, Dict, List, Literal
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.radix.primitives.base import RadixPrimitiveComponentWithClassName
 from reflex.style import Style
 from reflex.vars import Var
@@ -445,7 +444,7 @@ class SliderThumb(SliderComponent):
         """
         ...
 
-class Slider(SimpleNamespace):
+class Slider(ComponentNamespace):
     root = staticmethod(SliderRoot.create)
     track = staticmethod(SliderTrack.create)
     range = staticmethod(SliderRange.create)

+ 2 - 2
reflex/components/radix/themes/components/alert_dialog.py

@@ -1,8 +1,8 @@
 """Interactive components provided by @radix-ui/themes."""
-from types import SimpleNamespace
 from typing import Any, Dict, Literal
 
 from reflex import el
+from reflex.components.component import ComponentNamespace
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 
@@ -95,7 +95,7 @@ class AlertDialogCancel(RadixThemesComponent):
     tag = "AlertDialog.Cancel"
 
 
-class AlertDialog(SimpleNamespace):
+class AlertDialog(ComponentNamespace):
     """AlertDialog components namespace."""
 
     root = staticmethod(AlertDialogRoot.create)

+ 2 - 2
reflex/components/radix/themes/components/alert_dialog.pyi

@@ -7,9 +7,9 @@ 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 types import SimpleNamespace
 from typing import Any, Dict, Literal
 from reflex import el
+from reflex.components.component import ComponentNamespace
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 from ..base import RadixThemesComponent
@@ -647,7 +647,7 @@ class AlertDialogCancel(RadixThemesComponent):
         """
         ...
 
-class AlertDialog(SimpleNamespace):
+class AlertDialog(ComponentNamespace):
     root = staticmethod(AlertDialogRoot.create)
     trigger = staticmethod(AlertDialogTrigger.create)
     content = staticmethod(AlertDialogContent.create)

+ 2 - 3
reflex/components/radix/themes/components/callout.py

@@ -1,11 +1,10 @@
 """Interactive components provided by @radix-ui/themes."""
 
-from types import SimpleNamespace
 from typing import Literal, Union
 
 import reflex as rx
 from reflex import el
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.lucide.icon import Icon
 from reflex.vars import Var
 
@@ -81,7 +80,7 @@ class Callout(CalloutRoot):
         )
 
 
-class CalloutNamespace(SimpleNamespace):
+class CalloutNamespace(ComponentNamespace):
     """Callout components namespace."""
 
     root = staticmethod(CalloutRoot.create)

+ 2 - 3
reflex/components/radix/themes/components/callout.pyi

@@ -7,11 +7,10 @@ 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 types import SimpleNamespace
 from typing import Literal, Union
 import reflex as rx
 from reflex import el
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.lucide.icon import Icon
 from reflex.vars import Var
 from ..base import LiteralAccentColor, RadixThemesComponent
@@ -715,7 +714,7 @@ class Callout(CalloutRoot):
         """
         ...
 
-class CalloutNamespace(SimpleNamespace):
+class CalloutNamespace(ComponentNamespace):
     root = staticmethod(CalloutRoot.create)
     icon = staticmethod(CalloutIcon.create)
     text = staticmethod(CalloutText.create)

+ 2 - 3
reflex/components/radix/themes/components/checkbox.py

@@ -1,9 +1,8 @@
 """Interactive components provided by @radix-ui/themes."""
 
-from types import SimpleNamespace
 from typing import Any, Dict, Literal
 
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.radix.themes.layout.flex import Flex
 from reflex.components.radix.themes.typography.text import Text
 from reflex.constants import EventTriggers
@@ -162,7 +161,7 @@ class HighLevelCheckbox(RadixThemesComponent):
         )
 
 
-class CheckboxNamespace(SimpleNamespace):
+class CheckboxNamespace(ComponentNamespace):
     """Checkbox components namespace."""
 
     __call__ = staticmethod(HighLevelCheckbox.create)

+ 2 - 3
reflex/components/radix/themes/components/checkbox.pyi

@@ -7,9 +7,8 @@ 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 types import SimpleNamespace
 from typing import Any, Dict, Literal
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.radix.themes.layout.flex import Flex
 from reflex.components.radix.themes.typography.text import Text
 from reflex.constants import EventTriggers
@@ -371,7 +370,7 @@ class HighLevelCheckbox(RadixThemesComponent):
         """
         ...
 
-class CheckboxNamespace(SimpleNamespace):
+class CheckboxNamespace(ComponentNamespace):
     @staticmethod
     def __call__(
         *children,

+ 2 - 2
reflex/components/radix/themes/components/context_menu.py

@@ -1,7 +1,7 @@
 """Interactive components provided by @radix-ui/themes."""
-from types import SimpleNamespace
 from typing import Any, Dict, List, Literal
 
+from reflex.components.component import ComponentNamespace
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 
@@ -147,7 +147,7 @@ class ContextMenuSeparator(RadixThemesComponent):
     tag = "ContextMenu.Separator"
 
 
-class ContextMenu(SimpleNamespace):
+class ContextMenu(ComponentNamespace):
     """Menu representing a set of actions, displayed at the origin of a pointer right-click or long-press."""
 
     root = staticmethod(ContextMenuRoot.create)

+ 2 - 2
reflex/components/radix/themes/components/context_menu.pyi

@@ -7,8 +7,8 @@ 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 types import SimpleNamespace
 from typing import Any, Dict, List, Literal
+from reflex.components.component import ComponentNamespace
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 from ..base import LiteralAccentColor, RadixThemesComponent
@@ -826,7 +826,7 @@ class ContextMenuSeparator(RadixThemesComponent):
         """
         ...
 
-class ContextMenu(SimpleNamespace):
+class ContextMenu(ComponentNamespace):
     root = staticmethod(ContextMenuRoot.create)
     trigger = staticmethod(ContextMenuTrigger.create)
     content = staticmethod(ContextMenuContent.create)

+ 2 - 2
reflex/components/radix/themes/components/dialog.py

@@ -1,9 +1,9 @@
 """Interactive components provided by @radix-ui/themes."""
 
-from types import SimpleNamespace
 from typing import Any, Dict, Literal
 
 from reflex import el
+from reflex.components.component import ComponentNamespace
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 
@@ -80,7 +80,7 @@ class DialogClose(RadixThemesComponent):
     tag = "Dialog.Close"
 
 
-class Dialog(SimpleNamespace):
+class Dialog(ComponentNamespace):
     """Dialog components namespace."""
 
     root = __call__ = staticmethod(DialogRoot.create)

+ 2 - 2
reflex/components/radix/themes/components/dialog.pyi

@@ -7,9 +7,9 @@ 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 types import SimpleNamespace
 from typing import Any, Dict, Literal
 from reflex import el
+from reflex.components.component import ComponentNamespace
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 from ..base import RadixThemesComponent
@@ -570,7 +570,7 @@ class DialogClose(RadixThemesComponent):
         """
         ...
 
-class Dialog(SimpleNamespace):
+class Dialog(ComponentNamespace):
     root = staticmethod(DialogRoot.create)
     trigger = staticmethod(DialogTrigger.create)
     title = staticmethod(DialogTitle.create)

+ 2 - 2
reflex/components/radix/themes/components/dropdown_menu.py

@@ -1,7 +1,7 @@
 """Interactive components provided by @radix-ui/themes."""
-from types import SimpleNamespace
 from typing import Any, Dict, List, Literal, Union
 
+from reflex.components.component import ComponentNamespace
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 
@@ -272,7 +272,7 @@ class DropdownMenuSeparator(RadixThemesComponent):
     tag = "DropdownMenu.Separator"
 
 
-class DropdownMenu(SimpleNamespace):
+class DropdownMenu(ComponentNamespace):
     """DropdownMenu components namespace."""
 
     root = staticmethod(DropdownMenuRoot.create)

+ 2 - 2
reflex/components/radix/themes/components/dropdown_menu.pyi

@@ -7,8 +7,8 @@ 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 types import SimpleNamespace
 from typing import Any, Dict, List, Literal, Union
+from reflex.components.component import ComponentNamespace
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 from ..base import LiteralAccentColor, RadixThemesComponent
@@ -927,7 +927,7 @@ class DropdownMenuSeparator(RadixThemesComponent):
         """
         ...
 
-class DropdownMenu(SimpleNamespace):
+class DropdownMenu(ComponentNamespace):
     root = staticmethod(DropdownMenuRoot.create)
     trigger = staticmethod(DropdownMenuTrigger.create)
     content = staticmethod(DropdownMenuContent.create)

+ 2 - 2
reflex/components/radix/themes/components/hover_card.py

@@ -1,8 +1,8 @@
 """Interactive components provided by @radix-ui/themes."""
-from types import SimpleNamespace
 from typing import Any, Dict, Literal
 
 from reflex import el
+from reflex.components.component import ComponentNamespace
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 
@@ -64,7 +64,7 @@ class HoverCardContent(el.Div, RadixThemesComponent):
     avoid_collisions: Var[bool]
 
 
-class HoverCard(SimpleNamespace):
+class HoverCard(ComponentNamespace):
     """For sighted users to preview content available behind a link."""
 
     root = __call__ = staticmethod(HoverCardRoot.create)

+ 2 - 2
reflex/components/radix/themes/components/hover_card.pyi

@@ -7,9 +7,9 @@ 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 types import SimpleNamespace
 from typing import Any, Dict, Literal
 from reflex import el
+from reflex.components.component import ComponentNamespace
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 from ..base import RadixThemesComponent
@@ -337,7 +337,7 @@ class HoverCardContent(el.Div, RadixThemesComponent):
         """
         ...
 
-class HoverCard(SimpleNamespace):
+class HoverCard(ComponentNamespace):
     root = staticmethod(HoverCardRoot.create)
     trigger = staticmethod(HoverCardTrigger.create)
     content = staticmethod(HoverCardContent.create)

+ 2 - 2
reflex/components/radix/themes/components/popover.py

@@ -1,8 +1,8 @@
 """Interactive components provided by @radix-ui/themes."""
-from types import SimpleNamespace
 from typing import Any, Dict, Literal
 
 from reflex import el
+from reflex.components.component import ComponentNamespace
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 
@@ -86,7 +86,7 @@ class PopoverClose(RadixThemesComponent):
     tag = "Popover.Close"
 
 
-class Popover(SimpleNamespace):
+class Popover(ComponentNamespace):
     """Floating element for displaying rich content, triggered by a button."""
 
     root = staticmethod(PopoverRoot.create)

+ 2 - 2
reflex/components/radix/themes/components/popover.pyi

@@ -7,9 +7,9 @@ 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 types import SimpleNamespace
 from typing import Any, Dict, Literal
 from reflex import el
+from reflex.components.component import ComponentNamespace
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 from ..base import RadixThemesComponent
@@ -437,7 +437,7 @@ class PopoverClose(RadixThemesComponent):
         """
         ...
 
-class Popover(SimpleNamespace):
+class Popover(ComponentNamespace):
     root = staticmethod(PopoverRoot.create)
     trigger = staticmethod(PopoverTrigger.create)
     content = staticmethod(PopoverContent.create)

+ 2 - 3
reflex/components/radix/themes/components/radio_group.py

@@ -1,10 +1,9 @@
 """Interactive components provided by @radix-ui/themes."""
 
-from types import SimpleNamespace
 from typing import Any, Dict, List, Literal, Optional, Union
 
 import reflex as rx
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.radix.themes.layout.flex import Flex
 from reflex.components.radix.themes.typography.text import Text
 from reflex.constants import EventTriggers
@@ -189,7 +188,7 @@ class HighLevelRadioGroup(RadixThemesComponent):
         )
 
 
-class RadioGroup(SimpleNamespace):
+class RadioGroup(ComponentNamespace):
     """RadioGroup components namespace."""
 
     root = staticmethod(RadioGroupRoot.create)

+ 2 - 3
reflex/components/radix/themes/components/radio_group.pyi

@@ -7,10 +7,9 @@ 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 types import SimpleNamespace
 from typing import Any, Dict, List, Literal, Optional, Union
 import reflex as rx
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.radix.themes.layout.flex import Flex
 from reflex.components.radix.themes.typography.text import Text
 from reflex.constants import EventTriggers
@@ -451,7 +450,7 @@ class HighLevelRadioGroup(RadixThemesComponent):
         """
         ...
 
-class RadioGroup(SimpleNamespace):
+class RadioGroup(ComponentNamespace):
     root = staticmethod(RadioGroupRoot.create)
     item = staticmethod(RadioGroupItem.create)
 

+ 2 - 3
reflex/components/radix/themes/components/select.py

@@ -1,9 +1,8 @@
 """Interactive components provided by @radix-ui/themes."""
-from types import SimpleNamespace
 from typing import Any, Dict, List, Literal, Union
 
 import reflex as rx
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 
@@ -236,7 +235,7 @@ class HighLevelSelect(SelectRoot):
         )
 
 
-class Select(SimpleNamespace):
+class Select(ComponentNamespace):
     """Select components namespace."""
 
     root = staticmethod(SelectRoot.create)

+ 2 - 3
reflex/components/radix/themes/components/select.pyi

@@ -7,10 +7,9 @@ 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 types import SimpleNamespace
 from typing import Any, Dict, List, Literal, Union
 import reflex as rx
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 from ..base import LiteralAccentColor, LiteralRadius, RadixThemesComponent
@@ -967,7 +966,7 @@ class HighLevelSelect(SelectRoot):
         """
         ...
 
-class Select(SimpleNamespace):
+class Select(ComponentNamespace):
     root = staticmethod(SelectRoot.create)
     trigger = staticmethod(SelectTrigger.create)
     content = staticmethod(SelectContent.create)

+ 2 - 2
reflex/components/radix/themes/components/table.py

@@ -1,8 +1,8 @@
 """Interactive components provided by @radix-ui/themes."""
-from types import SimpleNamespace
 from typing import List, Literal
 
 from reflex import el
+from reflex.components.component import ComponentNamespace
 from reflex.vars import Var
 
 from ..base import (
@@ -111,7 +111,7 @@ class TableRowHeaderCell(el.Th, RadixThemesComponent):
     ]
 
 
-class Table(SimpleNamespace):
+class Table(ComponentNamespace):
     """Table components namespace."""
 
     root = staticmethod(TableRoot.create)

+ 2 - 2
reflex/components/radix/themes/components/table.pyi

@@ -7,9 +7,9 @@ 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 types import SimpleNamespace
 from typing import List, Literal
 from reflex import el
+from reflex.components.component import ComponentNamespace
 from reflex.vars import Var
 from ..base import RadixThemesComponent
 
@@ -1066,7 +1066,7 @@ class TableRowHeaderCell(el.Th, RadixThemesComponent):
         """
         ...
 
-class Table(SimpleNamespace):
+class Table(ComponentNamespace):
     root = staticmethod(TableRoot.create)
     header = staticmethod(TableHeader.create)
     body = staticmethod(TableBody.create)

+ 2 - 2
reflex/components/radix/themes/components/tabs.py

@@ -1,7 +1,7 @@
 """Interactive components provided by @radix-ui/themes."""
-from types import SimpleNamespace
 from typing import Any, Dict, List, Literal
 
+from reflex.components.component import ComponentNamespace
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 
@@ -71,7 +71,7 @@ class TabsContent(RadixThemesComponent):
     value: Var[str]
 
 
-class Tabs(SimpleNamespace):
+class Tabs(ComponentNamespace):
     """Set of content sections to be displayed one at a time."""
 
     root = __call__ = staticmethod(TabsRoot.create)

+ 2 - 2
reflex/components/radix/themes/components/tabs.pyi

@@ -7,8 +7,8 @@ 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 types import SimpleNamespace
 from typing import Any, Dict, List, Literal
+from reflex.components.component import ComponentNamespace
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 from ..base import RadixThemesComponent
@@ -352,7 +352,7 @@ class TabsContent(RadixThemesComponent):
         """
         ...
 
-class Tabs(SimpleNamespace):
+class Tabs(ComponentNamespace):
     root = staticmethod(TabsRoot.create)
     list = staticmethod(TabsList.create)
     trigger = staticmethod(TabsTrigger.create)

+ 2 - 3
reflex/components/radix/themes/components/text_field.py

@@ -1,10 +1,9 @@
 """Interactive components provided by @radix-ui/themes."""
 
-from types import SimpleNamespace
 from typing import Any, Dict, Literal
 
 from reflex.components import el
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.core.debounce import DebounceInput
 from reflex.constants import EventTriggers
 from reflex.vars import Var
@@ -159,7 +158,7 @@ class Input(RadixThemesComponent):
         }
 
 
-class TextField(SimpleNamespace):
+class TextField(ComponentNamespace):
     """TextField components namespace."""
 
     root = staticmethod(TextFieldRoot.create)

+ 2 - 3
reflex/components/radix/themes/components/text_field.pyi

@@ -7,10 +7,9 @@ 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 types import SimpleNamespace
 from typing import Any, Dict, Literal
 from reflex.components import el
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.core.debounce import DebounceInput
 from reflex.constants import EventTriggers
 from reflex.vars import Var
@@ -888,7 +887,7 @@ class Input(RadixThemesComponent):
         ...
     def get_event_triggers(self) -> Dict[str, Any]: ...
 
-class TextField(SimpleNamespace):
+class TextField(ComponentNamespace):
     root = staticmethod(TextFieldRoot.create)
     input = staticmethod(TextFieldInput.create)
     slot = staticmethod(TextFieldSlot.create)

+ 2 - 3
reflex/components/radix/themes/layout/list.py

@@ -1,9 +1,8 @@
 """List components."""
 
-from types import SimpleNamespace
 from typing import Iterable, Literal, Optional, Union
 
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.core.foreach import Foreach
 from reflex.components.el.elements.typography import Li
 from reflex.style import Style
@@ -142,7 +141,7 @@ class ListItem(Li):
     ...
 
 
-class List(SimpleNamespace):
+class List(ComponentNamespace):
     """List components."""
 
     item = ListItem.create

+ 2 - 3
reflex/components/radix/themes/layout/list.pyi

@@ -7,9 +7,8 @@ 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 types import SimpleNamespace
 from typing import Iterable, Literal, Optional, Union
-from reflex.components.component import Component
+from reflex.components.component import Component, ComponentNamespace
 from reflex.components.core.foreach import Foreach
 from reflex.components.el.elements.typography import Li
 from reflex.style import Style
@@ -1014,7 +1013,7 @@ class ListItem(Li):
         """
         ...
 
-class List(SimpleNamespace):
+class List(ComponentNamespace):
     item = ListItem.create
     ordered = OrderedList.create
     unordered = UnorderedList.create

+ 2 - 2
reflex/components/radix/themes/typography/text.py

@@ -5,10 +5,10 @@ https://www.radix-ui.com/themes/docs/theme/typography
 
 from __future__ import annotations
 
-from types import SimpleNamespace
 from typing import Literal
 
 from reflex import el
+from reflex.components.component import ComponentNamespace
 from reflex.vars import Var
 
 from ..base import (
@@ -107,7 +107,7 @@ class Strong(el.Strong, RadixThemesComponent):
     tag = "Strong"
 
 
-class TextNamespace(SimpleNamespace):
+class TextNamespace(ComponentNamespace):
     """Checkbox components namespace."""
 
     __call__ = staticmethod(Text.create)

+ 2 - 2
reflex/components/radix/themes/typography/text.pyi

@@ -7,9 +7,9 @@ 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 types import SimpleNamespace
 from typing import Literal
 from reflex import el
+from reflex.components.component import ComponentNamespace
 from reflex.vars import Var
 from ..base import LiteralAccentColor, RadixThemesComponent
 from .base import LiteralTextAlign, LiteralTextSize, LiteralTextTrim, LiteralTextWeight
@@ -1138,7 +1138,7 @@ class Strong(el.Strong, RadixThemesComponent):
         """
         ...
 
-class TextNamespace(SimpleNamespace):
+class TextNamespace(ComponentNamespace):
     em = staticmethod(Em.create)
     kbd = staticmethod(Kbd.create)
     quote = staticmethod(Quote.create)

+ 9 - 0
tests/test_style.py

@@ -6,6 +6,7 @@ import pytest
 
 import reflex as rx
 from reflex import style
+from reflex.components.component import evaluate_style_namespaces
 from reflex.style import Style
 from reflex.vars import Var
 
@@ -494,3 +495,11 @@ def test_style_via_component_with_state(
     assert comp.style._var_data == expected_get_style["css"]._var_data
     # Assert that style values are equal.
     compare_dict_of_var(comp._get_style(), expected_get_style)
+
+
+def test_evaluate_style_namespaces():
+    """Test that namespaces get converted to component create functions."""
+    style_dict = {rx.text: {"color": "blue"}}
+    assert rx.text.__call__ not in style_dict
+    style_dict = evaluate_style_namespaces(style_dict)  # type: ignore
+    assert rx.text.__call__ in style_dict