dioxus_bootstrap_css/
theme.rs1use dioxus::prelude::*;
2
3use crate::types::Color;
4
5#[derive(Clone, Copy, Debug, Default, PartialEq)]
7pub enum Theme {
8 #[default]
9 Light,
10 Dark,
11}
12
13impl Theme {
14 pub fn toggle(self) -> Self {
16 match self {
17 Theme::Light => Theme::Dark,
18 Theme::Dark => Theme::Light,
19 }
20 }
21
22 pub fn as_str(&self) -> &'static str {
24 match self {
25 Theme::Light => "light",
26 Theme::Dark => "dark",
27 }
28 }
29}
30
31impl std::fmt::Display for Theme {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 write!(f, "{}", self.as_str())
34 }
35}
36
37#[derive(Clone, PartialEq, Props)]
51pub struct ThemeProviderProps {
52 pub theme: Signal<Theme>,
54}
55
56#[component]
57pub fn ThemeProvider(props: ThemeProviderProps) -> Element {
58 let theme = *props.theme.read();
59 let theme_str = theme.as_str();
60
61 rsx! {
63 document::Script { "document.documentElement.setAttribute('data-bs-theme', '{theme_str}');" }
64 }
65}
66
67#[derive(Clone, PartialEq, Props)]
77pub struct ThemeToggleProps {
78 pub theme: Signal<Theme>,
80 #[props(default)]
82 pub color: Option<Color>,
83 #[props(default)]
85 pub class: String,
86}
87
88#[component]
89pub fn ThemeToggle(props: ThemeToggleProps) -> Element {
90 let theme = *props.theme.read();
91 let mut theme_signal = props.theme;
92
93 let icon = match theme {
94 Theme::Light => "moon-stars",
95 Theme::Dark => "sun",
96 };
97
98 let label = match theme {
99 Theme::Light => "Switch to dark mode",
100 Theme::Dark => "Switch to light mode",
101 };
102
103 let btn_class = match &props.color {
104 Some(c) => format!("btn btn-outline-{c}"),
105 None => "btn btn-outline-secondary".to_string(),
106 };
107
108 let full_class = if props.class.is_empty() {
109 btn_class
110 } else {
111 format!("{btn_class} {}", props.class)
112 };
113
114 rsx! {
115 button {
116 class: "{full_class}",
117 r#type: "button",
118 title: "{label}",
119 "aria-label": "{label}",
120 onclick: move |_| {
121 let new_theme = theme.toggle();
122 theme_signal.set(new_theme);
123 },
124 i { class: "bi bi-{icon}" }
125 }
126 }
127}