This is an automated email from the ASF dual-hosted git repository. maximebeauchemin 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 05994319b7 feat(theming): improving theme docs and configuration (#33851) 05994319b7 is described below commit 05994319b72d96facf065a4299b2ad9b79a25ab9 Author: Maxime Beauchemin <maximebeauche...@gmail.com> AuthorDate: Sun Jun 22 15:39:00 2025 -0700 feat(theming): improving theme docs and configuration (#33851) --- docs/docs/configuration/theming.mdx | 53 ++++++++++++++++++++++ .../src/components/ThemeEditor/index.tsx | 1 - .../packages/superset-ui-core/src/theme/types.ts | 5 +- superset-frontend/src/constants.ts | 2 +- superset-frontend/src/features/home/RightMenu.tsx | 1 - superset-frontend/src/preamble.ts | 12 +---- superset-frontend/src/types/bootstrapTypes.ts | 2 +- .../src/views/RootContextProviders.tsx | 4 ++ superset/config.py | 29 ++++++++---- superset/views/base.py | 2 +- 10 files changed, 84 insertions(+), 27 deletions(-) diff --git a/docs/docs/configuration/theming.mdx b/docs/docs/configuration/theming.mdx new file mode 100644 index 0000000000..7983b07d17 --- /dev/null +++ b/docs/docs/configuration/theming.mdx @@ -0,0 +1,53 @@ +--- +title: Theming +hide_title: true +sidebar_position: 12 +version: 1 +--- +# Theming Superset + +:::note +apache-superset>=6.0 +::: + +Superset now rides on **Ant Design v5’s token-based theming**. +Every Antd token works, plus a handful of Superset-specific ones for charts and dashboard chrome. + +## 1 — Create a theme + +1. Open the official [Ant Design Theme Editor](https://ant.design/theme-editor) +2. Design your palette, typography, and component overrides. +3. Open the `CONFIG` modal and paste the JSON. + +You can also extend with Superset-specific tokens (documented in the default theme object) before you import. + +## 2 — Apply it instance-wide + +```python +# superset_config.py +THEME = { + # Paste your JSON theme definition here +} +``` + +Restart Superset to apply changes + +## 3 — Tweak live in the app (beta) + +Set the feature flag in your `superset_config` +```python +DEFAULT_FEATURE_FLAGS: dict[str, bool] = { + {{ ... }} + THEME_ALLOW_THEME_EDITOR_BETA = True, +} +``` + +- Enables a JSON editor panel inside Superset as a new icon in the navbar +- Intended for testing/design and rapid in-context iteration +- End-user theme switching & preferences coming later + +## 4 — Potential Next Steps + +- CRUD UI for managing multiple themes +- Per-dashboard & per-workspace theme assignment +- User-selectable theme preferences diff --git a/superset-frontend/packages/superset-ui-core/src/components/ThemeEditor/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/ThemeEditor/index.tsx index 1a87688275..93dc0e9b53 100644 --- a/superset-frontend/packages/superset-ui-core/src/components/ThemeEditor/index.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/ThemeEditor/index.tsx @@ -67,7 +67,6 @@ const ThemeEditor: React.FC<ThemeEditorProps> = ({ const handleSave = (): void => { try { const parsedTheme = JSON.parse(jsonMetadata); - console.log('Parsed theme:', parsedTheme); setTheme?.(parsedTheme); setIsModalOpen(false); } catch (error) { diff --git a/superset-frontend/packages/superset-ui-core/src/theme/types.ts b/superset-frontend/packages/superset-ui-core/src/theme/types.ts index bd38d69985..10e75029bf 100644 --- a/superset-frontend/packages/superset-ui-core/src/theme/types.ts +++ b/superset-frontend/packages/superset-ui-core/src/theme/types.ts @@ -108,9 +108,6 @@ export interface LegacySupersetTheme { } export interface SupersetSpecificTokens { - // Brand-related - brandIconMaxWidth: number; - // Font-related fontSizeXS: string; fontSizeXXL: string; @@ -118,6 +115,8 @@ export interface SupersetSpecificTokens { fontWeightLight: string; fontWeightStrong: number; + // Brand-related + brandIconMaxWidth: number; brandLogoAlt: string; brandLogoUrl: string; brandLogoMargin: string; diff --git a/superset-frontend/src/constants.ts b/superset-frontend/src/constants.ts index 0900265d1e..093dde8ec2 100644 --- a/superset-frontend/src/constants.ts +++ b/superset-frontend/src/constants.ts @@ -141,7 +141,7 @@ export const DEFAULT_COMMON_BOOTSTRAP_DATA: CommonBootstrapData = { }, extra_categorical_color_schemes: [], extra_sequential_color_schemes: [], - theme_overrides: {}, + theme: {}, menu_data: { menu: [], brand: { diff --git a/superset-frontend/src/features/home/RightMenu.tsx b/superset-frontend/src/features/home/RightMenu.tsx index 9ea78f2f80..c3029b34e0 100644 --- a/superset-frontend/src/features/home/RightMenu.tsx +++ b/superset-frontend/src/features/home/RightMenu.tsx @@ -373,7 +373,6 @@ const RightMenu = ({ }; const theme = useTheme(); - return ( <StyledDiv align={align}> {canDatabase && ( diff --git a/superset-frontend/src/preamble.ts b/superset-frontend/src/preamble.ts index 1feca31546..d0ea972fb4 100644 --- a/superset-frontend/src/preamble.ts +++ b/superset-frontend/src/preamble.ts @@ -20,13 +20,7 @@ import { setConfig as setHotLoaderConfig } from 'react-hot-loader'; import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'; import dayjs from 'dayjs'; // eslint-disable-next-line no-restricted-imports -import { - configure, - makeApi, - initFeatureFlags, - // eslint-disable-next-line no-restricted-imports - themeObject, // TODO: DO not import theme directly -} from '@superset-ui/core'; +import { configure, makeApi, initFeatureFlags } from '@superset-ui/core'; import setupClient from './setup/setupClient'; import setupColors from './setup/setupColors'; import setupFormatters from './setup/setupFormatters'; @@ -68,10 +62,6 @@ setupFormatters( setupDashboardComponents(); -if (Object.keys(bootstrapData?.common?.theme_overrides || {}).length > 0) { - themeObject.setConfig(bootstrapData.common.theme_overrides); -} - const getMe = makeApi<void, User>({ method: 'GET', endpoint: '/api/v1/me/', diff --git a/superset-frontend/src/types/bootstrapTypes.ts b/superset-frontend/src/types/bootstrapTypes.ts index 1e943fcdbe..9f20b586d0 100644 --- a/superset-frontend/src/types/bootstrapTypes.ts +++ b/superset-frontend/src/types/bootstrapTypes.ts @@ -153,7 +153,7 @@ export interface CommonBootstrapData { language_pack: LanguagePack; extra_categorical_color_schemes: ColorSchemeConfig[]; extra_sequential_color_schemes: SequentialSchemeConfig[]; - theme_overrides: JsonObject; + theme: JsonObject; menu_data: MenuData; d3_format: Partial<FormatLocaleDefinition>; d3_time_format: Partial<TimeLocaleDefinition>; diff --git a/superset-frontend/src/views/RootContextProviders.tsx b/superset-frontend/src/views/RootContextProviders.tsx index 53ae497267..d27b271c44 100644 --- a/superset-frontend/src/views/RootContextProviders.tsx +++ b/superset-frontend/src/views/RootContextProviders.tsx @@ -32,6 +32,10 @@ import { store } from './store'; import '../preamble'; const { common } = getBootstrapData(); + +if (Object.keys(common?.theme || {}).length > 0) { + themeObject.setConfig(common.theme); +} const themeController = new ThemeController({ themeObject }); const extensionsRegistry = getExtensionsRegistry(); diff --git a/superset/config.py b/superset/config.py index 3df32995bc..c526d01bc2 100644 --- a/superset/config.py +++ b/superset/config.py @@ -551,7 +551,8 @@ DEFAULT_FEATURE_FLAGS: dict[str, bool] = { "PLAYWRIGHT_REPORTS_AND_THUMBNAILS": False, # Set to True to enable experimental chart plugins "CHART_PLUGINS_EXPERIMENTAL": False, - # Regardless of database configuration settings, force SQLLAB to run async using Celery # noqa: E501 + # Regardless of database configuration settings, force SQLLAB to run async + # using Celery "SQLLAB_FORCE_RUN_ASYNC": False, # Set to True to to enable factory resent CLI command "ENABLE_FACTORY_RESET_COMMAND": False, @@ -559,11 +560,17 @@ DEFAULT_FEATURE_FLAGS: dict[str, bool] = { # If on, you'll want to add "https://avatars.slack-edge.com" to the list of allowed # domains in your TALISMAN_CONFIG "SLACK_ENABLE_AVATARS": False, - # Adds a switch to the navbar to enable/disable the dark theme - # This is used for development to expose what is dynamic (css-in-js) vs - # what is managed by `.less` files. - "DARK_THEME_SWITCH": False, - # Allow users to optionally specify date formats in email subjects, which will be parsed if enabled. # noqa: E501 + # Adds a switch to the navbar to easily switch between light and dark themes. + # This is intended to use for development, visual review, and theming-debugging + # purposes. + "THEME_ENABLE_DARK_THEME_SWITCH": False, + # Adds a theme editor as a modal dialog in the navbar. Allows people to type in JSON + # and see the changes applied to the current theme. + # This is intended to use for theme creation, visual review and theming-debugging + # purposes. + "THEME_ALLOW_THEME_EDITOR_BETA": False, + # Allow users to optionally specify date formats in email subjects, which will + # be parsed if enabled "DATE_FORMAT_IN_EMAIL_SUBJECT": False, # Allow metrics and columns to be grouped into (potentially nested) folders in the # chart builder @@ -662,11 +669,17 @@ COMMON_BOOTSTRAP_OVERRIDES_FUNC: Callable[ # noqa: E731 # This is merely a default EXTRA_CATEGORICAL_COLOR_SCHEMES: list[dict[str, Any]] = [] -# THEME_OVERRIDES is used for adding custom theme to superset, it follows the ant design +# THEME is used for setting a custom theme to Superset, it follows the ant design # theme structure # You can use the AntDesign theme editor to generate a theme structure # https://ant.design/theme-editor -THEME_OVERRIDES: dict[str, Any] = {} +# To expose a JSON theme editor modal that can be triggered from the navbar +# set the `ENABLE_THEME_EDITOR` feature flag to True. +# +# To set up the dark theme: +# THEME = {"algorithm": "dark"} + +THEME: dict[str, Any] = {} # EXTRA_SEQUENTIAL_COLOR_SCHEMES is used for adding custom sequential color schemes # EXTRA_SEQUENTIAL_COLOR_SCHEMES = [ diff --git a/superset/views/base.py b/superset/views/base.py index 2b7dd076fa..8d31561775 100644 --- a/superset/views/base.py +++ b/superset/views/base.py @@ -371,7 +371,7 @@ def cached_common_bootstrap_data( # pylint: disable=unused-argument "feature_flags": get_feature_flags(), "extra_sequential_color_schemes": conf["EXTRA_SEQUENTIAL_COLOR_SCHEMES"], "extra_categorical_color_schemes": conf["EXTRA_CATEGORICAL_COLOR_SCHEMES"], - "theme_overrides": conf["THEME_OVERRIDES"], + "theme": conf["THEME"], "menu_data": menu_data(g.user), } bootstrap_data.update(conf["COMMON_BOOTSTRAP_OVERRIDES_FUNC"](bootstrap_data))