From 32a1d68352dff99b3fa03a2a3981f8d42f300d95 Mon Sep 17 00:00:00 2001 From: lukasmatusiewicz Date: Thu, 23 Apr 2026 11:05:35 +0200 Subject: [PATCH] feat: implement dark mode support with theme toggle and persistence --- README.md | 1 + src/main/resources/static/styles.css | 29 +++++++++++++++++++-- src/main/resources/templates/dashboard.html | 26 ++++++++++++++++++ src/main/resources/templates/edit-task.html | 27 +++++++++++++++++++ src/main/resources/templates/login.html | 5 ++++ src/main/resources/templates/register.html | 5 ++++ src/main/resources/templates/tasks.html | 26 ++++++++++++++++++ 7 files changed, 117 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1d0c5e1..ca4d5ab 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ To run the tests locally, use: ## ✨ Key Features * **Interactive Dashboard**: Real-time summary of pending, overdue, and recently completed tasks with visual charts. +* **Dark Mode Support**: Full dark theme support with persistence across sessions using `localStorage`. * **Full CRUD Cycle**: Create, Read, Update, and Delete tasks. * **Due Date Tracking**: Set deadlines for tasks and track overdue items. * **Quick Status Toggle**: Instantly mark tasks as Done or Undone from the main list view. diff --git a/src/main/resources/static/styles.css b/src/main/resources/static/styles.css index 71496b4..a80b889 100644 --- a/src/main/resources/static/styles.css +++ b/src/main/resources/static/styles.css @@ -1,17 +1,30 @@ /* Custom Task Manager Styles */ +:root { + --task-card-bg: #ffffff; + --task-card-text: #212529; +} + +[data-bs-theme="dark"] { + --task-card-bg: #2b3035; + --task-card-text: #dee2e6; +} + body { - background-color: #f8f9fa; + background-color: var(--bs-body-bg); + color: var(--bs-body-color); } /* Task Card Hover Effects */ .task-card { transition: transform 0.2s, box-shadow 0.2s; + background-color: var(--task-card-bg); + color: var(--task-card-text); } .task-card:hover { transform: translateY(-3px); - box-shadow: 0 4px 15px rgba(0,0,0,0.1); + box-shadow: 0 4px 15px rgba(0,0,0,0.3); } /* Priority Indicator Borders */ @@ -44,3 +57,15 @@ body.auth-page { align-items: center; min-height: 100vh; } + +/* Dark Mode Toggle Button Positioning */ +.theme-toggle { + cursor: pointer; + padding: 5px 10px; + border-radius: 20px; + transition: background-color 0.3s; +} + +.theme-toggle:hover { + background-color: rgba(255, 255, 255, 0.1); +} diff --git a/src/main/resources/templates/dashboard.html b/src/main/resources/templates/dashboard.html index 443235f..c546790 100644 --- a/src/main/resources/templates/dashboard.html +++ b/src/main/resources/templates/dashboard.html @@ -29,6 +29,9 @@
+
@@ -174,6 +177,29 @@
Tasks by Priority
ctxPriority.fillText("No priority data available", 150, 150); } /*]]>*/ + + // Theme Management + const themeToggle = document.getElementById('themeToggle'); + const themeIcon = document.getElementById('themeIcon'); + const htmlElement = document.documentElement; + + // Load saved theme + const savedTheme = localStorage.getItem('theme') || 'light'; + htmlElement.setAttribute('data-bs-theme', savedTheme); + updateIcon(savedTheme); + + themeToggle.addEventListener('click', () => { + const currentTheme = htmlElement.getAttribute('data-bs-theme'); + const newTheme = currentTheme === 'dark' ? 'light' : 'dark'; + + htmlElement.setAttribute('data-bs-theme', newTheme); + localStorage.setItem('theme', newTheme); + updateIcon(newTheme); + }); + + function updateIcon(theme) { + themeIcon.textContent = theme === 'dark' ? '☀️' : '🌙'; + } diff --git a/src/main/resources/templates/edit-task.html b/src/main/resources/templates/edit-task.html index 07299cf..93a1f95 100644 --- a/src/main/resources/templates/edit-task.html +++ b/src/main/resources/templates/edit-task.html @@ -14,6 +14,9 @@ @@ -60,5 +63,29 @@

Edit Task

+ diff --git a/src/main/resources/templates/login.html b/src/main/resources/templates/login.html index c791856..da739ee 100644 --- a/src/main/resources/templates/login.html +++ b/src/main/resources/templates/login.html @@ -45,5 +45,10 @@

Task Manager Login

+ diff --git a/src/main/resources/templates/register.html b/src/main/resources/templates/register.html index a89e5e9..8d18c8e 100644 --- a/src/main/resources/templates/register.html +++ b/src/main/resources/templates/register.html @@ -43,5 +43,10 @@

Create Account

+ diff --git a/src/main/resources/templates/tasks.html b/src/main/resources/templates/tasks.html index 6f8dc7e..b6c387a 100644 --- a/src/main/resources/templates/tasks.html +++ b/src/main/resources/templates/tasks.html @@ -30,6 +30,9 @@
+ @@ -178,6 +181,29 @@

Add New Task

alert('An error occurred while deleting the task.'); } } + + // Theme Management + const themeToggle = document.getElementById('themeToggle'); + const themeIcon = document.getElementById('themeIcon'); + const htmlElement = document.documentElement; + + // Load saved theme + const savedTheme = localStorage.getItem('theme') || 'light'; + htmlElement.setAttribute('data-bs-theme', savedTheme); + updateIcon(savedTheme); + + themeToggle.addEventListener('click', () => { + const currentTheme = htmlElement.getAttribute('data-bs-theme'); + const newTheme = currentTheme === 'dark' ? 'light' : 'dark'; + + htmlElement.setAttribute('data-bs-theme', newTheme); + localStorage.setItem('theme', newTheme); + updateIcon(newTheme); + }); + + function updateIcon(theme) { + themeIcon.textContent = theme === 'dark' ? '☀️' : '🌙'; + } \ No newline at end of file