feat(basic-host): Add theme toggle and MCP style variables (#336)
* 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
This commit is contained in:
parent
ee5d3f85ac
commit
7bbf2bb250
1 changed files with 287 additions and 12 deletions
64
examples/basic-host/src/theme.ts
Normal file
64
examples/basic-host/src/theme.ts
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* 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");
|
||||
});
|
||||
Loading…
Reference in a new issue