diff --git a/frontend/Cargo.toml b/frontend/Cargo.toml index 083c177..ceb072b 100644 --- a/frontend/Cargo.toml +++ b/frontend/Cargo.toml @@ -16,7 +16,8 @@ serde = { workspace = true } wasm-bindgen-futures = "0.4.70" web-sys = { version = "0.3.95", features = [ "Window","Document","Request","Response","Headers", "HtmlSelectElement", "RequestCredentials", - "SubmitEvent","InputEvent","HtmlInputElement","Event", "HtmlFormElement", "MouseEvent" + "SubmitEvent","InputEvent","HtmlInputElement","Event", "HtmlFormElement", "MouseEvent", + "Element", "MediaQueryList", "DomTokenList" ] } gloo-net = "0.7.0" gloo-storage = "0.4.0" diff --git a/frontend/src/dark_mode.rs b/frontend/src/dark_mode.rs new file mode 100644 index 0000000..6e16770 --- /dev/null +++ b/frontend/src/dark_mode.rs @@ -0,0 +1,65 @@ +use gloo_storage::{LocalStorage, Storage}; +use web_sys::window; +use yew::prelude::*; + +#[function_component(DarkModeToggle)] +pub fn dark_mode_toggle() -> Html { + // 1. Initialize state from LocalStorage or system preference + let is_dark = use_state(|| { + LocalStorage::get::("dark-mode").unwrap_or_else(|_| { + // Fallback to system preference if not set + window() + .and_then(|w| w.match_media("(prefers-color-scheme: dark)").ok().flatten()) + .map(|m| m.matches()) + .unwrap_or(false) + }) + }); + + // 2. Synchronize the class on the body when the state changes + { + let is_dark = is_dark.clone(); + use_effect_with(is_dark, |is_dark| { + if let Some(win) = window() { + if let Some(doc) = win.document() { + if let Some(body) = doc.body() { + if **is_dark { + let _ = body.class_list().add_1("theme-dark"); + let _ = body.class_list().remove_1("theme-light"); + let _ = LocalStorage::set("dark-mode", true); + } else { + let _ = body.class_list().add_1("theme-light"); + let _ = body.class_list().remove_1("theme-dark"); + let _ = LocalStorage::set("dark-mode", false); + } + } + } + } + || () + }); + } + + // 3. Toggle action + let onclick = { + let is_dark = is_dark.clone(); + Callback::from(move |_| { + is_dark.set(!*is_dark); + }) + }; + + html! { + + } +} diff --git a/frontend/src/lib.rs b/frontend/src/lib.rs index 94bdc4c..f3c243f 100644 --- a/frontend/src/lib.rs +++ b/frontend/src/lib.rs @@ -1,5 +1,6 @@ mod auth; mod pages; +mod dark_mode; use crate::auth::ProtectedRoute; use crate::pages::*; use gloo_net::http::Request; @@ -271,6 +272,7 @@ fn switch(route: Route) -> Html { pub fn app() -> Html { html! { + render={switch} /> } diff --git a/frontend/src/pages/sidebar.rs b/frontend/src/pages/sidebar.rs index 4034cde..187804c 100644 --- a/frontend/src/pages/sidebar.rs +++ b/frontend/src/pages/sidebar.rs @@ -386,7 +386,12 @@ pub fn sidebar() -> Html {