From b9354f77b6fca6b3ce1e65e788c55b0df013949c Mon Sep 17 00:00:00 2001 From: schn33fuchs Date: Thu, 28 May 2026 17:26:56 +0200 Subject: [PATCH 1/2] Darkmode implemented There is now a darkmode button --- frontend/Cargo.toml | 3 +- frontend/src/dark_mode.rs | 65 ++++++++++++++++ frontend/src/lib.rs | 2 + frontend/src/styles/_variables.scss | 12 +-- .../src/styles/components/_dark_mode.scss | 75 +++++++++++++++++++ frontend/src/styles/main.scss | 1 + 6 files changed, 151 insertions(+), 7 deletions(-) create mode 100644 frontend/src/dark_mode.rs create mode 100644 frontend/src/styles/components/_dark_mode.scss 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/styles/_variables.scss b/frontend/src/styles/_variables.scss index 6fa9c07..f07e0a1 100644 --- a/frontend/src/styles/_variables.scss +++ b/frontend/src/styles/_variables.scss @@ -1,15 +1,15 @@ // Color Palette (Reference Style) -$color-bg: #f0f2f5; -$color-bg-dark: #121212; -$color-container: #ffffff; -$color-container-dark: #333333; +$color-bg: var(--color-bg); +$color-bg-dark: var(--color-bg-dark); +$color-container: var(--color-container); +$color-container-dark: var(--color-container-dark); $color-sidebar: #0f172a; $color-primary: #2b79c2; $color-primary-hover: #1d5fa0; $color-accent: #2b79c2; $color-muted: #6b7280; -$color-text: #111827; -$color-text-dark: #e2e2e2; +$color-text: var(--color-text); +$color-text-dark: var(--color-text-dark); // Status Colors $color-status-todo: #ffcccc; diff --git a/frontend/src/styles/components/_dark_mode.scss b/frontend/src/styles/components/_dark_mode.scss new file mode 100644 index 0000000..f4dd395 --- /dev/null +++ b/frontend/src/styles/components/_dark_mode.scss @@ -0,0 +1,75 @@ +:root { + --color-bg: #f0f2f5; + --color-bg-dark: #121212; + --color-container: #ffffff; + --color-container-dark: #333333; + --color-text: #111827; + --color-text-dark: #e2e2e2; +} + +// Automatically respect standard media query if no override is set +@media (prefers-color-scheme: dark) { + :root { + --color-bg: #121212; + --color-container: #333333; + --color-text: #e2e2e2; + } +} + +// Force Light Mode overrides +body.theme-light { + --color-bg: #f0f2f5; + --color-bg-dark: #f0f2f5; + --color-container: #ffffff; + --color-container-dark: #ffffff; + --color-text: #111827; + --color-text-dark: #111827; +} + +// Force Dark Mode overrides +body.theme-dark { + --color-bg: #121212; + --color-bg-dark: #121212; + --color-container: #333333; + --color-container-dark: #333333; + --color-text: #e2e2e2; + --color-text-dark: #e2e2e2; +} + +// Fixed positioning ensures NO other component's layout is ever altered +.dark-mode-toggle { + position: fixed; + top: 1rem; + right: 1rem; + z-index: 9999; + width: 55px; + height: 55px; + border-radius: 50%; + border: 1px solid rgba(128, 128, 128, 0.2); + background-color: var(--color-container); + color: var(--color-text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + cursor: pointer; + transition: all 0.2s ease-in-out; + display: flex; + align-items: center; + justify-content: center; + padding: 0; + + svg { + width: 36px; + height: 36px; + stroke: var(--color-text); + transition: stroke 0.2s ease-in-out; + } + + &:hover { + transform: translateY(-1px); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15); + background-color: var(--color-bg); + } + + &:active { + transform: translateY(0); + } +} diff --git a/frontend/src/styles/main.scss b/frontend/src/styles/main.scss index aad6604..886a19f 100644 --- a/frontend/src/styles/main.scss +++ b/frontend/src/styles/main.scss @@ -10,6 +10,7 @@ @use "components/diagnostics"; @use "components/pages"; @use "components/setup"; +@use "components/dark_mode"; * { box-sizing: border-box; -- 2.49.1 From 778c112dd40d3499bcbb79420e9a8a0e4f5662d0 Mon Sep 17 00:00:00 2001 From: schn33fuchs Date: Thu, 28 May 2026 17:27:36 +0200 Subject: [PATCH 2/2] Home button fixed It is now an icon in the middle of the button instead of a unicode number --- frontend/src/pages/sidebar.rs | 14 ++++++++++++-- frontend/src/styles/components/_sidebar.scss | 12 ++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) 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 {