Browse Source

Refactor rx.color (#2522)

* Refactor

* Lint

* Change name space to top level

* Update test

* Lint

* Fix pyright

* Update pyi

---------

Co-authored-by: Alek Petuskey <alekpetuskey@aleks-mbp.lan>
Co-authored-by: Nikhil Rao <nikhil@reflex.dev>
Alek Petuskey 1 year ago
parent
commit
5589cbbfc2

+ 1 - 1
reflex/__init__.py

@@ -9,7 +9,6 @@ from __future__ import annotations
 import importlib
 import importlib
 from typing import Type
 from typing import Type
 
 
-from reflex.constants.colors import Color as color
 from reflex.page import page as page
 from reflex.page import page as page
 from reflex.utils import console
 from reflex.utils import console
 from reflex.utils.format import to_snake_case
 from reflex.utils.format import to_snake_case
@@ -254,6 +253,7 @@ _MAPPING = {
     "reflex.compiler.utils": ["get_asset_path"],
     "reflex.compiler.utils": ["get_asset_path"],
     "reflex.components": _ALL_COMPONENTS + ["chakra", "next"],
     "reflex.components": _ALL_COMPONENTS + ["chakra", "next"],
     "reflex.components.component": ["memo"],
     "reflex.components.component": ["memo"],
+    "reflex.components.core": ["color"],
     "reflex.components.el": ["el"],
     "reflex.components.el": ["el"],
     "reflex.components.lucide": ["lucide"],
     "reflex.components.lucide": ["lucide"],
     "reflex.components.radix": ["radix"],
     "reflex.components.radix": ["radix"],

+ 1 - 0
reflex/__init__.pyi

@@ -447,6 +447,7 @@ from reflex.components import NoSSRComponent as NoSSRComponent
 from reflex.components import chakra as chakra
 from reflex.components import chakra as chakra
 from reflex.components import next as next
 from reflex.components import next as next
 from reflex.components.component import memo as memo
 from reflex.components.component import memo as memo
+from reflex.components.core import color as color
 from reflex.components import el as el
 from reflex.components import el as el
 from reflex.components import lucide as lucide
 from reflex.components import lucide as lucide
 from reflex.components import radix as radix
 from reflex.components import radix as radix

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

@@ -2,6 +2,7 @@
 
 
 from . import layout as layout
 from . import layout as layout
 from .banner import ConnectionBanner, ConnectionModal
 from .banner import ConnectionBanner, ConnectionModal
+from .colors import color
 from .cond import Cond, cond
 from .cond import Cond, cond
 from .debounce import DebounceInput
 from .debounce import DebounceInput
 from .foreach import Foreach
 from .foreach import Foreach

+ 21 - 0
reflex/components/core/colors.py

@@ -0,0 +1,21 @@
+"""The colors used in Reflex are a wrapper around https://www.radix-ui.com/colors."""
+
+from reflex.constants.colors import Color, ColorType, ShadeType
+
+
+def color(
+    color: ColorType,
+    shade: ShadeType = 7,
+    alpha: bool = False,
+) -> Color:
+    """Create a color object.
+
+    Args:
+        color: The color to use.
+        shade: The shade of the color to use.
+        alpha: Whether to use the alpha variant of the color.
+
+    Returns:
+        The color object.
+    """
+    return Color(color, shade, alpha)

+ 26 - 0
reflex/constants/colors.py

@@ -1,4 +1,5 @@
 """The colors used in Reflex are a wrapper around https://www.radix-ui.com/colors."""
 """The colors used in Reflex are a wrapper around https://www.radix-ui.com/colors."""
+
 from dataclasses import dataclass
 from dataclasses import dataclass
 from typing import Literal
 from typing import Literal
 
 
@@ -40,6 +41,20 @@ ColorType = Literal[
 ShadeType = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
 ShadeType = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
 
 
 
 
+def format_color(color: ColorType, shade: ShadeType, alpha: bool) -> str:
+    """Format a color as a CSS color string.
+
+    Args:
+        color: The color to use.
+        shade: The shade of the color to use.
+        alpha: Whether to use the alpha variant of the color.
+
+    Returns:
+        The formatted color.
+    """
+    return f"var(--{color}-{'a' if alpha else ''}{shade})"
+
+
 @dataclass
 @dataclass
 class Color:
 class Color:
     """A color in the Reflex color palette."""
     """A color in the Reflex color palette."""
@@ -52,3 +67,14 @@ class Color:
 
 
     # Whether to use the alpha variant of the color
     # Whether to use the alpha variant of the color
     alpha: bool = False
     alpha: bool = False
+
+    def __format__(self, format_spec: str) -> str:
+        """Format the color as a CSS color string.
+
+        Args:
+            format_spec: The format specifier to use.
+
+        Returns:
+            The formatted color.
+        """
+        return format_color(self.color, self.shade, self.alpha)

+ 3 - 6
reflex/utils/serializers.py

@@ -8,7 +8,7 @@ from datetime import date, datetime, time, timedelta
 from typing import Any, Callable, Dict, List, Set, Tuple, Type, Union, get_type_hints
 from typing import Any, Callable, Dict, List, Set, Tuple, Type, Union, get_type_hints
 
 
 from reflex.base import Base
 from reflex.base import Base
-from reflex.constants.colors import Color
+from reflex.constants.colors import Color, format_color
 from reflex.utils import exceptions, format, types
 from reflex.utils import exceptions, format, types
 
 
 # Mapping from type to a serializer.
 # Mapping from type to a serializer.
@@ -232,7 +232,7 @@ def serialize_datetime(dt: Union[date, datetime, time, timedelta]) -> str:
 
 
 
 
 @serializer
 @serializer
-def serialize_color(color: Color) -> SerializedType:
+def serialize_color(color: Color) -> str:
     """Serialize a color.
     """Serialize a color.
 
 
     Args:
     Args:
@@ -241,10 +241,7 @@ def serialize_color(color: Color) -> SerializedType:
     Returns:
     Returns:
         The serialized color.
         The serialized color.
     """
     """
-    if color.alpha:
-        return f"var(--{color.color}-a{color.shade})"
-    else:
-        return f"var(--{color.color}-{color.shade})"
+    return format_color(color.color, color.shade, color.alpha)
 
 
 
 
 try:
 try:

+ 1 - 1
tests/utils/test_serializers.py

@@ -5,7 +5,7 @@ from typing import Any, Dict, List, Type
 import pytest
 import pytest
 
 
 from reflex.base import Base
 from reflex.base import Base
-from reflex.constants.colors import Color as color
+from reflex.components.core.colors import color
 from reflex.utils import serializers
 from reflex.utils import serializers
 from reflex.vars import Var
 from reflex.vars import Var