3 Commits

3 changed files with 99 additions and 5 deletions

View File

@@ -1,6 +1,64 @@
// ============ STATE ============ // ============ THEME ============
const CURRENT_PAGE = document.body?.dataset?.page || 'tasks'; const THEME_STORAGE_KEY = 'agentdash-theme';
const themeToggleBtn = document.getElementById('theme-toggle');
const systemThemeMedia = window.matchMedia('(prefers-color-scheme: dark)');
function getSystemTheme() {
return systemThemeMedia.matches ? 'dark' : 'light';
}
function getSavedTheme() {
try {
const saved = localStorage.getItem(THEME_STORAGE_KEY);
return saved === 'light' || saved === 'dark' ? saved : null;
} catch {
return null;
}
}
function setSavedTheme(theme) {
try {
localStorage.setItem(THEME_STORAGE_KEY, theme);
} catch {
// Ignore localStorage errors (privacy mode, quota, etc.).
}
}
function updateThemeToggleLabel() {
if (!themeToggleBtn) return;
const isDarkTheme = document.documentElement.getAttribute('data-theme') === 'dark';
const nextTheme = isDarkTheme ? 'light' : 'dark';
themeToggleBtn.textContent = isDarkTheme ? 'Light Mode' : 'Dark Mode';
themeToggleBtn.setAttribute('aria-label', `Switch to ${nextTheme} mode`);
}
function applyTheme(theme, { persist = false } = {}) {
document.documentElement.setAttribute('data-theme', theme);
if (persist) setSavedTheme(theme);
updateThemeToggleLabel();
if (usageStats) renderUsageCharts();
}
function initTheme() {
const savedTheme = getSavedTheme();
applyTheme(savedTheme || getSystemTheme());
if (themeToggleBtn) {
themeToggleBtn.addEventListener('click', () => {
const currentTheme = document.documentElement.getAttribute('data-theme') || getSystemTheme();
const nextTheme = currentTheme === 'dark' ? 'light' : 'dark';
applyTheme(nextTheme, { persist: true });
});
}
systemThemeMedia.addEventListener('change', (event) => {
if (!getSavedTheme()) {
applyTheme(event.matches ? 'dark' : 'light');
}
});
}
// ============ STATE ============
const COLUMNS = { const COLUMNS = {
Backlog: { title: '📋 Backlog', tasks: [] }, Backlog: { title: '📋 Backlog', tasks: [] },
Todo: { title: '📝 Todo', tasks: [] }, Todo: { title: '📝 Todo', tasks: [] },
@@ -752,6 +810,7 @@ function setupModalBackdropClose() {
// ============ INITIALIZATION ============ // ============ INITIALIZATION ============
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
initTheme();
setupModalBackdropClose(); setupModalBackdropClose();
if (CURRENT_PAGE === 'tasks') initTasksPage(); if (CURRENT_PAGE === 'tasks') initTasksPage();

View File

@@ -19,6 +19,7 @@
<a href="#wiki" class="nav-link" data-page="wiki">Wiki</a> <a href="#wiki" class="nav-link" data-page="wiki">Wiki</a>
<a href="#agents" class="nav-link" data-page="agents">Agents</a> <a href="#agents" class="nav-link" data-page="agents">Agents</a>
<a href="#usage" class="nav-link" data-page="usage">Usage</a> <a href="#usage" class="nav-link" data-page="usage">Usage</a>
<button id="theme-toggle" class="btn-secondary" type="button" aria-label="Toggle theme">Dark Mode</button>
</nav> </nav>
</header> </header>

View File

@@ -1,11 +1,22 @@
:root { :root {
--bg: #1a1a1a; --bg: #f5f7fb;
--fg: #e0e0e0; --fg: #1f2937;
--border: #444; --border: #c8d1df;
--primary: #3498db; --primary: #3498db;
--secondary: #2ecc71; --secondary: #2ecc71;
--danger: #e74c3c; --danger: #e74c3c;
--warning: #f39c12; --warning: #f39c12;
--dark: #1f2937;
--light: #f8fafc;
--card-bg: #ffffff;
--card-fg: #111827;
--modal-bg: rgba(0, 0, 0, 0.45);
}
:root[data-theme='dark'] {
--bg: #1a1a1a;
--fg: #e0e0e0;
--border: #444;
--dark: #121212; --dark: #121212;
--light: #f0f0f0; --light: #f0f0f0;
--card-bg: #2a2a2a; --card-bg: #2a2a2a;
@@ -13,6 +24,19 @@
--modal-bg: rgba(0, 0, 0, 0.7); --modal-bg: rgba(0, 0, 0, 0.7);
} }
@media (prefers-color-scheme: dark) {
:root:not([data-theme='light']) {
--bg: #1a1a1a;
--fg: #e0e0e0;
--border: #444;
--dark: #121212;
--light: #f0f0f0;
--card-bg: #2a2a2a;
--card-fg: #e0e0e0;
--modal-bg: rgba(0, 0, 0, 0.7);
}
}
* { * {
margin: 0; margin: 0;
padding: 0; padding: 0;
@@ -24,6 +48,11 @@ body {
background-color: var(--bg); background-color: var(--bg);
color: var(--fg); color: var(--fg);
line-height: 1.6; line-height: 1.6;
transition: background-color 0.3s ease, color 0.3s ease;
}
body * {
transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
} }
.container { .container {
@@ -48,6 +77,7 @@ header h1 {
nav { nav {
display: flex; display: flex;
gap: 15px; gap: 15px;
align-items: center;
} }
.nav-link { .nav-link {
@@ -67,6 +97,10 @@ nav {
color: white; color: white;
} }
#theme-toggle {
margin-left: auto;
}
/* Buttons */ /* Buttons */
.btn-primary { .btn-primary {
background-color: var(--primary); background-color: var(--primary);