feat/fix: robust ThemeListener with overrides for all templates

This commit is contained in:
AI Studio 2026-05-18 01:14:17 +00:00
parent 762200d20b
commit cbdb0252aa
3 changed files with 117 additions and 51 deletions

View file

@ -2,43 +2,65 @@ import { useEffect } from 'react';
export function ThemeListener() { export function ThemeListener() {
useEffect(() => { useEffect(() => {
const handleMessage = (event: MessageEvent) => { const handleMessage = (event: any) => {
// Allow messages from any origin since preview is generic
if (event.data?.type === 'UPDATE_APPEARANCE') { if (event.data?.type === 'UPDATE_APPEARANCE') {
const settings = event.data.settings; const settings = event.data.settings;
if (!settings) return; if (!settings) return;
const root = document.documentElement; let css = '';
// Update Primary Color
if (settings.primaryColor) { if (settings.primaryColor) {
root.style.setProperty('--color-brand-primary', settings.primaryColor); css += "\n:root { " +
root.style.setProperty('--color-brand-blue', settings.primaryColor); "--color-brand-primary: " + settings.primaryColor + " !important; " +
root.style.setProperty('--color-brand-gold', settings.primaryColor); "--color-brand-blue: " + settings.primaryColor + " !important; " +
"--color-brand-gold: " + settings.primaryColor + " !important; " +
"--color-blue-500: " + settings.primaryColor + " !important; " +
"--color-blue-600: " + settings.primaryColor + " !important; " +
"--color-emerald-500: " + settings.primaryColor + " !important; " +
"--color-emerald-600: " + settings.primaryColor + " !important; " +
"} " +
".text-brand-blue, .text-blue-600, .group-hover\\:text-blue-600:hover, .text-brand-gold, .text-emerald-600, .text-blue-500, .text-emerald-500 { color: " + settings.primaryColor + " !important; } " +
".bg-brand-blue, .bg-blue-600, .hover\\:bg-blue-500:hover, .bg-brand-gold, .bg-emerald-600, .bg-blue-500, .bg-emerald-500 { background-color: " + settings.primaryColor + " !important; } " +
".border-brand-blue, .border-blue-600, .focus\\:border-blue-600:focus, .border-brand-gold, .border-emerald-600, .border-blue-500, .border-emerald-500 { border-color: " + settings.primaryColor + " !important; } " +
".fill-blue-600, .fill-emerald-600 { fill: " + settings.primaryColor + " !important; }";
} }
// Update Background Color
if (settings.backgroundColor) { if (settings.backgroundColor) {
root.style.setProperty('--color-brand-bg', settings.backgroundColor); css += "\n:root { --color-brand-bg: " + settings.backgroundColor + " !important; } " +
document.body.style.backgroundColor = settings.backgroundColor; "body { background-color: " + settings.backgroundColor + " !important; }";
} }
// Update Font Family
if (settings.fontFamily) { if (settings.fontFamily) {
const fontLink = document.getElementById('dynamic-font') as HTMLLinkElement; const fontLink = document.getElementById('dynamic-font');
const fontName = settings.fontFamily.replace(/ /g, '+'); const fontName = settings.fontFamily.replace(/ /g, '+');
const fontUrl = 'https://fonts.googleapis.com/css2?family=' + fontName + ':wght@300;400;500;600;700&display=swap';
if (fontLink) { if (fontLink) {
fontLink.href = `https://fonts.googleapis.com/css2?family=${fontName}:wght@300;400;500;600;700&display=swap`; (fontLink as HTMLLinkElement).href = fontUrl;
} else { } else {
const link = document.createElement('link'); const link = document.createElement('link');
link.id = 'dynamic-font'; link.id = 'dynamic-font';
link.rel = 'stylesheet'; link.rel = 'stylesheet';
link.href = `https://fonts.googleapis.com/css2?family=${fontName}:wght@300;400;500;600;700&display=swap`; link.href = fontUrl;
document.head.appendChild(link); document.head.appendChild(link);
} }
root.style.setProperty('--font-sans', `"${settings.fontFamily}", sans-serif`);
document.body.style.fontFamily = `"${settings.fontFamily}", sans-serif`; css += "\n:root { " +
"--font-sans: \"" + settings.fontFamily + "\", sans-serif !important; " +
"--font-serif: \"" + settings.fontFamily + "\", serif !important; " +
"--font-mono: \"" + settings.fontFamily + "\", monospace !important; " +
"} " +
"body, h1, h2, h3, h4, h5, h6, .font-serif, .font-sans, .font-mono, p, span, a, button { " +
"font-family: \"" + settings.fontFamily + "\", sans-serif !important; " +
"}";
} }
let styleNode = document.getElementById('dynamic-theme-style');
if (!styleNode) {
styleNode = document.createElement('style');
styleNode.id = 'dynamic-theme-style';
document.head.appendChild(styleNode);
}
styleNode.innerHTML = css;
} }
}; };

View file

@ -2,43 +2,65 @@ import { useEffect } from 'react';
export function ThemeListener() { export function ThemeListener() {
useEffect(() => { useEffect(() => {
const handleMessage = (event: MessageEvent) => { const handleMessage = (event: any) => {
// Allow messages from any origin since preview is generic
if (event.data?.type === 'UPDATE_APPEARANCE') { if (event.data?.type === 'UPDATE_APPEARANCE') {
const settings = event.data.settings; const settings = event.data.settings;
if (!settings) return; if (!settings) return;
const root = document.documentElement; let css = '';
// Update Primary Color
if (settings.primaryColor) { if (settings.primaryColor) {
root.style.setProperty('--color-brand-primary', settings.primaryColor); css += "\n:root { " +
root.style.setProperty('--color-brand-blue', settings.primaryColor); "--color-brand-primary: " + settings.primaryColor + " !important; " +
root.style.setProperty('--color-brand-gold', settings.primaryColor); "--color-brand-blue: " + settings.primaryColor + " !important; " +
"--color-brand-gold: " + settings.primaryColor + " !important; " +
"--color-blue-500: " + settings.primaryColor + " !important; " +
"--color-blue-600: " + settings.primaryColor + " !important; " +
"--color-emerald-500: " + settings.primaryColor + " !important; " +
"--color-emerald-600: " + settings.primaryColor + " !important; " +
"} " +
".text-brand-blue, .text-blue-600, .group-hover\\:text-blue-600:hover, .text-brand-gold, .text-emerald-600, .text-blue-500, .text-emerald-500 { color: " + settings.primaryColor + " !important; } " +
".bg-brand-blue, .bg-blue-600, .hover\\:bg-blue-500:hover, .bg-brand-gold, .bg-emerald-600, .bg-blue-500, .bg-emerald-500 { background-color: " + settings.primaryColor + " !important; } " +
".border-brand-blue, .border-blue-600, .focus\\:border-blue-600:focus, .border-brand-gold, .border-emerald-600, .border-blue-500, .border-emerald-500 { border-color: " + settings.primaryColor + " !important; } " +
".fill-blue-600, .fill-emerald-600 { fill: " + settings.primaryColor + " !important; }";
} }
// Update Background Color
if (settings.backgroundColor) { if (settings.backgroundColor) {
root.style.setProperty('--color-brand-bg', settings.backgroundColor); css += "\n:root { --color-brand-bg: " + settings.backgroundColor + " !important; } " +
document.body.style.backgroundColor = settings.backgroundColor; "body { background-color: " + settings.backgroundColor + " !important; }";
} }
// Update Font Family
if (settings.fontFamily) { if (settings.fontFamily) {
const fontLink = document.getElementById('dynamic-font') as HTMLLinkElement; const fontLink = document.getElementById('dynamic-font');
const fontName = settings.fontFamily.replace(/ /g, '+'); const fontName = settings.fontFamily.replace(/ /g, '+');
const fontUrl = 'https://fonts.googleapis.com/css2?family=' + fontName + ':wght@300;400;500;600;700&display=swap';
if (fontLink) { if (fontLink) {
fontLink.href = `https://fonts.googleapis.com/css2?family=${fontName}:wght@300;400;500;600;700&display=swap`; (fontLink as HTMLLinkElement).href = fontUrl;
} else { } else {
const link = document.createElement('link'); const link = document.createElement('link');
link.id = 'dynamic-font'; link.id = 'dynamic-font';
link.rel = 'stylesheet'; link.rel = 'stylesheet';
link.href = `https://fonts.googleapis.com/css2?family=${fontName}:wght@300;400;500;600;700&display=swap`; link.href = fontUrl;
document.head.appendChild(link); document.head.appendChild(link);
} }
root.style.setProperty('--font-sans', `"${settings.fontFamily}", sans-serif`);
document.body.style.fontFamily = `"${settings.fontFamily}", sans-serif`; css += "\n:root { " +
"--font-sans: \"" + settings.fontFamily + "\", sans-serif !important; " +
"--font-serif: \"" + settings.fontFamily + "\", serif !important; " +
"--font-mono: \"" + settings.fontFamily + "\", monospace !important; " +
"} " +
"body, h1, h2, h3, h4, h5, h6, .font-serif, .font-sans, .font-mono, p, span, a, button { " +
"font-family: \"" + settings.fontFamily + "\", sans-serif !important; " +
"}";
} }
let styleNode = document.getElementById('dynamic-theme-style');
if (!styleNode) {
styleNode = document.createElement('style');
styleNode.id = 'dynamic-theme-style';
document.head.appendChild(styleNode);
}
styleNode.innerHTML = css;
} }
}; };

View file

@ -2,43 +2,65 @@ import { useEffect } from 'react';
export function ThemeListener() { export function ThemeListener() {
useEffect(() => { useEffect(() => {
const handleMessage = (event: MessageEvent) => { const handleMessage = (event: any) => {
// Allow messages from any origin since preview is generic
if (event.data?.type === 'UPDATE_APPEARANCE') { if (event.data?.type === 'UPDATE_APPEARANCE') {
const settings = event.data.settings; const settings = event.data.settings;
if (!settings) return; if (!settings) return;
const root = document.documentElement; let css = '';
// Update Primary Color
if (settings.primaryColor) { if (settings.primaryColor) {
root.style.setProperty('--color-brand-primary', settings.primaryColor); css += "\n:root { " +
root.style.setProperty('--color-brand-blue', settings.primaryColor); "--color-brand-primary: " + settings.primaryColor + " !important; " +
root.style.setProperty('--color-brand-gold', settings.primaryColor); "--color-brand-blue: " + settings.primaryColor + " !important; " +
"--color-brand-gold: " + settings.primaryColor + " !important; " +
"--color-blue-500: " + settings.primaryColor + " !important; " +
"--color-blue-600: " + settings.primaryColor + " !important; " +
"--color-emerald-500: " + settings.primaryColor + " !important; " +
"--color-emerald-600: " + settings.primaryColor + " !important; " +
"} " +
".text-brand-blue, .text-blue-600, .group-hover\\:text-blue-600:hover, .text-brand-gold, .text-emerald-600, .text-blue-500, .text-emerald-500 { color: " + settings.primaryColor + " !important; } " +
".bg-brand-blue, .bg-blue-600, .hover\\:bg-blue-500:hover, .bg-brand-gold, .bg-emerald-600, .bg-blue-500, .bg-emerald-500 { background-color: " + settings.primaryColor + " !important; } " +
".border-brand-blue, .border-blue-600, .focus\\:border-blue-600:focus, .border-brand-gold, .border-emerald-600, .border-blue-500, .border-emerald-500 { border-color: " + settings.primaryColor + " !important; } " +
".fill-blue-600, .fill-emerald-600 { fill: " + settings.primaryColor + " !important; }";
} }
// Update Background Color
if (settings.backgroundColor) { if (settings.backgroundColor) {
root.style.setProperty('--color-brand-bg', settings.backgroundColor); css += "\n:root { --color-brand-bg: " + settings.backgroundColor + " !important; } " +
document.body.style.backgroundColor = settings.backgroundColor; "body { background-color: " + settings.backgroundColor + " !important; }";
} }
// Update Font Family
if (settings.fontFamily) { if (settings.fontFamily) {
const fontLink = document.getElementById('dynamic-font') as HTMLLinkElement; const fontLink = document.getElementById('dynamic-font');
const fontName = settings.fontFamily.replace(/ /g, '+'); const fontName = settings.fontFamily.replace(/ /g, '+');
const fontUrl = 'https://fonts.googleapis.com/css2?family=' + fontName + ':wght@300;400;500;600;700&display=swap';
if (fontLink) { if (fontLink) {
fontLink.href = `https://fonts.googleapis.com/css2?family=${fontName}:wght@300;400;500;600;700&display=swap`; (fontLink as HTMLLinkElement).href = fontUrl;
} else { } else {
const link = document.createElement('link'); const link = document.createElement('link');
link.id = 'dynamic-font'; link.id = 'dynamic-font';
link.rel = 'stylesheet'; link.rel = 'stylesheet';
link.href = `https://fonts.googleapis.com/css2?family=${fontName}:wght@300;400;500;600;700&display=swap`; link.href = fontUrl;
document.head.appendChild(link); document.head.appendChild(link);
} }
root.style.setProperty('--font-sans', `"${settings.fontFamily}", sans-serif`);
document.body.style.fontFamily = `"${settings.fontFamily}", sans-serif`; css += "\n:root { " +
"--font-sans: \"" + settings.fontFamily + "\", sans-serif !important; " +
"--font-serif: \"" + settings.fontFamily + "\", serif !important; " +
"--font-mono: \"" + settings.fontFamily + "\", monospace !important; " +
"} " +
"body, h1, h2, h3, h4, h5, h6, .font-serif, .font-sans, .font-mono, p, span, a, button { " +
"font-family: \"" + settings.fontFamily + "\", sans-serif !important; " +
"}";
} }
let styleNode = document.getElementById('dynamic-theme-style');
if (!styleNode) {
styleNode = document.createElement('style');
styleNode.id = 'dynamic-theme-style';
document.head.appendChild(styleNode);
}
styleNode.innerHTML = css;
} }
}; };