From b41c1ade440c75ca91c4592d779f5877e306f6f8 Mon Sep 17 00:00:00 2001 From: agentbox Date: Sat, 1 Aug 2026 13:19:19 +0000 Subject: [PATCH] feat: dark mode toggle for the web UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CSS variables for dark theme: surface, text, borders, accents - Dark mode overrides for all hardcoded colors (buttons, tags, flashes, inputs, table headers, code blocks) - Toggle button (☀️/🌙) in navbar, saved to localStorage - Inline script applies saved theme before page render (no flash) - Applied to both base.html and public.html - System color-scheme meta tag for native browser chrome --- static/style.css | 109 ++++++++++++++++++++++++++++++++++++++++++ templates/base.html | 30 +++++++++++- templates/public.html | 31 +++++++++++- 3 files changed, 167 insertions(+), 3 deletions(-) diff --git a/static/style.css b/static/style.css index 0169e2d..7447edc 100644 --- a/static/style.css +++ b/static/style.css @@ -15,9 +15,28 @@ --orange-bg: #fff3e0; --gray-bg: #f0f0f0; --primary: #1565c0; + --primary-bg: #e3f2fd; --radius: 8px; } +/* ── Dark mode ── */ +[data-theme="dark"] { + --bg: #1a1a2e; + --surface: #16213e; + --text: #e0e0e0; + --muted: #999; + --border: #2a2a4a; + --green: #66bb6a; + --green-bg: #1b3a1b; + --red: #ef5350; + --red-bg: #3a1b1b; + --orange: #ff9800; + --orange-bg: #3a2e1b; + --gray-bg: #2a2a3a; + --primary: #64b5f6; + --primary-bg: #1a2a3a; +} + body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: var(--bg); @@ -358,3 +377,93 @@ body { width: auto; } } + +/* ── Dark mode overrides for non-variable colors ── */ +[data-theme="dark"] body { + color-scheme: dark; +} +[data-theme="dark"] .btn:hover { + background: #2a2a4a; +} +[data-theme="dark"] .btn-primary { + color: #1a1a2e; +} +[data-theme="dark"] .btn-primary:hover { + background: #42a5f5; +} +[data-theme="dark"] .btn-danger:hover { + background: #d32f2f; +} +[data-theme="dark"] .nav-household { + background: var(--primary-bg); + color: var(--primary); +} +[data-theme="dark"] .you-tag { + background: var(--primary-bg); +} +[data-theme="dark"] .chip-yes.active { + color: #1a1a2e; +} +[data-theme="dark"] .chip-no.active { + color: #1a1a2e; +} +[data-theme="dark"] .badge-yes, +[data-theme="dark"] .badge-no { + color: #1a1a2e; +} +[data-theme="dark"] .meal-table th { + background: #1a1a30; +} +[data-theme="dark"] .public-url-box { + background: #1a1a30; +} +[data-theme="dark"] .lang-link:hover { + background: #2a2a4a; + color: var(--text); +} +[data-theme="dark"] .lang-active { + color: #1a1a2e; +} +[data-theme="dark"] .lang-active:hover { + background: #42a5f5; + color: #1a1a2e; +} +[data-theme="dark"] .flash-error { + background: #3a1b1b; + color: #ef5350; + border-color: #5a2a2a; +} +[data-theme="dark"] .flash-success { + background: #1b3a1b; + color: #66bb6a; + border-color: #2a5a2a; +} +[data-theme="dark"] input, +[data-theme="dark"] select, +[data-theme="dark"] textarea { + background: #1a1a30; + color: var(--text); + border-color: var(--border); +} +[data-theme="dark"] input::placeholder { + color: #666; +} +[data-theme="dark"] .manage-form { + border-color: var(--border); +} + +/* ── Dark mode toggle button ── */ +.theme-toggle { + background: none; + border: 1px solid var(--border); + border-radius: 20px; + cursor: pointer; + font-size: 1rem; + padding: 4px 10px; + line-height: 1; + color: var(--text); + transition: background 0.15s; +} +.theme-toggle:hover { + background: var(--gray-bg); +} diff --git a/templates/base.html b/templates/base.html index 7f35376..bbd1960 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,16 +1,25 @@ - + + {% block title %}{{ t('Meal Tracker') }}{% endblock %} +