浏览代码

[REF-2087] Better rx.progress styling integration with radix themes (#2762)

* [REF-2087] Better rx.progress styling integration with radix themes

Support the `radius` prop on `ProgressRoot`, via data-radius and CSS tokens

Support the `color_scheme` on `ProgressIndicator`, via data-accent-color and CSS token

Move high-level `Progress` to a real `Component` subclass to get better pyi hinting

Allow overriding the background color of the `ProgressIndicator` via low-level api

Remove `value` and `max` props from `ProgressRoot` (these only apply to `ProgressIndicator`)

* Progress: do not pass `value` or `max` to ProgressRoot

* progress: use background_color instead of background-color
Masen Furer 1 年之前
父节点
当前提交
75b63cbc25
共有 2 个文件被更改,包括 348 次插入54 次删除
  1. 42 43
      reflex/components/radix/primitives/progress.py
  2. 306 11
      reflex/components/radix/primitives/progress.pyi

+ 42 - 43
reflex/components/radix/primitives/progress.py

@@ -2,13 +2,13 @@
 
 from __future__ import annotations
 
-from typing import Optional, Union
+from typing import Optional
 
 from reflex.components.component import Component, ComponentNamespace
 from reflex.components.core.colors import color
 from reflex.components.radix.primitives.accordion import DEFAULT_ANIMATION_DURATION
 from reflex.components.radix.primitives.base import RadixPrimitiveComponentWithClassName
-from reflex.components.radix.themes.base import LiteralAccentColor
+from reflex.components.radix.themes.base import LiteralAccentColor, LiteralRadius
 from reflex.style import Style
 from reflex.vars import Var
 
@@ -25,19 +25,19 @@ class ProgressRoot(ProgressComponent):
     tag = "Root"
     alias = "RadixProgressRoot"
 
-    # The current progress value.
-    value: Var[Optional[int]]
-
-    # The maximum progress value.
-    max: Var[int]
+    # Override theme radius for progress bar: "none" | "small" | "medium" | "large" | "full"
+    radius: Var[LiteralRadius]
 
     def _apply_theme(self, theme: Component):
+        if self.radius is not None:
+            self.custom_attrs["data-radius"] = self.radius
+
         self.style = Style(
             {
                 "position": "relative",
                 "overflow": "hidden",
                 "background": "var(--gray-a3)",
-                "border_radius": "99999px",
+                "border_radius": "max(var(--radius-2), var(--radius-full))",
                 "width": "100%",
                 "height": "20px",
                 "boxShadow": "inset 0 0 0 1px var(--gray-a5)",
@@ -45,6 +45,9 @@ class ProgressRoot(ProgressComponent):
             }
         )
 
+    def _exclude_props(self) -> list[str]:
+        return ["radius"]
+
 
 class ProgressIndicator(ProgressComponent):
     """The Progress bar indicator."""
@@ -63,22 +66,12 @@ class ProgressIndicator(ProgressComponent):
     color_scheme: Var[LiteralAccentColor]
 
     def _apply_theme(self, theme: Component):
-        global_color_scheme = getattr(theme, "accent_color", None)
-
-        if global_color_scheme is None and self.color_scheme is None:
-            raise ValueError(
-                "`color_scheme` cannot be None. Either set the `color_scheme` prop on the progress indicator "
-                "component or set the `accent_color` prop in your global theme."
-            )
-
-        color_scheme = color(
-            self.color_scheme if self.color_scheme is not None else global_color_scheme,  # type: ignore
-            9,
-        )
+        if self.color_scheme is not None:
+            self.custom_attrs["data-accent-color"] = self.color_scheme
 
         self.style = Style(
             {
-                "background-color": color_scheme,
+                "background_color": color("accent", 9),
                 "width": "100%",
                 "height": "100%",
                 f"transition": f"transform {DEFAULT_ANIMATION_DURATION}ms linear",
@@ -87,6 +80,7 @@ class ProgressIndicator(ProgressComponent):
                 },
                 "transform": f"translateX(calc(-100% + ({self.value} / {self.max} * 100%)))",  # type: ignore
                 "boxShadow": "inset 0 0 0 1px var(--gray-a5)",
+                **self.style,
             }
         )
 
@@ -94,43 +88,48 @@ class ProgressIndicator(ProgressComponent):
         return ["color_scheme"]
 
 
-class Progress(ComponentNamespace):
-    """High-level API for progress bar."""
+class Progress(ProgressRoot):
+    """The high-level Progress component."""
 
-    root = staticmethod(ProgressRoot.create)
-    indicator = staticmethod(ProgressIndicator.create)
+    # Override theme color for progress bar indicator
+    color_scheme: Var[LiteralAccentColor]
 
-    @staticmethod
-    def __call__(
-        width: Optional[str] = "100%",
-        color_scheme: Optional[Union[Var, LiteralAccentColor]] = None,
-        **props,
-    ) -> Component:
+    # The current progress value.
+    value: Var[Optional[int]]
+
+    # The maximum progress value.
+    max: Var[Optional[int]]
+
+    @classmethod
+    def create(cls, **props) -> Component:
         """High-level API for progress bar.
 
         Args:
-            width: The width of the progress bar.
             **props: The props of the progress bar.
-            color_scheme: The color scheme of the progress indicator.
 
         Returns:
             The progress bar.
         """
