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

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

@@ -2,6 +2,7 @@
 
 from . import layout as layout
 from .banner import ConnectionBanner, ConnectionModal
+from .colors import color
 from .cond import Cond, cond
 from .debounce import DebounceInput
 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."""
+
 from dataclasses import dataclass
 from typing import Literal
 
@@ -40,6 +41,20 @@ ColorType = Literal[
 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
 class Color:
     """A color in the Reflex color palette."""
@@ -52,3 +67,14 @@ class Color:
 
     # Whether to use the alpha variant of the color
     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 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
 
 # Mapping from type to a serializer.
@@ -232,7 +232,7 @@ def serialize_datetime(dt: Union[date, datetime, time, timedelta]) -> str:
 
 
 @serializer
-def serialize_color(color: Color) -> SerializedType:
+def serialize_color(color: Color) -> str:
     """Serialize a color.
 
     Args:
@@ -241,10 +241,7 @@ def serialize_color(color: Color) -> SerializedType:
     Returns:
         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:

+ 1 - 1
tests/utils/test_serializers.py

@@ -5,7 +5,7 @@ from typing import Any, Dict, List, Type
 import pytest
 
 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.vars import Var