feat(theming): improving theme docs and configuration (#33851)

This commit is contained in:
Maxime Beauchemin
2025-06-22 15:39:00 -07:00
committed by GitHub
parent a4f32f829d
commit 05994319b7
10 changed files with 84 additions and 27 deletions

View File

@@ -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 v5s 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

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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: {

View File

@@ -373,7 +373,6 @@ const RightMenu = ({
};
const theme = useTheme();
return (
<StyledDiv align={align}>
{canDatabase && (

View File

@@ -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/',

View File

@@ -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>;

View File

@@ -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();

View File

@@ -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 = [

View File

@@ -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))