Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IconButton for color_mode with nice default and a position props to control it #3165

Merged
merged 7 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions reflex/components/lucide/icon.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Lucide Icon component."""

from reflex.components.component import Component
from reflex.style import Style
from reflex.utils import console, format
from reflex.vars import Var

Expand Down Expand Up @@ -73,16 +72,9 @@ def map_deprecated_icon_names_05(tag: str) -> str:

props["tag"] = format.to_title_case(format.to_snake_case(props["tag"])) + "Icon"
props["alias"] = f"Lucide{props['tag']}"
props.setdefault("color", f"var(--current-color)")
return super().create(*children, **props)

def _apply_theme(self, theme: Component):
self.style = Style(
{
"color": f"var(--current-color)",
**self.style,
}
)


RENAMED_ICONS_05 = {
"activity_square": "square_activity",
Expand Down
1 change: 0 additions & 1 deletion reflex/components/lucide/icon.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ from reflex.vars import Var, BaseVar, ComputedVar
from reflex.event import EventChain, EventHandler, EventSpec
from reflex.style import Style
from reflex.components.component import Component
from reflex.style import Style
from reflex.utils import console, format
from reflex.vars import Var

Expand Down
85 changes: 74 additions & 11 deletions reflex/components/radix/themes/color_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@
)
```
"""

from __future__ import annotations

import dataclasses
from typing import Literal, get_args

from reflex.components.component import BaseComponent
from reflex.components.core.cond import Cond, color_mode_cond
from reflex.components.core.cond import Cond, color_mode_cond, cond
from reflex.components.lucide.icon import Icon
from reflex.style import LIGHT_COLOR_MODE, color_mode, toggle_color_mode
from reflex.vars import BaseVar
from reflex.utils import console
from reflex.vars import BaseVar, Var

from .components.button import Button
from .components.icon_button import IconButton
from .components.switch import Switch

DEFAULT_LIGHT_ICON: Icon = Icon.create(tag="sun")
Expand Down Expand Up @@ -77,22 +80,83 @@ def create(cls, *children, **props):
)


class ColorModeButton(Button):
"""Button for toggling chakra light / dark mode via toggle_color_mode."""
LiteralPosition = Literal["top-left", "top-right", "bottom-left", "bottom-right"]


class ColorModeIconButton(IconButton):
"""Icon Button for toggling light / dark mode via toggle_color_mode."""

@classmethod
def create(cls, *children, **props):
"""Create a button component that calls toggle_color_mode on click.
def create(
cls,
*children,
position: LiteralPosition | None = None,
**props,
):
"""Create a icon button component that calls toggle_color_mode on click.

Args:
*children: The children of the component.
position: The position of the icon button. Follow document flow if None.
**props: The props to pass to the component.

