App Bridge

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

  1. The admin includes theme: "light" | "dark" in the initial whatalo:context message.
  2. A MutationObserver on the admin detects theme attribute changes on <html>.
  3. When the theme changes, the host pushes a new whatalo:context message to your plugin's iframe.
  4. The bridge sets document.documentElement.setAttribute("data-theme", theme) on your document root.
  5. Your CSS [data-theme="dark"] rules activate automatically.

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=dark

useThemeSync 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.

On this page