From a3892a338d5ea12f809671d40eb79ab8bc8eccd5 Mon Sep 17 00:00:00 2001 From: Stamen Stoychev Date: Wed, 5 Aug 2026 15:17:42 +0300 Subject: [PATCH] feat(*): add theming widget handling --- browser/src/index.tsx | 4 + browser/src/sample-theme.ts | 187 ++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 browser/src/sample-theme.ts diff --git a/browser/src/index.tsx b/browser/src/index.tsx index 8448fe8ebb..31ffb41769 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 './index.css'; // styles shared between all samples @@ -21,6 +22,9 @@ import './index.css'; // styles shared between all samples // ); // }); +// Lets the docs ThemingWidget re-theme this browser while embedded. +initSampleThemeListener(); + const container = document.getElementById('root'); const root = createRoot(container); root.render( 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 +//