From de204ea68c0063575e160997730935ce64369fec Mon Sep 17 00:00:00 2001 From: matteoscrugli Date: Mon, 8 Dec 2025 22:52:09 +0100 Subject: [PATCH] Add dark theme + auto accent color overrides MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use off-white backgrounds with dark text for active/selected elements when using dark theme with 'auto' accent color: - Tab buttons (active state) - Sidebar nav items (active state) - Primary buttons - Toggle switches - Badges, checkboxes, input focus states - Theme settings cards and options 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- frontend/src/contexts/ThemeContext.tsx | 5 ++ frontend/src/styles/AdminPanel.css | 97 +++++++++++++++++++++ frontend/src/styles/Layout.css | 17 ++++ frontend/src/styles/Sidebar.css | 14 +++ frontend/src/styles/ThemeSettings.css | 113 +++++++++++++++++++++++++ frontend/src/styles/theme/index.css | 22 +++++ 6 files changed, 268 insertions(+) diff --git a/frontend/src/contexts/ThemeContext.tsx b/frontend/src/contexts/ThemeContext.tsx index c97656a..931c39b 100644 --- a/frontend/src/contexts/ThemeContext.tsx +++ b/frontend/src/contexts/ThemeContext.tsx @@ -461,6 +461,11 @@ export function ThemeProvider({ children }: { children: ReactNode }) { localStorage.setItem('theme', theme); }, [theme]); + useEffect(() => { + const root = document.documentElement; + root.setAttribute('data-accent', accentColor); + }, [accentColor]); + useEffect(() => { const root = document.documentElement; const colors = ACCENT_COLORS[accentColor]; diff --git a/frontend/src/styles/AdminPanel.css b/frontend/src/styles/AdminPanel.css index 6c5e1e8..71de4e6 100644 --- a/frontend/src/styles/AdminPanel.css +++ b/frontend/src/styles/AdminPanel.css @@ -2257,4 +2257,101 @@ border: 1px solid var(--color-border); pointer-events: none; } +} + +/* ========== DARK THEME + AUTO ACCENT OVERRIDES ========== */ + +/* Primary buttons with auto accent in dark mode: use off-white background with dark text */ +[data-theme='dark'][data-accent='auto'] .btn-primary, +[data-theme='dark'][data-accent='auto'] .btn-primary-modern { + background: #e5e7eb; + color: #111827; +} + +[data-theme='dark'][data-accent='auto'] .btn-primary:hover, +[data-theme='dark'][data-accent='auto'] .btn-primary-modern:hover { + background: #f3f4f6; + color: #111827; +} + +/* Icon action buttons (edit) hover state with auto accent in dark mode */ +[data-theme='dark'][data-accent='auto'] .btn-icon-action.btn-edit:hover, +[data-theme='dark'][data-accent='auto'] .btn-icon-modern.btn-edit:hover { + background: #e5e7eb; + border-color: #e5e7eb; +} + +[data-theme='dark'][data-accent='auto'] .btn-icon-action.btn-edit:hover .material-symbols-outlined, +[data-theme='dark'][data-accent='auto'] .btn-icon-modern.btn-edit:hover .material-symbols-outlined { + color: #111827; +} + +/* Toggle switch checked state */ +[data-theme='dark'][data-accent='auto'] .toggle-modern input:checked+.toggle-slider-modern { + background: #e5e7eb; +} + +[data-theme='dark'][data-accent='auto'] .toggle-modern input:checked+.toggle-slider-modern:before { + background: #111827; +} + +/* Badge accent */ +[data-theme='dark'][data-accent='auto'] .badge-accent { + background: rgba(229, 231, 235, 0.15); + color: #e5e7eb; + border-color: rgba(229, 231, 235, 0.3); +} + +/* User avatar gradient */ +[data-theme='dark'][data-accent='auto'] .modern-table .user-avatar-modern { + background: linear-gradient(135deg, #d1d5db, #e5e7eb); + color: #111827; +} + +/* Sidebar mode option active state */ +[data-theme='dark'][data-accent='auto'] .sidebar-mode-option.active { + border-color: #e5e7eb; + background: rgba(229, 231, 235, 0.1); +} + +[data-theme='dark'][data-accent='auto'] .sidebar-mode-option.active .material-symbols-outlined, +[data-theme='dark'][data-accent='auto'] .sidebar-mode-option.active span:last-child { + color: #e5e7eb; +} + +/* Feature status badge active */ +[data-theme='dark'][data-accent='auto'] .feature-status-badge.active { + background: rgba(229, 231, 235, 0.1); + color: #e5e7eb; + border-color: rgba(229, 231, 235, 0.2); +} + +/* Focus states */ +[data-theme='dark'][data-accent='auto'] .input-group-modern:focus-within { + border-color: #e5e7eb; + box-shadow: 0 0 0 3px rgba(229, 231, 235, 0.15); +} + +[data-theme='dark'][data-accent='auto'] .form-field input:focus { + border-color: #e5e7eb; + box-shadow: 0 0 0 3px rgba(229, 231, 235, 0.1); +} + +/* Checkbox checked state in modals */ +[data-theme='dark'][data-accent='auto'] .users-modal .checkbox-row input[type="checkbox"]:checked { + background: #e5e7eb; + border-color: #e5e7eb; +} + +[data-theme='dark'][data-accent='auto'] .users-modal .checkbox-row input[type="checkbox"]:checked::after { + border-color: #111827; +} + +/* Modal toggle checked */ +[data-theme='dark'][data-accent='auto'] .users-modal .toggle-inline input:checked+.toggle-slider-sm { + background: #e5e7eb; +} + +[data-theme='dark'][data-accent='auto'] .users-modal .toggle-inline input:checked+.toggle-slider-sm::before { + background: #111827; } \ No newline at end of file diff --git a/frontend/src/styles/Layout.css b/frontend/src/styles/Layout.css index 3edf9d3..288c5a9 100644 --- a/frontend/src/styles/Layout.css +++ b/frontend/src/styles/Layout.css @@ -428,4 +428,21 @@ .tab-content-placeholder p { margin: 0; font-size: 1rem; +} + +/* ========== DARK THEME + AUTO ACCENT OVERRIDES ========== */ + +/* Tab buttons with auto accent in dark mode: use off-white background with dark text */ +[data-theme='dark'][data-accent='auto'] .page-tab-btn.active, +[data-theme='dark'][data-accent='auto'] .admin-tab-btn.active { + background: #e5e7eb; + color: #111827; + box-shadow: 0 2px 8px rgba(229, 231, 235, 0.2); +} + +[data-theme='dark'][data-accent='auto'] .page-tab-btn.active:focus, +[data-theme='dark'][data-accent='auto'] .admin-tab-btn.active:focus, +[data-theme='dark'][data-accent='auto'] .page-tab-btn.active:focus-visible, +[data-theme='dark'][data-accent='auto'] .admin-tab-btn.active:focus-visible { + box-shadow: 0 2px 8px rgba(229, 231, 235, 0.3); } \ No newline at end of file diff --git a/frontend/src/styles/Sidebar.css b/frontend/src/styles/Sidebar.css index 79be01b..724aa33 100644 --- a/frontend/src/styles/Sidebar.css +++ b/frontend/src/styles/Sidebar.css @@ -1018,4 +1018,18 @@ transform-origin: bottom center; animation: slideUpFade 0.25s cubic-bezier(0.4, 0, 0.2, 1); } +} + +/* ========== DARK THEME + AUTO ACCENT OVERRIDES ========== */ + +/* Nav items with auto accent in dark mode: use off-white background with dark text */ +[data-theme='dark'][data-accent='auto'] .nav-item.active { + background: #e5e7eb; + color: #111827 !important; + box-shadow: var(--shadow-md); +} + +[data-theme='dark'][data-accent='auto'] .nav-item.active .nav-icon, +[data-theme='dark'][data-accent='auto'] .nav-item.active .nav-label { + color: #111827 !important; } \ No newline at end of file diff --git a/frontend/src/styles/ThemeSettings.css b/frontend/src/styles/ThemeSettings.css index d2b5f88..e372e93 100644 --- a/frontend/src/styles/ThemeSettings.css +++ b/frontend/src/styles/ThemeSettings.css @@ -1372,4 +1372,117 @@ .option-card:hover .sidebar-mode-dynamic .sidebar-line { width: 100%; +} + +/* ========== DARK THEME + AUTO ACCENT OVERRIDES ========== */ + +/* Theme tab active state */ +[data-theme='dark'][data-accent='auto'] .theme-tab-btn.active { + color: #e5e7eb; + border-bottom-color: #e5e7eb; +} + +/* Color card active state */ +[data-theme='dark'][data-accent='auto'] .color-card.active { + border-color: #e5e7eb; + box-shadow: 0 0 0 3px rgba(229, 231, 235, 0.2); +} + +/* Palette card active state */ +[data-theme='dark'][data-accent='auto'] .palette-card.active { + border-color: #e5e7eb; + box-shadow: 0 0 0 3px rgba(229, 231, 235, 0.2); +} + +/* Palette check icon */ +[data-theme='dark'][data-accent='auto'] .palette-check .material-symbols-outlined { + background: #e5e7eb; + color: #111827; +} + +/* Option card active state */ +[data-theme='dark'][data-accent='auto'] .option-card.active { + border-color: #e5e7eb; + background: rgba(229, 231, 235, 0.05); + box-shadow: 0 0 0 3px rgba(229, 231, 235, 0.15); +} + +/* Preview elements with accent color */ +[data-theme='dark'][data-accent='auto'] .radius-preview-box, +[data-theme='dark'][data-accent='auto'] .density-line, +[data-theme='dark'][data-accent='auto'] .sidebar-mode-preview .sidebar-line { + background: #e5e7eb; +} + +[data-theme='dark'][data-accent='auto'] .radius-preview-box { + box-shadow: 0 2px 8px rgba(229, 231, 235, 0.2); +} + +[data-theme='dark'][data-accent='auto'] .font-preview { + color: #e5e7eb; +} + +/* Stat value accent */ +[data-theme='dark'][data-accent='auto'] .stat-value { + color: #e5e7eb; +} + +/* Badge accent */ +[data-theme='dark'][data-accent='auto'] .badge-accent { + background: #e5e7eb; + color: #111827; +} + +/* Primary button in theme settings */ +[data-theme='dark'][data-accent='auto'] .btn-primary { + background: #e5e7eb; + color: #111827; +} + +[data-theme='dark'][data-accent='auto'] .btn-primary:hover { + background: #f3f4f6; + color: #111827; + box-shadow: 0 4px 12px rgba(229, 231, 235, 0.2); +} + +/* Ghost button hover */ +[data-theme='dark'][data-accent='auto'] .btn-ghost:hover { + border-color: #e5e7eb; +} + +/* Input focus states */ +[data-theme='dark'][data-accent='auto'] .preview-inputs input:focus, +[data-theme='dark'][data-accent='auto'] .color-hex-input:focus { + border-color: #e5e7eb; +} + +/* Color picker button hover */ +[data-theme='dark'][data-accent='auto'] .btn-color-picker:hover { + border-color: #e5e7eb; +} + +/* Eyedropper button hover */ +[data-theme='dark'][data-accent='auto'] .btn-eyedropper:hover, +[data-theme='dark'][data-accent='auto'] .btn-eyedropper-popup:hover { + background: #e5e7eb; + border-color: #e5e7eb; + color: #111827; +} + +/* Eyedropper indicator */ +[data-theme='dark'][data-accent='auto'] .eyedropper-indicator { + color: #e5e7eb; +} + +/* Color control item active state */ +[data-theme='dark'][data-accent='auto'] .color-control-item.eyedropper-active { + border-color: #e5e7eb; + background: rgba(229, 231, 235, 0.05); + box-shadow: 0 0 0 2px rgba(229, 231, 235, 0.2); +} + +/* Chrome picker input focus */ +[data-theme='dark'][data-accent='auto'] .chrome-picker input:focus { + border-color: #e5e7eb !important; + box-shadow: 0 0 0 3px rgba(229, 231, 235, 0.15) !important; } \ No newline at end of file diff --git a/frontend/src/styles/theme/index.css b/frontend/src/styles/theme/index.css index d01ee40..0f9fac3 100644 --- a/frontend/src/styles/theme/index.css +++ b/frontend/src/styles/theme/index.css @@ -102,4 +102,26 @@ button:focus-visible { ::-webkit-scrollbar-thumb:hover { background: var(--color-border-hover); +} + +/* ========== DARK THEME + AUTO ACCENT OVERRIDES ========== */ + +/* Links */ +[data-theme='dark'][data-accent='auto'] a { + color: #e5e7eb; +} + +[data-theme='dark'][data-accent='auto'] a:hover { + color: #f3f4f6; +} + +/* Button focus outline */ +[data-theme='dark'][data-accent='auto'] button:focus, +[data-theme='dark'][data-accent='auto'] button:focus-visible { + outline-color: #e5e7eb; +} + +/* Loading state */ +[data-theme='dark'][data-accent='auto'] .loading { + color: #e5e7eb; } \ No newline at end of file