From eb3f7b94b2bdac534539fb5424be2d07cd117a2d Mon Sep 17 00:00:00 2001 From: rene Date: Sat, 18 Apr 2026 18:40:34 +0200 Subject: [PATCH] =?UTF-8?q?Feature:=20Dark=20Mode=20=E2=80=94=20System/Hel?= =?UTF-8?q?l/Dunkel-Toggle=20in=20Einstellungen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CSS-Variablen für Dark Mode in design-system.css (system + manuell via data-theme), Flash-freies Inline-Script in index.html, Toggle in settings.js (by_theme in localStorage). SW by-v210, APP_VER 179. --- backend/static/css/design-system.css | 69 ++++++++++++++++++++++++---- backend/static/index.html | 4 ++ backend/static/js/app.js | 9 ++-- backend/static/js/pages/settings.js | 44 ++++++++++++++++++ 4 files changed, 112 insertions(+), 14 deletions(-) diff --git a/backend/static/css/design-system.css b/backend/static/css/design-system.css index 15f8df2..dc1a0b2 100644 --- a/backend/static/css/design-system.css +++ b/backend/static/css/design-system.css @@ -115,21 +115,70 @@ --safe-right: env(safe-area-inset-right, 0px); } -/* Dark Mode — vorbereitet, nicht aktiv */ +/* Dark Mode — System-Präferenz (nur wenn kein manuelles Theme gesetzt) */ @media (prefers-color-scheme: dark) { - :root { - --c-bg: #1A1410; - --c-surface: #241C14; - --c-surface-2: #2E2418; - --c-surface-3: #3A2E20; - --c-border: #4A3C2C; - --c-border-light: #3A2E20; - --c-text: #F0EAE0; + :root:not([data-theme="light"]):not([data-theme="dark"]) { + --c-bg: #1A1410; + --c-surface: #241C14; + --c-surface-2: #2E2418; + --c-surface-3: #3A2E20; + --c-border: #4A3C2C; + --c-border-light: #3A2E20; + + --c-primary-subtle: #2A1C0A; + --c-primary-soft: #2E1E08; + + --c-nature-subtle: #1A2214; + --c-sky-subtle: #141C22; + --c-danger-subtle: #2A100A; + --c-success-subtle: #122010; + --c-warning-subtle: #261A08; + --c-info-subtle: #10182A; + + --c-text: #F0EAE0; --c-text-secondary: #C0B0A0; - --c-text-muted: #806A58; + --c-text-muted: #806A58; + --c-text-inverse: #2A1F14; + + --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.30); + --shadow-sm: 0 1px 4px rgba(0, 0, 0, 0.35), 0 1px 2px rgba(0, 0, 0, 0.25); + --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.40), 0 2px 4px rgba(0, 0, 0, 0.25); + --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.45), 0 4px 8px rgba(0, 0, 0, 0.30); + --shadow-xl: 0 16px 40px rgba(0, 0, 0, 0.50), 0 8px 16px rgba(0, 0, 0, 0.35); } } +/* Manuelles Dark-Theme via data-theme="dark" (überschreibt auch prefers-color-scheme: light) */ +:root[data-theme="dark"] { + --c-bg: #1A1410; + --c-surface: #241C14; + --c-surface-2: #2E2418; + --c-surface-3: #3A2E20; + --c-border: #4A3C2C; + --c-border-light: #3A2E20; + + --c-primary-subtle: #2A1C0A; + --c-primary-soft: #2E1E08; + + --c-nature-subtle: #1A2214; + --c-sky-subtle: #141C22; + --c-danger-subtle: #2A100A; + --c-success-subtle: #122010; + --c-warning-subtle: #261A08; + --c-info-subtle: #10182A; + + --c-text: #F0EAE0; + --c-text-secondary: #C0B0A0; + --c-text-muted: #806A58; + --c-text-inverse: #2A1F14; + + --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.30); + --shadow-sm: 0 1px 4px rgba(0, 0, 0, 0.35), 0 1px 2px rgba(0, 0, 0, 0.25); + --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.40), 0 2px 4px rgba(0, 0, 0, 0.25); + --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.45), 0 4px 8px rgba(0, 0, 0, 0.30); + --shadow-xl: 0 16px 40px rgba(0, 0, 0, 0.50), 0 8px 16px rgba(0, 0, 0, 0.35); +} + /* ------------------------------------------------------------ 2. RESET & BASE ------------------------------------------------------------ */ diff --git a/backend/static/index.html b/backend/static/index.html index f46531d..a02751d 100644 --- a/backend/static/index.html +++ b/backend/static/index.html @@ -170,6 +170,10 @@
+
+
+
+
diff --git a/backend/static/js/app.js b/backend/static/js/app.js index e36649b..8ec5eb4 100644 --- a/backend/static/js/app.js +++ b/backend/static/js/app.js @@ -3,7 +3,7 @@ Router, State-Management, Navigation, Initialisierung. ============================================================ */ -const APP_VER = '175'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '179'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const App = (() => { @@ -33,6 +33,7 @@ const App = (() => { // ---------------------------------------------------------- const pages = { welcome: { title: 'Willkommen', module: null }, + onboarding: { title: 'Einrichtung', module: null, requiresAuth: true }, diary: { title: 'Tagebuch', module: null, requiresAuth: true }, health: { title: 'Gesundheit', module: null, requiresAuth: true }, 'dog-profile': { title: 'Mein Hund', module: null, requiresAuth: true }, @@ -413,9 +414,9 @@ const App = (() => { } await _loadDogs(); - // Eingeloggter User ohne Hund (z.B. nach Reload) → direkt zur Hund-Anlage - if (state.dogs.length === 0) { - navigate('dog-profile'); + // Eingeloggter User ohne Hund → Onboarding-Wizard (einmalig) + if (state.dogs.length === 0 && !localStorage.getItem('by_onboarding_done')) { + navigate('onboarding'); } _updateNotifBadge(); diff --git a/backend/static/js/pages/settings.js b/backend/static/js/pages/settings.js index 8478bca..6aeb9d9 100644 --- a/backend/static/js/pages/settings.js +++ b/backend/static/js/pages/settings.js @@ -182,6 +182,32 @@ window.Page_settings = (() => { App-Einstellungen
+ + +
+ +
+
Dark Mode
+
+ Erscheinungsbild der App +
+
+ +
+
@@ -420,6 +446,24 @@ window.Page_settings = (() => { } }); + document.getElementById('select-theme')?.addEventListener('change', e => { + const val = e.target.value; + localStorage.setItem('by_theme', val); + const html = document.documentElement; + if (val === 'dark') { + html.setAttribute('data-theme', 'dark'); + } else if (val === 'light') { + html.setAttribute('data-theme', 'light'); + } else { + html.removeAttribute('data-theme'); + } + UI.toast.info( + val === 'dark' ? 'Dark Mode aktiviert.' : + val === 'light' ? 'Hell-Modus aktiviert.' : + 'Theme folgt der Systemeinstellung.' + ); + }); + document.getElementById('toggle-pocket-mode')?.addEventListener('change', e => { localStorage.setItem('by_pocket_mode', String(e.target.checked)); UI.toast.info(e.target.checked