Add vars and components for working with color_mode (#1132)
* `pc.color_mode`: a BaseVar that accesses colorMode on the frontend * `pc.color_mode_cond`: a `pc.cond` wrapper that conditionally renders components or props based on the value of `color_mode` * `pc.color_mode_icon`: by default "sun" if light mode, "moon" if dark mode * `pc.color_mode_switch`: a Switch component where is_checked depends on the color_mode and changing the value calls toggle_color_mode * `pc.color_mode_button`: a Button component that calls toggle_color_mode on click The default template has been updated to include a color_mode_button with color_mode_icon for toggling light/dark mode. The inline hover style has also been updated to use color_mode_cond to show a different highlight color based on the color_mode.
This commit is contained in:
parent
2bc45b000c
commit
aa2a1df201
@ -14,7 +14,8 @@ class State(pc.State):
|
||||
|
||||
|
||||
def index() -> pc.Component:
|
||||
return pc.center(
|
||||
return pc.fragment(
|
||||
pc.color_mode_button(pc.color_mode_icon(), float="right"),
|
||||
pc.vstack(
|
||||
pc.heading("Welcome to Pynecone!", font_size="2em"),
|
||||
pc.box("Get started by editing ", pc.code(filename, font_size="1em")),
|
||||
@ -25,13 +26,16 @@ def index() -> pc.Component:
|
||||
padding="0.5em",
|
||||
border_radius="0.5em",
|
||||
_hover={
|
||||
"color": "rgb(107,99,246)",
|
||||
"color": pc.color_mode_cond(
|
||||
light="rgb(107,99,246)",
|
||||
dark="rgb(179, 175, 255)",
|
||||
)
|
||||
},
|
||||
),
|
||||
spacing="1.5em",
|
||||
font_size="2em",
|
||||
padding_top="10%",
|
||||
),
|
||||
padding_top="10%",
|
||||
)
|
||||
|
||||
|
||||
|
@ -32,6 +32,7 @@ from .model import session as session
|
||||
from .route import route as route
|
||||
from .state import ComputedVar as var
|
||||
from .state import State as State
|
||||
from .style import color_mode as color_mode
|
||||
from .style import toggle_color_mode as toggle_color_mode
|
||||
from .vars import Var as Var
|
||||
from .vars import cached_var as cached_var
|
||||
|
@ -238,3 +238,6 @@ text = Text.create
|
||||
script = ScriptTag.create
|
||||
aspect_ratio = AspectRatio.create
|
||||
kbd = KeyboardKey.create
|
||||
color_mode_button = ColorModeButton.create
|
||||
color_mode_icon = ColorModeIcon.create
|
||||
color_mode_switch = ColorModeSwitch.create
|
||||
|
@ -2,6 +2,12 @@
|
||||
|
||||
from .button import Button, ButtonGroup
|
||||
from .checkbox import Checkbox, CheckboxGroup
|
||||
from .colormodeswitch import (
|
||||
ColorModeButton,
|
||||
ColorModeIcon,
|
||||
ColorModeSwitch,
|
||||
color_mode_cond,
|
||||
)
|
||||
from .copytoclipboard import CopyToClipboard
|
||||
from .date_picker import DatePicker
|
||||
from .date_time_picker import DateTimePicker
|
||||
@ -34,4 +40,8 @@ from .switch import Switch
|
||||
from .textarea import TextArea
|
||||
from .upload import Upload
|
||||
|
||||
__all__ = [f for f in dir() if f[0].isupper()] # type: ignore
|
||||
helpers = [
|
||||
"color_mode_cond",
|
||||
]
|
||||
|
||||
__all__ = [f for f in dir() if f[0].isupper()] + helpers # type: ignore
|
||||
|
116
pynecone/components/forms/colormodeswitch.py
Normal file
116
pynecone/components/forms/colormodeswitch.py
Normal file
@ -0,0 +1,116 @@
|
||||
"""A switch component for toggling color_mode.
|
||||
|
||||
To style components based on color mode, use style props with `color_mode_cond`:
|
||||
|
||||
```
|
||||
pc.text(
|
||||
"Hover over me",
|
||||
_hover={
|
||||
"background": pc.color_mode_cond(
|
||||
light="var(--chakra-colors-gray-200)",
|
||||
dark="var(--chakra-colors-gray-700)",
|
||||
),
|
||||
},
|
||||
)
|
||||
```
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from pynecone.components.component import Component
|
||||
from pynecone.components.layout.cond import Cond, cond
|
||||
from pynecone.components.media.icon import Icon
|
||||
from pynecone.style import color_mode, toggle_color_mode
|
||||
from pynecone.vars import BaseVar
|
||||
|
||||
from .button import Button
|
||||
from .switch import Switch
|
||||
|
||||
DEFAULT_COLOR_MODE = "light"
|
||||
DEFAULT_LIGHT_ICON = Icon.create(tag="sun")
|
||||
DEFAULT_DARK_ICON = Icon.create(tag="moon")
|
||||
|
||||
|
||||
def color_mode_cond(light: Any, dark: Any = None) -> BaseVar | Component:
|
||||
"""Create a component or Prop based on color_mode.
|
||||
|
||||
Args:
|
||||
light: The component or prop to render if color_mode is default
|
||||
dark: The component or prop to render if color_mode is non-default
|
||||
|
||||
Returns:
|
||||
The conditional component or prop.
|
||||
"""
|
||||
return cond(
|
||||
color_mode == DEFAULT_COLOR_MODE,
|
||||
light,
|
||||
dark,
|
||||
)
|
||||
|
||||
|
||||
class ColorModeIcon(Cond):
|
||||
"""Displays the current color mode as an icon."""
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
light_component: Component | None = None,
|
||||
dark_component: Component | None = None,
|
||||
):
|
||||
"""Create an icon component based on color_mode.
|
||||
|
||||
Args:
|
||||
light_component: the component to display when color mode is default
|
||||
dark_component: the component to display when color mode is dark (non-default)
|
||||
|
||||
Returns:
|
||||
The conditionally rendered component
|
||||
"""
|
||||
return color_mode_cond(
|
||||
light=light_component or DEFAULT_LIGHT_ICON,
|
||||
dark=dark_component or DEFAULT_DARK_ICON,
|
||||
)
|
||||
|
||||
|
||||
class ColorModeSwitch(Switch):
|
||||
"""Switch for toggling chakra light / dark mode via toggle_color_mode."""
|
||||
|
||||
@classmethod
|
||||
def create(cls, *children, **props):
|
||||
"""Create a switch component bound to color_mode.
|
||||
|
||||
Args:
|
||||
*children: The children of the component.
|
||||
**props: The props to pass to the component.
|
||||
|
||||
Returns:
|
||||
The switch component.
|
||||
"""
|
||||
return Switch.create(
|
||||
*children,
|
||||
is_checked=color_mode != DEFAULT_COLOR_MODE,
|
||||
on_change=toggle_color_mode,
|
||||
**props,
|
||||
)
|
||||
|
||||
|
||||
class ColorModeButton(Button):
|
||||
"""Button for toggling chakra light / dark mode via toggle_color_mode."""
|
||||
|
||||
@classmethod
|
||||
def create(cls, *children, **props):
|
||||
"""Create a button component that calls toggle_color_mode on click.
|
||||
|
||||
Args:
|
||||
*children: The children of the component.
|
||||
**props: The props to pass to the component.
|
||||
|
||||
Returns:
|
||||
The switch component.
|
||||
"""
|
||||
return Button.create(
|
||||
*children,
|
||||
on_click=toggle_color_mode,
|
||||
**props,
|
||||
)
|
@ -7,6 +7,7 @@ from pynecone.event import EventChain
|
||||
from pynecone.utils import format
|
||||
from pynecone.vars import BaseVar, Var
|
||||
|
||||
color_mode = BaseVar(name=constants.COLOR_MODE, type_="str")
|
||||
toggle_color_mode = BaseVar(name=constants.TOGGLE_COLOR_MODE, type_=EventChain)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user