diff --git a/browser/src/index.tsx b/browser/src/index.tsx index 36e80a84fe..cf0ac0f45e 100644 --- a/browser/src/index.tsx +++ b/browser/src/index.tsx @@ -5,6 +5,7 @@ import { BrowserRouter } from "react-router-dom"; import SamplesBrowser from "./navigation/SamplesBrowser"; import RegisterServiceWorker from './serviceWorker'; import { createRoot } from 'react-dom/client'; +import { initSampleThemeListener } from './sample-theme'; import { initSampleSizeReporter } from './sample-size-reporter'; import './index.css'; // styles shared between all samples @@ -22,6 +23,8 @@ import './index.css'; // styles shared between all samples // ); // }); +// Lets the docs ThemingWidget re-theme this browser while embedded. +initSampleThemeListener(); // Lets docs samples embedded with size their iframe to // their content. Dormant unless the docs host asks for it. initSampleSizeReporter(); diff --git a/browser/src/sample-theme.ts b/browser/src/sample-theme.ts new file mode 100644 index 0000000000..1c202a346a --- /dev/null +++ b/browser/src/sample-theme.ts @@ -0,0 +1,187 @@ +/** + * sample-theme.ts + * + * Lets the docs site re-theme this samples browser while it is embedded in a + * docs `` iframe. + * + * The docs ThemingWidget dispatches `igd-theme-change`; the Sample widget + * bridges that to `postMessage({ type: 'igd-sample-theme', theme, mode })` on + * the frame, and re-posts the current selection on every iframe `load`. Here we + * validate the sender and swap the Ignite UI theme stylesheets to match. + * + * Dormant unless a trusted docs host asks for a theme. + */ + +type ThemeName = 'material' | 'fluent' | 'bootstrap' | 'indigo'; +type ThemeMode = 'light' | 'dark' | 'system'; +type ResolvedMode = 'light' | 'dark'; + +interface ThemeMessage { + type?: string; + event?: string; + theme?: string; + themeName?: string; + mode?: string; +} + +type CssLoader = () => Promise<{ default: string }>; + +const MESSAGE_TYPE = 'igd-sample-theme'; +const STYLE_ATTR = 'data-igd-sample-theme'; +const DARK_QUERY = '(prefers-color-scheme: dark)'; + +// Vite only bundles dynamic imports with literal specifiers, so every +// mode/theme pair is spelled out. `?inline` yields the CSS as a string instead +// of injecting a sheet, which lets selections replace each other in owned +//