Skip to main content

dioxus_docs_kit/components/blog/
theme_toggle.rs

1use dioxus::prelude::*;
2use dioxus_free_icons::Icon;
3use dioxus_free_icons::icons::ld_icons::{LdMoon, LdSun};
4
5use crate::blog::registry::BlogRegistry;
6use crate::components::docs_layout::CurrentTheme;
7
8/// Light/dark theme toggle for blog layouts.
9#[component]
10pub fn BlogThemeToggle() -> Element {
11    let registry = use_context::<&'static BlogRegistry>();
12
13    let toggle = match registry
14        .theme
15        .as_ref()
16        .and_then(|t| t.toggle_themes.as_ref())
17    {
18        Some(t) => t.clone(),
19        None => return rsx! {},
20    };
21
22    let storage_key = registry
23        .theme
24        .as_ref()
25        .map(|t| t.storage_key.clone())
26        .unwrap_or_default();
27
28    let CurrentTheme(mut current_theme) = use_context::<CurrentTheme>();
29
30    let (light, dark) = toggle;
31    let is_dark = current_theme() == dark;
32
33    rsx! {
34        button {
35            class: "btn btn-ghost btn-sm btn-square",
36            title: if is_dark { "Switch to light mode" } else { "Switch to dark mode" },
37            onclick: move |_| {
38                let new_theme = if (current_theme)() == dark { light.clone() } else { dark.clone() };
39                current_theme.set(new_theme.clone());
40                let key = storage_key.clone();
41                spawn(async move {
42                    let _ = document::eval(&format!(
43                        r#"document.documentElement.setAttribute('data-theme', '{new_theme}');
44                        try {{ localStorage.setItem('{key}', '{new_theme}'); }} catch(e) {{}}"#
45                    ));
46                });
47            },
48            if is_dark {
49                Icon { class: "size-5", icon: LdSun }
50            } else {
51                Icon { class: "size-5", icon: LdMoon }
52            }
53        }
54    }
55}