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:
|
def index() -> pc.Component:
|
||||||
return pc.center(
|
return pc.fragment(
|
||||||
|
pc.color_mode_button(pc.color_mode_icon(), float="right"),
|
||||||
pc.vstack(
|
pc.vstack(
|
||||||
pc.heading("Welcome to Pynecone!", font_size="2em"),
|
pc.heading("Welcome to Pynecone!", font_size="2em"),
|
||||||
pc.box("Get started by editing ", pc.code(filename, font_size="1em")),
|
pc.box("Get started by editing ", pc.code(filename, font_size="1em")),
|
||||||
@ -25,13 +26,16 @@ def index() -> pc.Component:
|
|||||||
padding="0.5em",
|
padding="0.5em",
|
||||||
border_radius="0.5em",
|
border_radius="0.5em",
|
||||||
_hover={
|
_hover={
|
||||||
"color": "rgb(107,99,246)",
|
"color": pc.color_mode_cond(
|
||||||
|
light="rgb(107,99,246)",
|
||||||
|
dark="rgb(179, 175, 255)",
|
||||||
|
)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
spacing="1.5em",
|
spacing="1.5em",
|
||||||
font_size="2em",
|
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 .route import route as route
|
||||||
from .state import ComputedVar as var
|
from .state import ComputedVar as var
|
||||||
from .state import State as State
|
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 .style import toggle_color_mode as toggle_color_mode
|
||||||
from .vars import Var as Var
|
from .vars import Var as Var
|
||||||
from .vars import cached_var as cached_var
|
from .vars import cached_var as cached_var
|
||||||
|
@ -238,3 +238,6 @@ text = Text.create
|
|||||||
script = ScriptTag.create
|
script = ScriptTag.create
|
||||||
aspect_ratio = AspectRatio.create
|
aspect_ratio = AspectRatio.create
|
||||||
kbd = KeyboardKey.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 .button import Button, ButtonGroup
|
||||||
from .checkbox import Checkbox, CheckboxGroup
|
from .checkbox import Checkbox, CheckboxGroup
|
||||||
|
from .colormodeswitch import (
|
||||||
|
ColorModeButton,
|
||||||
|
ColorModeIcon,
|
||||||
|
ColorModeSwitch,
|
||||||
|
color_mode_cond,
|
||||||
|
)
|
||||||
from .copytoclipboard import CopyToClipboard
|
from .copytoclipboard import CopyToClipboard
|
||||||
from .date_picker import DatePicker
|
from .date_picker import DatePicker
|
||||||
from .date_time_picker import DateTimePicker
|
from .date_time_picker import DateTimePicker
|
||||||
@ -34,4 +40,8 @@ from .switch import Switch
|
|||||||
from .textarea import TextArea
|
from .textarea import TextArea
|
||||||
from .upload import Upload
|
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.utils import format
|
||||||
from pynecone.vars import BaseVar, Var
|
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)
|
toggle_color_mode = BaseVar(name=constants.TOGGLE_COLOR_MODE, type_=EventChain)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user