-        style = props.setdefault("style", {})
-        style.update({"width": width})
-
-        progress_indicator_props = (
-            {"color_scheme": color_scheme} if color_scheme is not None else {}
-        )
+        progress_indicator_props = {}
+        if "color_scheme" in props:
+            progress_indicator_props["color_scheme"] = props.pop("color_scheme")
 
         return ProgressRoot.create(
             ProgressIndicator.create(
-                value=props.get("value"),
-                max=props.get("max", 100),
-                **progress_indicator_props,  # type: ignore
+                value=props.pop("value", 0),
+                max=props.pop("max", 100),
+                **progress_indicator_props,
             ),
             **props,
         )
 
 
-progress = Progress()
+class ProgressNamespace(ComponentNamespace):
+    """High-level API for progress bar."""
+
+    root = staticmethod(ProgressRoot.create)
+    indicator = staticmethod(ProgressIndicator.create)
+    __call__ = staticmethod(Progress.create)
+
+
+progress = ProgressNamespace()

+ 306 - 11
reflex/components/radix/primitives/progress.pyi

@@ -7,12 +7,12 @@ 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 Optional, Union
+from typing import Optional
 from reflex.components.component import Component, ComponentNamespace
 from reflex.components.core.colors import color
 from reflex.components.radix.primitives.accordion import DEFAULT_ANIMATION_DURATION
 from reflex.components.radix.primitives.base import RadixPrimitiveComponentWithClassName
-from reflex.components.radix.themes.base import LiteralAccentColor
+from reflex.components.radix.themes.base import LiteralAccentColor, LiteralRadius
 from reflex.style import Style
 from reflex.vars import Var
 
@@ -103,8 +103,12 @@ class ProgressRoot(ProgressComponent):
     def create(  # type: ignore
         cls,
         *children,
-        value: Optional[Union[Var[Optional[int]], Optional[int]]] = None,
-        max: Optional[Union[Var[int], int]] = None,
+        radius: Optional[
+            Union[
+                Var[Literal["none", "small", "medium", "large", "full"]],
+                Literal["none", "small", "medium", "large", "full"],
+            ]
+        ] = None,
         as_child: Optional[Union[Var[bool], bool]] = None,
         style: Optional[Style] = None,
         key: Optional[Any] = None,
@@ -163,8 +167,7 @@ class ProgressRoot(ProgressComponent):
 
         Args:
             *children: The children of the component.
-            value: The current progress value.
-            max: The maximum progress value.
+            radius: Override theme radius for progress bar: "none" | "small" | "medium" | "large" | "full"
             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.
@@ -330,15 +333,307 @@ class ProgressIndicator(ProgressComponent):
         """
         ...
 
-class Progress(ComponentNamespace):
+class Progress(ProgressRoot):
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        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,
+        value: Optional[Union[Var[Optional[int]], Optional[int]]] = None,
+        max: Optional[Union[Var[Optional[int]], Optional[int]]] = None,
+        radius: Optional[
+            Union[
+                Var[Literal["none", "small", "medium", "large", "full"]],
+                Literal["none", "small", "medium", "large", "full"],
+            ]
+        ] = 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_scroll: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "Progress":
+        """High-level API for progress bar.
+
+        Args:
+            color_scheme: Override theme color for progress bar indicator
+            value: The current progress value.
+            max: The maximum progress value.
+            radius: Override theme radius for progress bar: "none" | "small" | "medium" | "large" | "full"
+            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 progress bar.
+
+        Returns:
+            The progress bar.
+        """
+        ...
+
+class ProgressNamespace(ComponentNamespace):
     root = staticmethod(ProgressRoot.create)
     indicator = staticmethod(ProgressIndicator.create)
 
     @staticmethod
     def __call__(
-        width: Optional[str] = "100%",
-        color_scheme: Optional[Union[Var, LiteralAccentColor]] = None,
+        *children,
+        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,
+        value: Optional[Union[Var[Optional[int]], Optional[int]]] = None,
+        max: Optional[Union[Var[Optional[int]], Optional[int]]] = None,
+        radius: Optional[
+            Union[
+                Var[Literal["none", "small", "medium", "large", "full"]],
+                Literal["none", "small", "medium", "large", "full"],
+            ]
+        ] = 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_scroll: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, list, function, BaseVar]
+        ] = None,
         **props
-    ) -> Component: ...
+    ) -> "Progress":
+        """High-level API for progress bar.
+
+        Args:
+            color_scheme: Override theme color for progress bar indicator
+            value: The current progress value.
+            max: The maximum progress value.
+            radius: Override theme radius for progress bar: "none" | "small" | "medium" | "large" | "full"
+            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 progress bar.
+
+        Returns:
+            The progress bar.
+        """
+        ...
 
-progress = Progress()
+progress = ProgressNamespace()