Skip to Main Content
Preset Feature Feedback
Status Needs review
Categories New feature
Created by Customer Engagement
Created on Jul 31, 2026

Embedded dashboards: honour a theme mode at load time, before first paint

What is the problem or goal you're trying to solve or accomplish?

The customer embeds Preset dashboards in a customer-facing portal whose host UI follows the user's light/dark preference. They need the embedded dashboard to render in the correct theme mode on its first paint.

Today theme mode can only be set after the embedded application has loaded and painted, so every dashboard load renders in the workspace default (light) theme and then repaints. For a dark-mode user this is a full-width white block against a near-black portal background, lasting the full dashboard load.

Why it is not addressable host-side

  • EmbedDashboardParams exposes no theme or themeMode field. setThemeMode and setThemeConfig exist only on the EmbeddedDashboard returned by the promise. Confirmed against the published tarballs of both @preset-sdk/embedded@0.3.2 and @superset-ui/embedded-sdk@0.4.0.

  • embedDashboard() assigns iframe.src up front and initialises the comms channel inside the iframe's load handler, so the earliest possible moment to request a theme mode is after the embedded app has loaded and painted.

  • The SDK already sets iframe.style.background = 'transparent'; the customer additionally forces color-scheme: auto, allowTransparency and frameBorder=0. None of it helps, because the embedded document paints its own opaque light background.

Reproduction

Support workspace f5321d75 (eu5a) on Preset 6.0.0.24. The customer's workspace 22deae22 (us1a) is on the same build, so the reproduction transfers directly with no version caveat. Dark host page, guest-token embed, throttled connection, screen recordings measured frame by frame with banded luminance over the iframe region.

  • Light window on a single-chart dashboard: ~1.7s. The customer's own recording shows ~0.7s on their infrastructure.

  • The window is dominated by the wait before the host is permitted to send the theme instruction, not by the theme being slow to apply. Measured split across two runs: 75% and 86% of the visible window elapsed before setThemeMode could be dispatched.

  • Total load timing is highly variable: sdkResolved ranged 1656–4522ms across five runs on the same environment.

A theme mode honoured at load time would eliminate the defect rather than shorten it, because the embedded app would never paint in the wrong mode at all.

Impact: every dashboard load, for every dark-mode end user, across all embedded dashboards in the customer's portal. Customer-visible.

How are you solving it currently?

Calling setThemeMode('dark') on the resolved handle. It works, but is post-load by construction, so the flash remains on every load. They previously pushed a full theme via setThemeConfig at embed time and have since moved to workspace-level themes. Both are post-load; timing is identical either way.

URL-parameter path — tested, negative

Support tested passing a theme mode through dashboardUiConfig.urlParams in three spellings — themeMode, theme_mode, thememode. All three were confirmed present in the embedded document's request URL and all three had no effect; the dashboard rendered light in every case. No URL-parameter path exists on 6.0.0.24.

SDK substitution — tested, negative

Support also ran the same test with @superset-ui/embedded-sdk@0.4.0 substituted for @preset-sdk/embedded@0.3.2, everything else unchanged. Result was identical: the dashboard rendered light with themeMode=dark present in the iframe URL. A control run confirmed setThemeMode works correctly through the Superset SDK against a Preset workspace, so the negative is genuine rather than a broken integration.

This is expected on inspection: neither SDK exposes a theme field, and both build the iframe URL identically. The capability is in the embedded frontend application served by the workspace, not in the client SDK.

Host-side mitigation — partial, and not robustly specifiable

Covering the mount point with a host-styled opaque panel until shortly after setThemeMode is sent does remove the flash. Two caveats, both material:

  1. The panel must be a sibling of the mount point. embedDashboard() calls mountPoint.replaceChildren(iframe), so any placeholder or skeleton rendered inside the mount point is silently destroyed at mount, with no error. The Superset SDK has a third replaceChildren() call site (teardown on guest-token fetch failure) on top of mount and unmount. This behaviour is undocumented and it breaks the most natural implementation of exactly the mitigation affected customers need.

  2. The removal timing cannot be specified reliably. Measured latency between setThemeMode being dispatched and the dark repaint landing: 566ms, 733ms and 785ms across three runs (both SDKs, single-frame repaint in each case). A 600ms margin produced a measured 167ms full-white flash (peak band luminance 245 of 255). A 1500ms margin was clean, but at n=1. A 1000ms margin flashed on a cold load and not on a warm one. There is no supported signal to remove the guesswork. setThemeMode is ourPort.emit(...) — fire-and-forget, returns void, no acknowledgement or callback. The SDK's round-trip methods (getScrollSize, getChartStates, getActiveTabs, getDataMask, getChartDataPayloads) can prove the iframe received the theme message via switchboard message ordering, but none of them proves it has painted. The iframe is cross-origin, so the host cannot inspect what it renders. The practical consequence: any customer implementing this mitigation must ship a hard-coded delay tuned against infrastructure they cannot measure on behalf of their users. That is not something Support can responsibly specify a value for.

What is your recommended solution?

In their stated priority order:

  1. Preferred — a themeMode (and ideally theme) field on EmbedDashboardParams that the SDK bakes into the iframe URL, so the embedded app renders in the correct mode on first paint.

  2. Otherwise — a documented, supported embed URL parameter (e.g. theme_mode=dark) passable through dashboardUiConfig.urlParams.

  3. Otherwise — have the embedded page render a transparent/neutral background until theme resolution completes, so the host background shows through instead of white.

Support note — option 2 is already implemented upstream.

Apache Superset PR #40760 ("feat(embedded): support themeMode URL param for initial theme") was merged to apache:master on 2026-06-08, merge commit dc423b2, no milestone. It adds superset-frontend/src/embedded/getInitialThemeMode.ts, which reads the themeMode URL parameter (dark / system / default) and supplies it as initialMode to ThemeController in EmbeddedContextProviders. The PR states explicitly that no SDK changes are required, since urlParams already carries arbitrary parameters to the iframe.

The only SDK-repo file the PR touches is superset-embedded-sdk/README.md, which documents themeMode as a URL parameter with supported values default / dark / system. That documentation is present in the published @superset-ui/embedded-sdk@0.4.0 package.

Therefore the ask is not to build a capability — it is to serve a build that contains one. The deciding variable is whether the workspace's superset-frontend build includes getInitialThemeMode. It does not on 6.0.0.24, confirmed empirically. Open question for engineering: which Preset build carries dc423b2, and can it be brought forward.

Option 1 becomes optional ergonomics on top. Option 3 largely dissolves if the app starts in the correct mode.

Related, tracked separately

  • setThemeMode / setThemeConfig are shipped and functional but absent from Preset's embedding documentation. The published @preset-sdk/embedded README is a 19-line stub with no mention of theming. The replaceChildren mount-point behaviour is likewise undocumented. Documentation update in progress.

  • Service Worker registration failure (assets.preset.io scriptURL origin does not match the workspace host) appeared on every embedded load across all runs. Not theme-related, not yet classified, needs its own triage.


  • Attach files
  • +1