From a101899d9cd077a0d5a3879de1203fb7c6cc2567 Mon Sep 17 00:00:00 2001 From: Andrew Zambazos Date: Tue, 24 Feb 2026 21:00:38 +1300 Subject: [PATCH] Add RGB CSS variables for theme colors Introduce --primary-rgb, --accent-rgb, --success-rgb and --warning-rgb and replace hardcoded rgba(...) usages in CSS with rgba(var(--*-rgb), alpha) to allow dynamic alpha blending from theme colors. Add a hexToRgb helper in setup.js and populate these RGB variables in applyThemeToSetupPage (handles 3- and 6-digit hex and validates input), so runtime theme changes can drive translucent shadows, backgrounds and highlights. --- renderer/setup.css | 22 +++++++++++++--------- renderer/setup.js | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/renderer/setup.css b/renderer/setup.css index 7d424e8..938b4cb 100644 --- a/renderer/setup.css +++ b/renderer/setup.css @@ -12,14 +12,18 @@ --dark-blue: #0B1C2B; --dark-purple: #1B1035; --primary: #7B2EFF; + --primary-rgb: 123, 46, 255; --accent: #00C6FF; + --accent-rgb: 0, 198, 255; --text: #E0E0E0; --text-secondary: #A0A0A0; --card-bg: rgba(255, 255, 255, 0.05); --card-hover: rgba(255, 255, 255, 0.08); --border: rgba(255, 255, 255, 0.1); --success: #4CAF50; + --success-rgb: 76, 175, 80; --warning: #FF9800; + --warning-rgb: 255, 152, 0; --gradient-primary: linear-gradient(135deg, var(--accent), var(--primary)); --gradient-bg: linear-gradient(145deg, var(--bg) 0%, var(--dark-purple) 100%); --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.2); @@ -98,7 +102,7 @@ body, html { .progress-step.active .step-circle { background: var(--primary); border-color: transparent; - box-shadow: 0 4px 12px rgba(123, 46, 255, 0.4); + box-shadow: 0 4px 12px rgba(var(--primary-rgb), 0.4); transform: scale(1.1); } @@ -190,7 +194,7 @@ body, html { .setup-logo { width: 120px; height: 120px; - filter: drop-shadow(0 8px 24px rgba(123, 46, 255, 0.3)); + filter: drop-shadow(0 8px 24px rgba(var(--primary-rgb), 0.3)); animation: float 3s ease-in-out infinite; } @@ -273,7 +277,7 @@ body, html { .theme-card.selected { border-color: var(--primary); background: var(--card-hover); - box-shadow: 0 0 0 3px rgba(123, 46, 255, 0.2); + box-shadow: 0 0 0 3px rgba(var(--primary-rgb), 0.2); } .theme-card.selected::after { @@ -383,7 +387,7 @@ body, html { .default-browser-status.is-default { border-color: var(--success); - background: rgba(76, 175, 80, 0.1); + background: rgba(var(--success-rgb), 0.1); } .default-browser-status.is-default .status-icon { @@ -396,7 +400,7 @@ body, html { .default-browser-status.not-default { border-color: var(--warning); - background: rgba(255, 152, 0, 0.1); + background: rgba(var(--warning-rgb), 0.1); } @keyframes spin { @@ -430,7 +434,7 @@ body, html { justify-content: center; font-size: 4rem; font-weight: bold; - box-shadow: 0 8px 32px rgba(123, 46, 255, 0.4); + box-shadow: 0 8px 32px rgba(var(--primary-rgb), 0.4); animation: scaleIn 0.5s ease; } @@ -492,7 +496,7 @@ body, html { /* Future Feature Teaser */ .future-feature-teaser { - background: linear-gradient(135deg, rgba(123, 46, 255, 0.1), rgba(0, 198, 255, 0.1)); + background: linear-gradient(135deg, rgba(var(--primary-rgb), 0.1), rgba(var(--accent-rgb), 0.1)); border: 1px solid var(--border); border-radius: 16px; padding: 2rem; @@ -554,12 +558,12 @@ body, html { .btn-primary { background: var(--primary); color: white; - box-shadow: 0 4px 12px rgba(123, 46, 255, 0.3); + box-shadow: 0 4px 12px rgba(var(--primary-rgb), 0.3); } .btn-primary:hover { transform: translateY(-2px); - box-shadow: 0 6px 20px rgba(123, 46, 255, 0.4); + box-shadow: 0 6px 20px rgba(var(--primary-rgb), 0.4); } .btn-primary:active { diff --git a/renderer/setup.js b/renderer/setup.js index 9281b91..522bbe8 100644 --- a/renderer/setup.js +++ b/renderer/setup.js @@ -121,6 +121,22 @@ function getThemeById(themeId) { return null; } +function hexToRgb(hex) { + if (!hex || typeof hex !== 'string') return null; + let normalized = hex.trim().replace(/^#/, ''); + if (normalized.length === 3) { + normalized = normalized.split('').map(char => char + char).join(''); + } + if (!/^[a-fA-F\d]{6}$/.test(normalized)) return null; + + const intValue = parseInt(normalized, 16); + return { + r: (intValue >> 16) & 255, + g: (intValue >> 8) & 255, + b: intValue & 255 + }; +} + /** * Apply theme to the setup page UI and persist selection */ @@ -140,6 +156,25 @@ function applyThemeToSetupPage(theme, themeId = null) { setVar('--primary', colors.primary, '#7B2EFF'); setVar('--accent', colors.accent, '#00C6FF'); setVar('--text', colors.text, '#E0E0E0'); + setVar('--success', colors.accent, '#4CAF50'); + setVar('--warning', colors.primary, '#FF9800'); + + const primaryRgb = hexToRgb(colors.primary || '#7B2EFF'); + const accentRgb = hexToRgb(colors.accent || '#00C6FF'); + const successRgb = hexToRgb(colors.accent || '#4CAF50'); + const warningRgb = hexToRgb(colors.primary || '#FF9800'); + if (primaryRgb) { + setVar('--primary-rgb', `${primaryRgb.r}, ${primaryRgb.g}, ${primaryRgb.b}`); + } + if (accentRgb) { + setVar('--accent-rgb', `${accentRgb.r}, ${accentRgb.g}, ${accentRgb.b}`); + } + if (successRgb) { + setVar('--success-rgb', `${successRgb.r}, ${successRgb.g}, ${successRgb.b}`); + } + if (warningRgb) { + setVar('--warning-rgb', `${warningRgb.r}, ${warningRgb.g}, ${warningRgb.b}`); + } if (theme.gradient) { document.body.style.background = theme.gradient;