Theme Integration
Keep your plugin visually in sync with the Whatalo admin's light and dark mode using the App Bridge.
The Whatalo admin supports light and dark mode. When the merchant switches themes, the admin pushes an updated context payload to your plugin in real time. The App Bridge handles the sync so your UI always matches the surrounding shell.
How It Works
- The admin includes
theme: "light" | "dark"in the initialwhatalo:contextmessage. - A
MutationObserveron the admin detects theme attribute changes on<html>. - When the theme changes, the host pushes a new
whatalo:contextmessage to your plugin's iframe. - The bridge sets
document.documentElement.setAttribute("data-theme", theme)on your document root. - Your CSS
[data-theme="dark"]rules activate automatically.
Option 1: useThemeSync Hook (Recommended)
The plugin template ships a useThemeSync hook in ./components/whatalo-ui that handles the attribute update for you:
import { useThemeSync } from "./components/whatalo-ui";
function App() {
// Syncs data-theme on document.documentElement automatically
useThemeSync();
return <div className="my-plugin">...</div>;
}Call this hook once at the root of your plugin.
Option 2: Read the Theme Value Directly
import { useAppBridge } from "@whatalo/plugin-sdk/bridge";
function MyComponent() {
const { theme } = useAppBridge();
return (
<div className={theme === "dark" ? "dark-mode" : "light-mode"}>
...
</div>
);
}CSS Custom Properties Pattern
The template's WUI components use CSS custom properties toggled by the data-theme attribute:
/* Default (light) */
:root {
--wui-bg: #ffffff;
--wui-text: #1a1a2e;
--wui-border: #e2e8f0;
}
/* Dark mode — activated when the admin is in dark mode */
[data-theme="dark"] {
--wui-bg: #1a1a2e;
--wui-text: #e8e8e8;
--wui-border: #2d3748;
}Use these tokens in your plugin's own styles for consistent theming without hardcoding color values.
Iframe Background
Your plugin iframe has overflow: hidden and a transparent background. The admin shell manages scrolling — your plugin content should fill the iframe height (use the resize action or useAutoResize).
Theme in Modal Iframes
Modals opened via bridge.modal.open() do not receive App Bridge context directly. The bridge passes the current theme as a URL query parameter:
https://your-plugin.example.com/modal/order/123?theme=darkuseThemeSync reads the ?theme= parameter first, then falls back to bridge context if the parameter is absent. This means the same hook works identically in both your main iframe and any modal iframes.