From bece5bdb44c0f45986542f7236f618b08d40187b Mon Sep 17 00:00:00 2001 From: Masen Furer Date: Mon, 29 Jan 2024 16:58:05 -0800 Subject: [PATCH] [REF-1632] Apply `rx.App` styles to Radix Themes root `div` (#2481) --- integration/test_tailwind.py | 13 ++++++------ reflex/app.py | 7 ++++--- reflex/compiler/utils.py | 23 ++++++++++---------- reflex/components/radix/themes/base.py | 28 ++++++++++++++++++++----- reflex/components/radix/themes/base.pyi | 3 ++- tests/test_app.py | 2 +- 6 files changed, 48 insertions(+), 28 deletions(-) diff --git a/integration/test_tailwind.py b/integration/test_tailwind.py index 93d99158a..71079fc0e 100644 --- a/integration/test_tailwind.py +++ b/integration/test_tailwind.py @@ -10,14 +10,13 @@ from reflex.testing import AppHarness PARAGRAPH_TEXT = "Tailwind Is Cool" PARAGRAPH_CLASS_NAME = "text-red-500" -GLOBAL_PARAGRAPH_COLOR = "rgba(0, 0, 242, 1)" +TEXT_RED_500_COLOR = "rgba(239, 68, 68, 1)" def TailwindApp( tailwind_disabled: bool = False, paragraph_text: str = PARAGRAPH_TEXT, paragraph_class_name: str = PARAGRAPH_CLASS_NAME, - global_paragraph_color: str = GLOBAL_PARAGRAPH_COLOR, ): """App with tailwind optionally disabled. @@ -25,7 +24,6 @@ def TailwindApp( tailwind_disabled: Whether tailwind is disabled for the app. paragraph_text: Text for the paragraph. paragraph_class_name: Tailwind class_name for the paragraph. - global_paragraph_color: Color for the paragraph set in global app styles. """ import reflex as rx import reflex.components.radix.themes as rdxt @@ -38,7 +36,7 @@ def TailwindApp( id="p-content", ) - app = rx.App(style={"p": {"color": global_paragraph_color}}) + app = rx.App(style={"font_family": "monospace"}) app.add_page(index) if tailwind_disabled: config = rx.config.get_config() @@ -100,9 +98,10 @@ def test_tailwind_app(tailwind_app: AppHarness, tailwind_disabled: bool): assert len(paragraphs) == 3 for p in paragraphs: assert tailwind_app.poll_for_content(p, exp_not_equal="") == PARAGRAPH_TEXT + assert p.value_of_css_property("font-family") == "monospace" if tailwind_disabled: - # expect "blue" color from global stylesheet, not "text-red-500" from tailwind utility class - assert p.value_of_css_property("color") == GLOBAL_PARAGRAPH_COLOR + # expect default color, not "text-red-500" from tailwind utility class + assert p.value_of_css_property("color") != TEXT_RED_500_COLOR else: # expect "text-red-500" from tailwind utility class - assert p.value_of_css_property("color") == "rgba(239, 68, 68, 1)" + assert p.value_of_css_property("color") == TEXT_RED_500_COLOR diff --git a/reflex/app.py b/reflex/app.py index 5b93e02d0..ddfa626ea 100644 --- a/reflex/app.py +++ b/reflex/app.py @@ -44,6 +44,7 @@ from reflex.components.core.client_side_routing import ( wait_for_client_redirect, ) from reflex.components.core.upload import UploadFilesProvider +from reflex.components.radix import themes from reflex.config import get_config from reflex.event import Event, EventHandler, EventSpec from reflex.middleware import HydrateMiddleware, Middleware @@ -129,11 +130,11 @@ class App(Base): Union[Component, ComponentCallable] ] = default_overlay_component - # Background tasks that are currently running. + # Background tasks that are currently running background_tasks: Set[asyncio.Task] = set() - # The radix theme for the entire app. - theme: Optional[Component] + # The radix theme for the entire app + theme: Optional[Component] = themes.theme(accent_color="blue") def __init__(self, *args, **kwargs): """Initialize the app. diff --git a/reflex/compiler/utils.py b/reflex/compiler/utils.py index dd3a09453..c39e427cf 100644 --- a/reflex/compiler/utils.py +++ b/reflex/compiler/utils.py @@ -290,20 +290,21 @@ def create_theme(style: ComponentStyle) -> dict: The base style for the app. """ # Get the global style from the style dict. - global_style = Style({k: v for k, v in style.items() if not isinstance(k, type)}) + style_rules = Style({k: v for k, v in style.items() if not isinstance(k, type)}) - # Root styles. - root_style = Style({k: v for k, v in global_style.items() if k.startswith("::")}) - - # Body styles. - root_style["body"] = Style( - {k: v for k, v in global_style.items() if k not in root_style} - ) + root_style = { + # Root styles. + ":root": Style( + {f"*{k}": v for k, v in style_rules.items() if k.startswith(":")} + ), + # Body styles. + "body": Style( + {k: v for k, v in style_rules.items() if not k.startswith(":")}, + ), + } # Return the theme. - return { - "styles": {"global": root_style}, - } + return {"styles": {"global": root_style}} def get_page_path(path: str) -> str: diff --git a/reflex/components/radix/themes/base.py b/reflex/components/radix/themes/base.py index 75ef45a18..d1dfb25e8 100644 --- a/reflex/components/radix/themes/base.py +++ b/reflex/components/radix/themes/base.py @@ -2,9 +2,10 @@ from __future__ import annotations -from typing import Literal +from typing import Any, Literal from reflex.components import Component +from reflex.components.tags import Tag from reflex.utils import imports from reflex.vars import Var @@ -154,10 +155,27 @@ class Theme(RadixThemesComponent): scaling: Var[LiteralScaling] def _get_imports(self) -> imports.ImportDict: - return { - **super()._get_imports(), - "": [imports.ImportVar(tag="@radix-ui/themes/styles.css", install=False)], - } + return imports.merge_imports( + super()._get_imports(), + { + "": [ + imports.ImportVar(tag="@radix-ui/themes/styles.css", install=False) + ], + "/utils/theme.js": [ + imports.ImportVar(tag="theme", is_default=True), + ], + }, + ) + + def _render(self, props: dict[str, Any] | None = None) -> Tag: + tag = super()._render(props) + tag.add_props( + css=Var.create( + "{{...theme.styles.global[':root'], ...theme.styles.global.body}}", + _var_is_local=False, + ), + ) + return tag class ThemePanel(RadixThemesComponent): diff --git a/reflex/components/radix/themes/base.pyi b/reflex/components/radix/themes/base.pyi index ae2435584..12d922a47 100644 --- a/reflex/components/radix/themes/base.pyi +++ b/reflex/components/radix/themes/base.pyi @@ -7,8 +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 typing import Literal +from typing import Any, Literal from reflex.components import Component +from reflex.components.tags import Tag from reflex.utils import imports from reflex.vars import Var diff --git a/tests/test_app.py b/tests/test_app.py index 528a31c25..b9a018434 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -1222,7 +1222,7 @@ def test_app_wrap_compile_theme(compilable_app): "function AppWrap({children}) {" "return (" "" - "" + "" "" "{children}" ""