From 762200d20b9de3ac4d174cd418e123a82162be04 Mon Sep 17 00:00:00 2001 From: AI Studio Date: Fri, 15 May 2026 18:42:05 +0000 Subject: [PATCH] feat/fix: improve responsive constraints & add live ThemeListener --- Template-01/src/App.tsx | 4 +- .../src/components/layout/ThemeListener.tsx | 50 +++++++++++++++++++ Template-01/src/index.css | 11 ++++ Template-02/src/App.tsx | 4 +- .../src/components/layout/ThemeListener.tsx | 50 +++++++++++++++++++ Template-02/src/index.css | 11 ++++ Template-03/src/App.tsx | 4 +- .../src/components/layout/ThemeListener.tsx | 50 +++++++++++++++++++ Template-03/src/index.css | 11 ++++ 9 files changed, 192 insertions(+), 3 deletions(-) create mode 100644 Template-01/src/components/layout/ThemeListener.tsx create mode 100644 Template-02/src/components/layout/ThemeListener.tsx create mode 100644 Template-03/src/components/layout/ThemeListener.tsx diff --git a/Template-01/src/App.tsx b/Template-01/src/App.tsx index 72f4e55..70da4e6 100644 --- a/Template-01/src/App.tsx +++ b/Template-01/src/App.tsx @@ -1,3 +1,4 @@ +import { ThemeListener } from './components/layout/ThemeListener'; import React, { lazy, Suspense } from 'react'; import { BrowserRouter, Routes, Route, Navigate, useParams } from 'react-router-dom'; import { HelmetProvider } from 'react-helmet-async'; @@ -28,7 +29,8 @@ export default function App() { - loading_module...}> + + loading_module...}> } /> diff --git a/Template-01/src/components/layout/ThemeListener.tsx b/Template-01/src/components/layout/ThemeListener.tsx new file mode 100644 index 0000000..55dfcbb --- /dev/null +++ b/Template-01/src/components/layout/ThemeListener.tsx @@ -0,0 +1,50 @@ +import { useEffect } from 'react'; + +export function ThemeListener() { + useEffect(() => { + const handleMessage = (event: MessageEvent) => { + // Allow messages from any origin since preview is generic + if (event.data?.type === 'UPDATE_APPEARANCE') { + const settings = event.data.settings; + if (!settings) return; + + const root = document.documentElement; + + // Update Primary Color + if (settings.primaryColor) { + root.style.setProperty('--color-brand-primary', settings.primaryColor); + root.style.setProperty('--color-brand-blue', settings.primaryColor); + root.style.setProperty('--color-brand-gold', settings.primaryColor); + } + + // Update Background Color + if (settings.backgroundColor) { + root.style.setProperty('--color-brand-bg', settings.backgroundColor); + document.body.style.backgroundColor = settings.backgroundColor; + } + + // Update Font Family + if (settings.fontFamily) { + const fontLink = document.getElementById('dynamic-font') as HTMLLinkElement; + const fontName = settings.fontFamily.replace(/ /g, '+'); + if (fontLink) { + fontLink.href = `https://fonts.googleapis.com/css2?family=${fontName}:wght@300;400;500;600;700&display=swap`; + } else { + const link = document.createElement('link'); + link.id = 'dynamic-font'; + link.rel = 'stylesheet'; + link.href = `https://fonts.googleapis.com/css2?family=${fontName}:wght@300;400;500;600;700&display=swap`; + document.head.appendChild(link); + } + root.style.setProperty('--font-sans', `"${settings.fontFamily}", sans-serif`); + document.body.style.fontFamily = `"${settings.fontFamily}", sans-serif`; + } + } + }; + + window.addEventListener('message', handleMessage); + return () => window.removeEventListener('message', handleMessage); + }, []); + + return null; +} \ No newline at end of file diff --git a/Template-01/src/index.css b/Template-01/src/index.css index e00bee1..5c8f3c2 100644 --- a/Template-01/src/index.css +++ b/Template-01/src/index.css @@ -105,3 +105,14 @@ @apply inline-flex items-center justify-center px-4 py-2 bg-tech-text text-white rounded font-mono text-xs font-bold uppercase tracking-widest transition-all hover:bg-slate-800 active:scale-95 shadow-sm; } } + + +html, body { + overflow-x: hidden; + width: 100%; + max-width: 100vw; +} + +img { + max-width: 100%; +} diff --git a/Template-02/src/App.tsx b/Template-02/src/App.tsx index 0b87309..adc5b7c 100644 --- a/Template-02/src/App.tsx +++ b/Template-02/src/App.tsx @@ -1,3 +1,4 @@ +import { ThemeListener } from './components/layout/ThemeListener'; import React, { lazy, Suspense } from 'react'; import { BrowserRouter, Routes, Route, Navigate, useParams } from 'react-router-dom'; import { HelmetProvider } from 'react-helmet-async'; @@ -28,7 +29,8 @@ export default function App() { - VANTA_KERN_INIT...}> + + VANTA_KERN_INIT...}> } /> diff --git a/Template-02/src/components/layout/ThemeListener.tsx b/Template-02/src/components/layout/ThemeListener.tsx new file mode 100644 index 0000000..55dfcbb --- /dev/null +++ b/Template-02/src/components/layout/ThemeListener.tsx @@ -0,0 +1,50 @@ +import { useEffect } from 'react'; + +export function ThemeListener() { + useEffect(() => { + const handleMessage = (event: MessageEvent) => { + // Allow messages from any origin since preview is generic + if (event.data?.type === 'UPDATE_APPEARANCE') { + const settings = event.data.settings; + if (!settings) return; + + const root = document.documentElement; + + // Update Primary Color + if (settings.primaryColor) { + root.style.setProperty('--color-brand-primary', settings.primaryColor); + root.style.setProperty('--color-brand-blue', settings.primaryColor); + root.style.setProperty('--color-brand-gold', settings.primaryColor); + } + + // Update Background Color + if (settings.backgroundColor) { + root.style.setProperty('--color-brand-bg', settings.backgroundColor); + document.body.style.backgroundColor = settings.backgroundColor; + } + + // Update Font Family + if (settings.fontFamily) { + const fontLink = document.getElementById('dynamic-font') as HTMLLinkElement; + const fontName = settings.fontFamily.replace(/ /g, '+'); + if (fontLink) { + fontLink.href = `https://fonts.googleapis.com/css2?family=${fontName}:wght@300;400;500;600;700&display=swap`; + } else { + const link = document.createElement('link'); + link.id = 'dynamic-font'; + link.rel = 'stylesheet'; + link.href = `https://fonts.googleapis.com/css2?family=${fontName}:wght@300;400;500;600;700&display=swap`; + document.head.appendChild(link); + } + root.style.setProperty('--font-sans', `"${settings.fontFamily}", sans-serif`); + document.body.style.fontFamily = `"${settings.fontFamily}", sans-serif`; + } + } + }; + + window.addEventListener('message', handleMessage); + return () => window.removeEventListener('message', handleMessage); + }, []); + + return null; +} \ No newline at end of file diff --git a/Template-02/src/index.css b/Template-02/src/index.css index 0f4b286..7073e1c 100644 --- a/Template-02/src/index.css +++ b/Template-02/src/index.css @@ -137,3 +137,14 @@ @apply border-l-4 border-tech-primary pl-8 py-2 my-10 italic text-white bg-tech-primary/5 rounded-r-lg; } } + + +html, body { + overflow-x: hidden; + width: 100%; + max-width: 100vw; +} + +img { + max-width: 100%; +} diff --git a/Template-03/src/App.tsx b/Template-03/src/App.tsx index 7f51d0e..ef74baf 100644 --- a/Template-03/src/App.tsx +++ b/Template-03/src/App.tsx @@ -1,3 +1,4 @@ +import { ThemeListener } from './components/layout/ThemeListener'; import React, { lazy, Suspense } from 'react'; import { BrowserRouter, Routes, Route, Navigate, useParams } from 'react-router-dom'; import { HelmetProvider } from 'react-helmet-async'; @@ -31,7 +32,8 @@ export default function App() { - VANTA_KERN_INIT...}> + + VANTA_KERN_INIT...}> } /> diff --git a/Template-03/src/components/layout/ThemeListener.tsx b/Template-03/src/components/layout/ThemeListener.tsx new file mode 100644 index 0000000..55dfcbb --- /dev/null +++ b/Template-03/src/components/layout/ThemeListener.tsx @@ -0,0 +1,50 @@ +import { useEffect } from 'react'; + +export function ThemeListener() { + useEffect(() => { + const handleMessage = (event: MessageEvent) => { + // Allow messages from any origin since preview is generic + if (event.data?.type === 'UPDATE_APPEARANCE') { + const settings = event.data.settings; + if (!settings) return; + + const root = document.documentElement; + + // Update Primary Color + if (settings.primaryColor) { + root.style.setProperty('--color-brand-primary', settings.primaryColor); + root.style.setProperty('--color-brand-blue', settings.primaryColor); + root.style.setProperty('--color-brand-gold', settings.primaryColor); + } + + // Update Background Color + if (settings.backgroundColor) { + root.style.setProperty('--color-brand-bg', settings.backgroundColor); + document.body.style.backgroundColor = settings.backgroundColor; + } + + // Update Font Family + if (settings.fontFamily) { + const fontLink = document.getElementById('dynamic-font') as HTMLLinkElement; + const fontName = settings.fontFamily.replace(/ /g, '+'); + if (fontLink) { + fontLink.href = `https://fonts.googleapis.com/css2?family=${fontName}:wght@300;400;500;600;700&display=swap`; + } else { + const link = document.createElement('link'); + link.id = 'dynamic-font'; + link.rel = 'stylesheet'; + link.href = `https://fonts.googleapis.com/css2?family=${fontName}:wght@300;400;500;600;700&display=swap`; + document.head.appendChild(link); + } + root.style.setProperty('--font-sans', `"${settings.fontFamily}", sans-serif`); + document.body.style.fontFamily = `"${settings.fontFamily}", sans-serif`; + } + } + }; + + window.addEventListener('message', handleMessage); + return () => window.removeEventListener('message', handleMessage); + }, []); + + return null; +} \ No newline at end of file diff --git a/Template-03/src/index.css b/Template-03/src/index.css index b54832f..5be1b53 100644 --- a/Template-03/src/index.css +++ b/Template-03/src/index.css @@ -69,3 +69,14 @@ @apply bg-gray-100 text-brand-primary px-1.5 py-0.5 rounded text-[0.9em]; } } + + +html, body { + overflow-x: hidden; + width: 100%; + max-width: 100vw; +} + +img { + max-width: 100%; +}