diff --git a/.vscode/settings.json b/.vscode/settings.json index dd3deb6ff..9a21e7413 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -19,6 +19,7 @@ "hostable", "INBUCKET", "Jwks", + "Luma", "midfix", "Millis", "mjsx", diff --git a/packages/stack/src/utils/browser-script.tsx b/packages/stack/src/utils/browser-script.tsx index c308780a2..b249c17f2 100644 --- a/packages/stack/src/utils/browser-script.tsx +++ b/packages/stack/src/utils/browser-script.tsx @@ -20,15 +20,33 @@ const script = () => { document.documentElement.setAttribute('data-stack-theme', mode); }; + const colorToRGB = (color: string): [number, number, number] | null => { + // Create a temporary element to use for color conversion + const temp = document.createElement('div'); + temp.style.color = color; + document.body.appendChild(temp); + + // Get the computed style + const computedColor = getComputedStyle(temp).color; + document.body.removeChild(temp); + + // Parse the RGB values + const match = computedColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); + if (match) { + return [parseInt(match[1]), parseInt(match[2]), parseInt(match[3])]; + } + + return null; + }; + + const rgbToLuma = (rgb: [number, number, number]) => { + return (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000; + }; + const copyFromColorScheme = () => { const colorScheme = getComputedStyle(document.documentElement).getPropertyValue('color-scheme'); if (colorScheme) { - if (colorScheme === 'normal') { - const isDark = window.matchMedia("(prefers-color-scheme: dark)").matches; - setTheme(isDark ? 'dark' : 'light'); - return true; - } const mode = getColorMode(colorScheme); if (mode) { setTheme(mode); @@ -38,6 +56,25 @@ const script = () => { return false; }; + const copyFromVariables = () => { + const backgroundColor = getComputedStyle(document.documentElement).getPropertyValue('--background'); + if (backgroundColor) { + // convert backgroundColor to hsl and check if it's dark + const rgb = colorToRGB(backgroundColor); + if (rgb) { + const luma = rgbToLuma(rgb); + console.log('luma', luma); + if (luma < 128) { + setTheme('dark'); + } else { + setTheme('light'); + } + return true; + } + } + return false; + }; + const copyFromAttributes = () => { for (const attributeName of attributes) { const colorTheme = document.documentElement.getAttribute(attributeName); @@ -57,6 +94,9 @@ const script = () => { if (copyFromColorScheme()) { return; } + if (copyFromVariables()) { + return; + } if (mutation.attributeName && attributes.includes(mutation.attributeName)) { copyFromAttributes(); } @@ -70,7 +110,9 @@ const script = () => { // Initial check on page load if (!copyFromColorScheme()) { - copyFromAttributes(); + if (!copyFromVariables()) { + copyFromAttributes(); + } } };