* feat(basic-host): add theme toggle and MCP style variables Add theme support to basic-host example: - theme.ts: Global theme manager with light/dark toggle - host-styles.ts: Full set of MCP CSS variables using light-dark() - ThemeToggle component with sun/moon icons - Theme-aware CSS using CSS custom properties - Pass theme + styles to apps via hostContext - Notify apps when theme changes via sendHostContextChange Apps now receive: - hostContext.theme: 'light' | 'dark' - hostContext.styles.variables: All 60+ MCP CSS variables - onhostcontextchanged notifications when theme changes * test: update e2e goldens for theme changes
64 lines
1.5 KiB
TypeScript
64 lines
1.5 KiB
TypeScript
/**
|
|
* Simple theme manager for the basic-host example.
|
|
* Manages light/dark theme state and notifies listeners.
|
|
*/
|
|
|
|
export type Theme = "light" | "dark";
|
|
|
|
type ThemeListener = (theme: Theme) => void;
|
|
|
|
const listeners = new Set<ThemeListener>();
|
|
|
|
// Get initial theme from system preference
|
|
let currentTheme: Theme = window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
? "dark"
|
|
: "light";
|
|
|
|
// Apply theme to document
|
|
function applyTheme(theme: Theme) {
|
|
document.documentElement.setAttribute("data-theme", theme);
|
|
document.documentElement.style.colorScheme = theme;
|
|
}
|
|
|
|
// Initial application
|
|
applyTheme(currentTheme);
|
|
|
|
/**
|
|
* Get current theme.
|
|
*/
|
|
export function getTheme(): Theme {
|
|
return currentTheme;
|
|
}
|
|
|
|
/**
|
|
* Set theme and notify all listeners.
|
|
*/
|
|
export function setTheme(theme: Theme): void {
|
|
if (theme === currentTheme) return;
|
|
currentTheme = theme;
|
|
applyTheme(theme);
|
|
listeners.forEach((listener) => listener(theme));
|
|
}
|
|
|
|
/**
|
|
* Toggle between light and dark themes.
|
|
*/
|
|
export function toggleTheme(): Theme {
|
|
const newTheme = currentTheme === "dark" ? "light" : "dark";
|
|
setTheme(newTheme);
|
|
return newTheme;
|
|
}
|
|
|
|
/**
|
|
* Subscribe to theme changes.
|
|
* Returns unsubscribe function.
|
|
*/
|
|
export function onThemeChange(listener: ThemeListener): () => void {
|
|
listeners.add(listener);
|
|
return () => listeners.delete(listener);
|
|
}
|
|
|
|
// Also listen for system preference changes
|
|
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => {
|
|
setTheme(e.matches ? "dark" : "light");
|
|
});
|