diff --git a/src/app-inspector/main.tsx b/src/app-inspector/main.tsx index 72028f2..71ce9df 100644 --- a/src/app-inspector/main.tsx +++ b/src/app-inspector/main.tsx @@ -3,8 +3,13 @@ import { AppInspectorContextProvider, pages, } from "@localstack/appinspector-ui"; -import { LocalStackThemeProvider } from "@localstack/integrations"; -import { StrictMode } from "react"; +import { + eventSystem, + LocalStackEventType, + LocalStackThemeProvider, + ThemeType, +} from "@localstack/integrations"; +import { StrictMode, useEffect } from "react"; import { render } from "react-dom"; import { HashRouter, @@ -15,6 +20,56 @@ import { Routes, } from "react-router-dom"; +/** + * Reads VS Code's current theme from the webview's body element. VS Code + * tags the body with `data-vscode-theme-kind` (and matching `vscode-*` + * classes) and updates them when the user changes their color theme. + * Returns undefined outside a VS Code webview, so the theme provider can + * fall back to the OS `prefers-color-scheme` default. + */ +function detectVSCodeTheme(): ThemeType | undefined { + const kind = + document.body.dataset.vscodeThemeKind ?? + (document.body.classList.contains("vscode-dark") + ? "vscode-dark" + : document.body.classList.contains("vscode-high-contrast") + ? "vscode-high-contrast" + : document.body.classList.contains("vscode-high-contrast-light") + ? "vscode-high-contrast-light" + : document.body.classList.contains("vscode-light") + ? "vscode-light" + : undefined); + if (kind === "vscode-dark" || kind === "vscode-high-contrast") { + return ThemeType.DARK; + } + if (kind === "vscode-light" || kind === "vscode-high-contrast-light") { + return ThemeType.LIGHT; + } + return undefined; +} + +const VSCodeThemeSync = () => { + useEffect(() => { + let lastTheme = detectVSCodeTheme(); + const observer = new MutationObserver(() => { + const next = detectVSCodeTheme(); + if (next && next !== lastTheme) { + lastTheme = next; + eventSystem.notify({ + eventType: LocalStackEventType.THEME_UPDATE, + data: { theme: next }, + }); + } + }); + observer.observe(document.body, { + attributes: true, + attributeFilter: ["class", "data-vscode-theme-kind"], + }); + return () => observer.disconnect(); + }, []); + return null; +}; + /* Passed by the VS Code extension when App Inspector is launched. */ declare global { interface Window { @@ -46,7 +101,11 @@ render( padding: "24px", }} > - + + (