You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by jl...@apache.org on 2025/11/17 18:30:09 UTC

(superset) branch master updated: feat(embedded): add setThemeMode API for dynamic theme switching (#36125)

This is an automated email from the ASF dual-hosted git repository.

jli pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 282f4e5de2 feat(embedded): add setThemeMode API for dynamic theme switching (#36125)
282f4e5de2 is described below

commit 282f4e5de2be345e5e9c7c5d439981fb53286dee
Author: Gabriel Torres Ruiz <ga...@gmail.com>
AuthorDate: Mon Nov 17 14:30:02 2025 -0400

    feat(embedded): add setThemeMode API for dynamic theme switching (#36125)
---
 superset-embedded-sdk/src/index.ts       | 18 +++++++++++++++-
 superset-frontend/src/embedded/index.tsx | 35 +++++++++++++++++++++++++++++++-
 2 files changed, 51 insertions(+), 2 deletions(-)

diff --git a/superset-embedded-sdk/src/index.ts b/superset-embedded-sdk/src/index.ts
index c04873924a..b9405393c5 100644
--- a/superset-embedded-sdk/src/index.ts
+++ b/superset-embedded-sdk/src/index.ts
@@ -81,6 +81,8 @@ export type ObserveDataMaskCallbackFn = (
     nativeFiltersChanged: boolean;
   },
 ) => void;
+export type ThemeMode = 'default' | 'dark' | 'system';
+
 export type EmbeddedDashboard = {
   getScrollSize: () => Promise<Size>;
   unmount: () => void;
@@ -92,6 +94,7 @@ export type EmbeddedDashboard = {
   getDataMask: () => Promise<Record<string, any>>;
   getChartStates: () => Promise<Record<string, any>>;
   setThemeConfig: (themeConfig: Record<string, any>) => void;
+  setThemeMode: (mode: ThemeMode) => void;
 };
 
 /**
@@ -265,6 +268,18 @@ export async function embedDashboard({
     }
   };
 
+  const setThemeMode = (mode: ThemeMode): void => {
+    try {
+      ourPort.emit('setThemeMode', { mode });
+      log(`Theme mode set to: ${mode}`);
+    } catch (error) {
+      log(
+        'Error sending theme mode. Ensure the iframe side implements the "setThemeMode" method.',
+      );
+      throw error;
+    }
+  };
+
   return {
     getScrollSize,
     unmount,
@@ -273,6 +288,7 @@ export async function embedDashboard({
     observeDataMask,
     getDataMask,
     getChartStates,
-    setThemeConfig
+    setThemeConfig,
+    setThemeMode,
   };
 }
diff --git a/superset-frontend/src/embedded/index.tsx b/superset-frontend/src/embedded/index.tsx
index 794cca051d..560aed5d0b 100644
--- a/superset-frontend/src/embedded/index.tsx
+++ b/superset-frontend/src/embedded/index.tsx
@@ -22,7 +22,7 @@ import { lazy, Suspense } from 'react';
 import ReactDOM from 'react-dom';
 import { BrowserRouter as Router, Route } from 'react-router-dom';
 import { makeApi, t, logging } from '@superset-ui/core';
-import { type SupersetThemeConfig } from '@apache-superset/core/ui';
+import { type SupersetThemeConfig, ThemeMode } from '@apache-superset/core/ui';
 import Switchboard from '@superset-ui/switchboard';
 import getBootstrapData, { applicationRoot } from 'src/utils/getBootstrapData';
 import setupClient from 'src/setup/setupClient';
@@ -264,6 +264,39 @@ window.addEventListener('message', function embeddedPageInitializer(event) {
       },
     );
 
+    Switchboard.defineMethod(
+      'setThemeMode',
+      (payload: { mode: 'default' | 'dark' | 'system' }) => {
+        const { mode } = payload;
+        log('Received setThemeMode request:', mode);
+
+        try {
+          const themeController = getThemeController();
+
+          const themeModeMap: Record<string, ThemeMode> = {
+            default: ThemeMode.DEFAULT,
+            dark: ThemeMode.DARK,
+            system: ThemeMode.SYSTEM,
+          };
+
+          const themeMode = themeModeMap[mode];
+          if (!themeMode) {
+            throw new Error(`Invalid theme mode: ${mode}`);
+          }
+
+          themeController.setThemeMode(themeMode);
+          return { success: true, message: `Theme mode set to ${mode}` };
+        } catch (error) {
+          logging.debug('Theme mode not changed:', error.message);
+          return {
+            success: false,
+            message: `Theme locked to current mode`,
+            silent: true,
+          };
+        }
+      },
+    );
+
     Switchboard.start();
   }
 });