diff --git a/js/ui.js b/js/ui.js index fa23d2a..3b78783 100644 --- a/js/ui.js +++ b/js/ui.js @@ -268,24 +268,60 @@ export class UIRenderer { if (!color) return; const root = document.documentElement; + const theme = root.getAttribute('data-theme'); + const isLightMode = theme === 'light'; + + let hex = color.replace('#', ''); + // Handle shorthand hex + if (hex.length === 3) { + hex = hex.split('').map(char => char + char).join(''); + } + + let r = parseInt(hex.substr(0, 2), 16); + let g = parseInt(hex.substr(2, 2), 16); + let b = parseInt(hex.substr(4, 2), 16); + + // Calculate perceived brightness + let brightness = ((r * 299) + (g * 587) + (b * 114)) / 1000; + + if (isLightMode) { + // In light mode, the background is white. + // We need the color (used for text/highlights) to be dark enough. + // If brightness is too high (> 150), darken it. + while (brightness > 150) { + r = Math.floor(r * 0.9); + g = Math.floor(g * 0.9); + b = Math.floor(b * 0.9); + brightness = ((r * 299) + (g * 587) + (b * 114)) / 1000; + } + } else { + // In dark mode, the background is dark. + // We need the color to be light enough. + // If brightness is too low (< 80), lighten it. + while (brightness < 80) { + r = Math.min(255, Math.floor(r * 1.15)); + g = Math.min(255, Math.floor(g * 1.15)); + b = Math.min(255, Math.floor(b * 1.15)); + brightness = ((r * 299) + (g * 587) + (b * 114)) / 1000; + // Break if we hit white or can't get brighter to avoid infinite loop + if (r >= 255 && g >= 255 && b >= 255) break; + } + } + + const adjustedColor = `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`; - // Calculate contrast text color - const hex = color.replace('#', ''); - const r = parseInt(hex.substr(0, 2), 16); - const g = parseInt(hex.substr(2, 2), 16); - const b = parseInt(hex.substr(4, 2), 16); - const brightness = ((r * 299) + (g * 587) + (b * 114)) / 1000; + // Calculate contrast text color for buttons (text on top of the vibrant color) const foreground = brightness > 128 ? '#000000' : '#ffffff'; // Set global CSS variables - root.style.setProperty('--primary', color); + root.style.setProperty('--primary', adjustedColor); root.style.setProperty('--primary-foreground', foreground); - root.style.setProperty('--highlight', color); + root.style.setProperty('--highlight', adjustedColor); root.style.setProperty('--highlight-rgb', `${r}, ${g}, ${b}`); - root.style.setProperty('--active-highlight', color); - root.style.setProperty('--ring', color); + root.style.setProperty('--active-highlight', adjustedColor); + root.style.setProperty('--ring', adjustedColor); - // Calculate a safe hover color (darken if too light) + // Calculate a safe hover color let hoverColor; if (brightness > 200) { const dr = Math.floor(r * 0.85);