Returns:
The button component.
"""
return Button.create(
*children,
if children:
console.deprecate(
feature_name="passing children to color_mode.button",
reason=", use color_mode_cond and toggle_color_mode instead to build a custom color_mode component",
deprecation_version="0.5.0",
removal_version="0.6.0",
)

position_values = get_args(LiteralPosition)

def find(const, var):
return Var.create_safe(const).contains(var)

def set_var_default(prop, default1, default2=""):
Lendemor marked this conversation as resolved.
Show resolved Hide resolved
props.setdefault(
prop, cond(find(position_map[prop], position), default1, default2)
)

def set_static_default(prop, default):
if prop in position:
props.setdefault(prop, default)

position_map = {
"position": position_values,
"left": ["top-left", "bottom-left"],
"right": ["top-right", "bottom-right"],
"top": ["top-left", "top-right"],
"bottom": ["bottom-left", "bottom-right"],
}

# position is used to set nice defaults for positioning the icon button
if isinstance(position, Var):
(set_var_default("position", "fixed", position),)
Lendemor marked this conversation as resolved.
Show resolved Hide resolved
set_var_default("bottom", "2rem")
set_var_default("top", "2rem")
set_var_default("left", "2rem")
set_var_default("right", "2rem")
elif position is not None:
if position in position_values:
props.setdefault("position", "fixed")
set_static_default("bottom", "2rem")
set_static_default("top", "2rem")
set_static_default("left", "2rem")
set_static_default("right", "2rem")
else:
props["position"] = position

props.setdefault("background", "transparent")
props.setdefault("color", "inherit")
props.setdefault("z_index", "20")
props.setdefault(":hover", {"cursor": "pointer"})

return super().create(
ColorModeIcon.create(),
on_click=toggle_color_mode,
**props,
)
Expand All @@ -102,8 +166,7 @@ class ColorModeNamespace(BaseVar):
"""Namespace for color mode components."""

icon = staticmethod(ColorModeIcon.create)
switch = staticmethod(ColorModeSwitch.create)
Lendemor marked this conversation as resolved.
Show resolved Hide resolved
button = staticmethod(ColorModeButton.create)
button = staticmethod(ColorModeIconButton.create)


color_mode_var_and_namespace = ColorModeNamespace(**dataclasses.asdict(color_mode))
23 changes: 14 additions & 9 deletions reflex/components/radix/themes/color_mode.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ from reflex.vars import Var, BaseVar, ComputedVar
from reflex.event import EventChain, EventHandler, EventSpec
from reflex.style import Style
import dataclasses
from typing import Literal, get_args
from reflex.components.component import BaseComponent
from reflex.components.core.cond import Cond, color_mode_cond
from reflex.components.core.cond import Cond, color_mode_cond, cond
from reflex.components.lucide.icon import Icon
from reflex.style import LIGHT_COLOR_MODE, color_mode, toggle_color_mode
from reflex.vars import BaseVar
from .components.button import Button
from reflex.utils import console
from reflex.vars import BaseVar, Var
from .components.icon_button import IconButton
from .components.switch import Switch

DEFAULT_LIGHT_ICON: Icon
Expand Down Expand Up @@ -267,12 +269,15 @@ class ColorModeSwitch(Switch):
"""
...

class ColorModeButton(Button):
LiteralPosition = Literal["top-left", "top-right", "bottom-left", "bottom-right"]

class ColorModeIconButton(IconButton):
@overload
@classmethod
def create( # type: ignore
cls,
*children,
position: Optional[LiteralPosition | None] = None,
as_child: Optional[Union[Var[bool], bool]] = None,
size: Optional[
Union[Var[Literal["1", "2", "3", "4"]], Literal["1", "2", "3", "4"]]
Expand Down Expand Up @@ -470,14 +475,15 @@ class ColorModeButton(Button):
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
**props
) -> "ColorModeButton":
"""Create a button component that calls toggle_color_mode on click.
) -> "ColorModeIconButton":
"""Create a icon button component that calls toggle_color_mode on click.

Args:
*children: The children of the component.
position: The position of the icon button. Follow document flow if None.
as_child: Change the default rendered element for the one passed as a child, merging their props and behavior.
size: Button size "1" - "4"
variant: Variant of button: "solid" | "soft" | "outline" | "ghost"
variant: Variant of button: "classic" | "solid" | "soft" | "surface" | "outline" | "ghost"
color_scheme: Override theme color for button
high_contrast: Whether to render the button with higher contrast color against background
radius: Override theme radius for button: "none" | "small" | "medium" | "large" | "full"
Expand Down Expand Up @@ -524,7 +530,6 @@ class ColorModeButton(Button):

class ColorModeNamespace(BaseVar):
icon = staticmethod(ColorModeIcon.create)
switch = staticmethod(ColorModeSwitch.create)
button = staticmethod(ColorModeButton.create)
button = staticmethod(ColorModeIconButton.create)

color_mode_var_and_namespace = ColorModeNamespace(**dataclasses.asdict(color_mode))
5 changes: 1 addition & 4 deletions reflex/components/radix/themes/components/icon_button.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from reflex.components.component import Component
from reflex.components.core.match import Match
from reflex.components.lucide import Icon
from reflex.style import Style
from reflex.vars import Var

from ..base import (
Expand Down Expand Up @@ -86,10 +85,8 @@ def create(cls, *children, **props) -> Component:
("4", "48px"),
"12px",
)
props.setdefault("padding", "6px")
return super().create(*children, **props)

def _apply_theme(self, theme: Component):
self.style = Style({"padding": "6px", **self.style})


icon_button = IconButton.create
1 change: 0 additions & 1 deletion reflex/components/radix/themes/components/icon_button.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ from reflex import el
from reflex.components.component import Component
from reflex.components.core.match import Match
from reflex.components.lucide import Icon
from reflex.style import Style
from reflex.vars import Var
from ..base import (
LiteralAccentColor,
Expand Down
Loading