You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ma...@apache.org on 2025/03/01 00:55:48 UTC
(superset) branch template_less updated: simplifying
This is an automated email from the ASF dual-hosted git repository.
maximebeauchemin pushed a commit to branch template_less
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/template_less by this push:
new a713bdf10f simplifying
a713bdf10f is described below
commit a713bdf10fdb14b302cce41cad9178db149504da
Author: Maxime Beauchemin <ma...@gmail.com>
AuthorDate: Fri Feb 28 16:54:05 2025 -0800
simplifying
---
.../packages/superset-ui-core/src/theme/Theme.tsx | 250 ++++++++-------------
.../packages/superset-ui-core/src/theme/index.tsx | 14 +-
.../packages/superset-ui-core/src/theme/types.ts | 27 +++
.../src/assets/stylesheets/antd/index.less | 20 +-
.../src/assets/stylesheets/less/variables.less | 42 ++--
superset-frontend/src/components/Tooltip/index.tsx | 6 +-
.../{TextAreaControl.jsx => TextAreaControl.tsx} | 8 +-
superset-frontend/src/features/home/RightMenu.tsx | 2 +-
8 files changed, 165 insertions(+), 204 deletions(-)
diff --git a/superset-frontend/packages/superset-ui-core/src/theme/Theme.tsx b/superset-frontend/packages/superset-ui-core/src/theme/Theme.tsx
index 1a03c97794..70caee50ae 100644
--- a/superset-frontend/packages/superset-ui-core/src/theme/Theme.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/theme/Theme.tsx
@@ -19,11 +19,7 @@
/* eslint-disable react-prefer-function-component/react-prefer-function-component */
// eslint-disable-next-line no-restricted-syntax
import React from 'react';
-import {
- theme as antdThemeImport,
- ThemeConfig as AntdThemeConfig,
- ConfigProvider,
-} from 'antd-v5';
+import { theme as antdThemeImport, ConfigProvider } from 'antd-v5';
import tinycolor from 'tinycolor2';
import {
@@ -31,21 +27,26 @@ import {
CacheProvider as EmotionCacheProvider,
} from '@emotion/react';
import createCache from '@emotion/cache';
-// import { merge } from 'lodash';
import {
- AntdTokens,
+ AntdThemeConfig,
+ AnyThemeConfig,
+ SerializableThemeConfig,
SupersetTheme,
allowedAntdTokens,
SharedAntdTokens,
- SystemColors,
ColorVariants,
- DeprecatedColorVariations,
DeprecatedThemeColors,
- LegacySupersetTheme,
FontSizeKey,
} from './types';
+import {
+ normalizeThemeConfig,
+ serializeThemeConfig,
+ getSystemColors,
+ getDeprecatedColors,
+} from './utils';
+
/* eslint-disable theme-colors/no-literal-colors */
export class Theme {
@@ -84,111 +85,30 @@ export class Theme {
xxl: 'fontSizeXXL',
};
- private constructor({
- seed,
- antdConfig,
- isDark = false,
- }: {
- seed?: Partial<SupersetTheme>;
- antdConfig?: AntdThemeConfig;
- isDark?: boolean;
- }) {
- this.updateTheme = this.updateTheme.bind(this);
+ private constructor({ config }: { config?: AnyThemeConfig }) {
this.SupersetThemeProvider = this.SupersetThemeProvider.bind(this);
- if (seed && antdConfig) {
- throw new Error('Pass either theme or antdConfig, not both.');
- } else if (antdConfig) {
- this.setThemeFromAntdConfig(antdConfig);
- } else if (seed) {
- this.setThemeFromSeed(seed || {}, isDark);
- }
- }
-
- static fromSeed(seed?: Partial<SupersetTheme>, isDark = false): Theme {
- const theme = new Theme({ seed, isDark });
- return theme;
- }
-
- static fromAntdConfig(antdConfig: AntdThemeConfig): Theme {
- const theme = new Theme({ antdConfig });
- return theme;
- }
-
- private static genDeprecatedColorVariations(
- color: string,
- isDark: boolean,
- ): DeprecatedColorVariations {
- const bg = isDark ? '#FFF' : '#000';
- const fg = isDark ? '#000' : '#FFF';
- const adjustColor = (c: string, perc: number, tgt: string): string =>
- tinycolor.mix(c, tgt, perc).toHexString();
- return {
- base: color,
- light1: adjustColor(color, 20, fg),
- light2: adjustColor(color, 45, fg),
- light3: adjustColor(color, 70, fg),
- light4: adjustColor(color, 90, fg),
- light5: adjustColor(color, 95, fg),
- dark1: adjustColor(color, 10, bg),
- dark2: adjustColor(color, 20, bg),
- dark3: adjustColor(color, 40, bg),
- dark4: adjustColor(color, 60, bg),
- dark5: adjustColor(color, 80, bg),
- };
- }
-
- private static getColors(
- systemColors: SystemColors,
- isDark: boolean,
- ): DeprecatedThemeColors {
- /* This method provides a set of color variations based on the system colors.
- * Goal is to deprecate usage of these in the future
- */
- const sc = systemColors;
- return {
- primary: Theme.genDeprecatedColorVariations(sc.colorPrimary, isDark),
- error: Theme.genDeprecatedColorVariations(sc.colorError, isDark),
- warning: Theme.genDeprecatedColorVariations(sc.colorWarning, isDark),
- success: Theme.genDeprecatedColorVariations(sc.colorSuccess, isDark),
- info: Theme.genDeprecatedColorVariations(sc.colorInfo, isDark),
- grayscale: Theme.genDeprecatedColorVariations('#666', isDark),
- };
- }
+ // Create a new config object with default tokens
+ const newConfig: AnyThemeConfig = config ? { ...config } : {};
- private static augmentSeedWithDefaults(
- seed: Partial<SupersetTheme>,
- ): Partial<SupersetTheme> {
- return {
+ // Ensure token property exists with defaults
+ newConfig.token = {
...Theme.defaultTokens,
- ...seed,
+ ...(config?.token || {}),
};
- }
- private static getSystemColors(antdTokens: SharedAntdTokens): SystemColors {
- return {
- colorPrimary: antdTokens.colorPrimary,
- colorError: antdTokens.colorError,
- colorWarning: antdTokens.colorWarning,
- colorSuccess: antdTokens.colorSuccess,
- colorInfo: antdTokens.colorInfo,
- };
+ this.setConfig(newConfig);
}
- private static getSupersetTheme(
- seed: Partial<SupersetTheme>,
- isDark = false,
- ): SupersetTheme {
- const antdConfig = Theme.getAntdConfig(seed, isDark);
- const antdTokens = Theme.getFilteredAntdTheme(antdConfig);
- const systemColors = Theme.getSystemColors(antdTokens);
-
- const theme: SupersetTheme = {
- colors: Theme.getColors(systemColors, isDark),
- ...Theme.defaultTokens,
- ...antdTokens,
- };
- return theme;
+ /**
+ * Create a theme from any theme configuration
+ * Automatically handles both AntdThemeConfig and SerializableThemeConfig
+ * If simple tokens are provided as { token: {...} }, they will be applied with defaults
+ * If no config is provided, uses default tokens
+ * Dark mode can be set via the algorithm property in the config
+ */
+ static fromConfig(config?: AnyThemeConfig): Theme {
+ return new Theme({ config });
}
private static getFilteredAntdTheme(
@@ -202,29 +122,45 @@ export class Theme {
) as SharedAntdTokens;
}
- private static getAntdConfig(
- seed: Partial<SupersetTheme>,
- isDark: boolean,
- ): AntdThemeConfig {
- const algorithm = isDark
- ? antdThemeImport.darkAlgorithm
- : antdThemeImport.defaultAlgorithm;
- return {
- token: seed,
- algorithm,
- };
+ private static getAntdTokens(
+ antdConfig: AntdThemeConfig,
+ ): Record<string, any> {
+ return antdThemeImport.getDesignToken(antdConfig);
}
- mergeTheme(partialTheme: Partial<LegacySupersetTheme>): void {
- // const mergedTheme = merge({}, this.theme, partialTheme);
- // const isDark = tinycolor(mergedTheme.colorBgBase).isDark();
- // const antdConfig = Theme.getAntdConfig(systemColors, isDark);
- // this.updateTheme(mergedTheme, antdConfig, isDark);
- }
+ /**
+ * Update the theme using any theme configuration
+ * Automatically handles both AntdThemeConfig and SerializableThemeConfig
+ * Dark mode should be specified via the algorithm property in the config
+ */
+ setConfig(config: AnyThemeConfig): void {
+ const antdConfig = normalizeThemeConfig(config);
- private updateTheme(theme: SupersetTheme, antdConfig: AntdThemeConfig): void {
- this.theme = theme;
+ // Apply default tokens to token property
+ antdConfig.token = {
+ ...Theme.defaultTokens,
+ ...(antdConfig.token || {}),
+ };
+
+ // First phase: Let Ant Design compute the tokens
+ const tokens = Theme.getFilteredAntdTheme(antdConfig);
+
+ // Set the base theme properties
this.antdConfig = antdConfig;
+ this.theme = {
+ ...Theme.defaultTokens,
+ ...antdConfig.token, // Passing through the extra, superset-specific tokens
+ ...tokens,
+ colors: {} as DeprecatedThemeColors, // Placeholder that will be filled in the second phase
+ };
+
+ // Second phase: Now that theme is initialized, we can determine if it's dark
+ // and generate the legacy colors correctly
+ const systemColors = getSystemColors(tokens);
+ const isDark = this.isThemeDark(); // Now we can safely call this
+ this.theme.colors = getDeprecatedColors(systemColors, isDark);
+
+ // Update the providers with the fully formed theme
this.updateProviders(
this.theme,
this.antdConfig,
@@ -232,6 +168,13 @@ export class Theme {
);
}
+ /**
+ * Export the current theme as a serializable configuration
+ */
+ toSerializedConfig(): SerializableThemeConfig {
+ return serializeThemeConfig(this.antdConfig);
+ }
+
private getToken(token: string): any {
return (this.theme as Record<string, any>)[token];
}
@@ -241,37 +184,40 @@ export class Theme {
return this.getToken(fontSizeKey) || this.getToken('fontSize');
}
- private static getAntdTokens(antdConfig: AntdThemeConfig): AntdTokens {
- return antdThemeImport.getDesignToken(antdConfig);
- }
-
- private isThemeDark(): boolean {
+ /**
+ * Check if the current theme is dark based on background color
+ */
+ isThemeDark(): boolean {
return tinycolor(this.theme.colorBgContainer).isDark();
}
- setThemeFromSeed(seed: Partial<SupersetTheme>, isDark: boolean): void {
- const augmentedSeed = Theme.augmentSeedWithDefaults(seed);
- const theme = Theme.getSupersetTheme(augmentedSeed, isDark);
- const antdConfig = Theme.getAntdConfig(augmentedSeed, isDark);
- this.updateTheme(theme, antdConfig);
- }
+ toggleDarkMode(isDark: boolean): void {
+ // Create a new config based on the current one
+ const newConfig = { ...this.antdConfig };
- setThemeFromAntdConfig(antdConfig: AntdThemeConfig): void {
- this.antdConfig = antdConfig;
- const tokens = Theme.getFilteredAntdTheme(antdConfig);
- const systemColors = Theme.getSystemColors(tokens);
- const isDark = this.isThemeDark();
+ // Determine the new algorithm based on isDark
+ const newAlgorithm = isDark
+ ? antdThemeImport.darkAlgorithm
+ : antdThemeImport.defaultAlgorithm;
- this.theme = {
- colors: Theme.getColors(systemColors, isDark),
- ...Theme.defaultTokens,
- ...tokens,
- };
- this.updateProviders(
- this.theme,
- this.antdConfig,
- createCache({ key: 'superset' }),
- );
+ // Handle the case where algorithm is an array
+ if (Array.isArray(newConfig.algorithm)) {
+ // Filter out any existing dark/default algorithms
+ const otherAlgorithms = newConfig.algorithm.filter(
+ alg =>
+ alg !== antdThemeImport.darkAlgorithm &&
+ alg !== antdThemeImport.defaultAlgorithm,
+ );
+
+ // Add the new algorithm to the front of the array
+ newConfig.algorithm = [newAlgorithm, ...otherAlgorithms];
+ } else {
+ // Simple case: just replace the algorithm
+ newConfig.algorithm = newAlgorithm;
+ }
+
+ // Update the theme with the new configuration
+ this.setConfig(newConfig);
}
getColorVariants(color: string): ColorVariants {
diff --git a/superset-frontend/packages/superset-ui-core/src/theme/index.tsx b/superset-frontend/packages/superset-ui-core/src/theme/index.tsx
index 6bc1439b8e..56fccafb55 100644
--- a/superset-frontend/packages/superset-ui-core/src/theme/index.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/theme/index.tsx
@@ -51,19 +51,7 @@ export function useTheme() {
const styled = emotionStyled;
// launching in in dark mode for now while iterating
-const themeObject = Theme.fromSeed({}, false);
-/*
-const themeObject = Theme.fromSeed({
- token: {
- colorPrimary: '#20a7c9',
- colorError: '#e04355',
- colorWarning: '#fcc700',
- colorSuccess: '#5ac189',
- colorInfo: '#66bcfe',
- },
- algorithm: antdThemeImport.defaultAlgorithm,
-});
- */
+const themeObject = Theme.fromConfig({});
const { theme } = themeObject;
const supersetTheme = theme;
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 499b90bd9b..5fe97e664d 100644
--- a/superset-frontend/packages/superset-ui-core/src/theme/types.ts
+++ b/superset-frontend/packages/superset-ui-core/src/theme/types.ts
@@ -20,11 +20,38 @@
// eslint-disable-next-line no-restricted-syntax
import { theme as antdThemeImport } from 'antd-v5';
+/**
+ * Get AntdThemeConfig type from the theme object
+ */
+import type { ThemeConfig } from 'antd-v5';
+
/**
* Grab all antd tokens via getDesignToken(...).
* (Same as in the original file.)
*/
export type AntdTokens = ReturnType<typeof antdThemeImport.getDesignToken>;
+export type AntdThemeConfig = ThemeConfig;
+
+/**
+ * A serializable version of Ant Design's ThemeConfig
+ * Compatible with theme editor exports
+ */
+export type SerializableThemeConfig = {
+ token?: Record<string, any>;
+ components?: Record<string, any>;
+ algorithm?:
+ | 'default'
+ | 'dark'
+ | 'compact'
+ | ('default' | 'dark' | 'compact')[];
+ hashed?: boolean;
+ inherit?: boolean;
+};
+
+/**
+ * A combined type that can be either a regular AntdThemeConfig or a SerializableThemeConfig
+ */
+export type AnyThemeConfig = AntdThemeConfig | SerializableThemeConfig;
/** Minimal color system references. */
export type FontSizeKey = 'xs' | 's' | 'm' | 'l' | 'xl' | 'xxl';
diff --git a/superset-frontend/src/assets/stylesheets/antd/index.less b/superset-frontend/src/assets/stylesheets/antd/index.less
index cc97a40751..ae9f0c1e6e 100644
--- a/superset-frontend/src/assets/stylesheets/antd/index.less
+++ b/superset-frontend/src/assets/stylesheets/antd/index.less
@@ -35,7 +35,7 @@
Theme variables here: https://github.com/ant-design/ant-design/blob/master/components/style/themes/default.less
*/
/* Core Colors */
-@primary-color: #20a7c9;
+@primary-color: #007aa0;
@info-color: #66bcfe;
@processing-color: #525252;
@success-color: #5ac189;
@@ -44,17 +44,17 @@
@normal-color: #d1d1d1;
// Menu-related
-@menu-highlight-color: #20a7c9;
+@menu-highlight-color: #007aa0;
@menu-item-active-bg: ;
-@menu-item-color: #136479;
+@menu-item-color: #004960;
@menu-popup-bg: #ffffff;
@menu-bg: #ffffff;
@tabs-card-head-background: #ffffff;
@component-background: #ffffff;
-@select-item-selected-bg: #f0feff;
-@select-item-active-bg: #f0feff;
-@select-item-hover-bg: #f0feff;
+@select-item-selected-bg: #cadfe0;
+@select-item-active-bg: #cadfe0;
+@select-item-hover-bg: #cadfe0;
@item-hover-bg: #ffffff;
@menu-item-hover-bg: #ffffff;
@@ -87,7 +87,7 @@
@border-radius-lg: 8;
/* Buttons */
-@btn-primary-bg: #20a7c9;
+@btn-primary-bg: #007aa0;
@btn-default-bg: #ffffff;
@btn-default-border: #d9d9d9;
@btn-danger-bg: #e04355;
@@ -96,7 +96,7 @@
/* Inputs */
//@input-bg: ;
@input-border-color: #d9d9d9;
-@input-hover-border-color: #6dd3e3;
+@input-hover-border-color: #3ca5ba;
/* Menus */
@menu-bg: #ffffff;
@@ -105,7 +105,7 @@
@menu-inline-submenu-bg: #ffffff;
@menu-highlight-color: rgba(0,0,0,0.88);
@menu-highlight-danger-color: #e04355;
-@menu-item-active-bg: #20a7c9;
+@menu-item-active-bg: #007aa0;
@menu-item-active-danger-bg: #fff0f0;
@menu-item-group-title-color: rgba(0,0,0,0.88);
@@ -122,7 +122,7 @@
/* Tables */
@table-header-bg: #ffffff;
@table-row-hover-bg: #ffffff;
-@table-selected-row-bg: #f0feff;
+@table-selected-row-bg: #cadfe0;
/* Motion */
@motion-duration-fast: 0.1s;
diff --git a/superset-frontend/src/assets/stylesheets/less/variables.less b/superset-frontend/src/assets/stylesheets/less/variables.less
index 5fc8086b6b..4423211c56 100644
--- a/superset-frontend/src/assets/stylesheets/less/variables.less
+++ b/superset-frontend/src/assets/stylesheets/less/variables.less
@@ -21,33 +21,33 @@
/* COLORS */
/************************************************************************/
-@primary-color: #20a7c9;
+@primary-color: #007aa0;
@indicator-color: @primary-color;
-@brand-primary-dark1: #20a7c9;
-@brand-primary-dark2: #1a86a1;
-@brand-primary-light1: #4db9d4;
-@brand-primary-light2: #84cfe1;
-@brand-primary-light3: #bce5ef;
-@brand-primary-light4: #e9f6fa;
-@brand-primary-light5: #f4fbfc;
-
-@brand-secondary: #20a7c9;
-@brand-secondary-dark1: #20a7c9;
-@brand-secondary-dark2: #1a86a1;
-@brand-secondary-dark3: #136479;
-@brand-secondary-light1: #4db9d4;
-@brand-secondary-light2: #84cfe1;
-@brand-secondary-light3: #bce5ef;
-@brand-secondary-light4: #e9f6fa;
-@brand-secondary-light5: #f4fbfc;
+@brand-primary-dark1: #007aa0;
+@brand-primary-dark2: #006280;
+@brand-primary-light1: #3395b3;
+@brand-primary-light2: #73b6cb;
+@brand-primary-light3: #b3d7e3;
+@brand-primary-light4: #e6f2f6;
+@brand-primary-light5: #f2f8fa;
+
+@brand-secondary: #007aa0;
+@brand-secondary-dark1: #007aa0;
+@brand-secondary-dark2: #006280;
+@brand-secondary-dark3: #004960;
+@brand-secondary-light1: #3395b3;
+@brand-secondary-light2: #73b6cb;
+@brand-secondary-light3: #b3d7e3;
+@brand-secondary-light4: #e6f2f6;
+@brand-secondary-light5: #f2f8fa;
// TODO line up with theme
@almost-black: #141414;
@gray-dark: #3d3d3d;
@gray-light: #f0f0f0;
@gray-light5: #f7f7f7;
-@gray: #20a7c9;
+@gray: #007aa0;
@gray-bg: #f0f0f0;
@gray-heading: rgba(0,0,0,0.88);
@menu-hover: rgba(0,0,0,0.88);
@@ -59,8 +59,8 @@
/**************************** text-specific *****************************/
@text-color: #000;
@heading-color: #000;
-@link: #20a7c9;
-@link-hover: #1a86a1;
+@link: #007aa0;
+@link-hover: #006280;
/***************************** status colors ****************************/
@info: #66bcfe;
diff --git a/superset-frontend/src/components/Tooltip/index.tsx b/superset-frontend/src/components/Tooltip/index.tsx
index 615ad802e7..528bfc475b 100644
--- a/superset-frontend/src/components/Tooltip/index.tsx
+++ b/superset-frontend/src/components/Tooltip/index.tsx
@@ -18,9 +18,11 @@
*/
import { supersetTheme } from '@superset-ui/core';
import { Tooltip as AntdTooltip } from 'antd-v5';
-import { TooltipProps, TooltipPlacement } from 'antd-v5/lib/tooltip';
+import type { TooltipProps } from 'antd-v5';
-export { TooltipProps, TooltipPlacement };
+// Re-export the types
+export type { TooltipProps };
+export type { TooltipPlacement } from 'antd-v5';
export const Tooltip = ({ overlayStyle, ...props }: TooltipProps) => (
<AntdTooltip
diff --git a/superset-frontend/src/explore/components/controls/TextAreaControl.jsx b/superset-frontend/src/explore/components/controls/TextAreaControl.tsx
similarity index 95%
rename from superset-frontend/src/explore/components/controls/TextAreaControl.jsx
rename to superset-frontend/src/explore/components/controls/TextAreaControl.tsx
index e8f165c8e1..9f8200c8e5 100644
--- a/superset-frontend/src/explore/components/controls/TextAreaControl.jsx
+++ b/superset-frontend/src/explore/components/controls/TextAreaControl.tsx
@@ -19,10 +19,8 @@
import { Component } from 'react';
import PropTypes from 'prop-types';
import { TextArea } from 'src/components/Input';
-import {
- Tooltip,
- TooltipProps as TooltipOptions,
-} from 'src/components/Tooltip';
+import { Tooltip } from 'src/components/Tooltip';
+import type { TooltipProps } from 'antd-v5'; // Import directly from antd-v5
import { t, withTheme } from '@superset-ui/core';
import Button from 'src/components/Button';
@@ -59,7 +57,7 @@ const propTypes = {
'vertical',
]),
textAreaStyles: PropTypes.object,
- tooltipOptions: PropTypes.oneOf([null, TooltipOptions]),
+ tooltipOptions: PropTypes.object, // Changed from PropTypes.oneOf to PropTypes.object
};
const defaultProps = {
diff --git a/superset-frontend/src/features/home/RightMenu.tsx b/superset-frontend/src/features/home/RightMenu.tsx
index 4aac551601..3c496c2776 100644
--- a/superset-frontend/src/features/home/RightMenu.tsx
+++ b/superset-frontend/src/features/home/RightMenu.tsx
@@ -482,7 +482,7 @@ const RightMenu = ({
<span>
<Switch
onChange={(checked: boolean) => {
- themeObject.setThemeFromSeed({}, checked);
+ themeObject.toggleDarkMode(checked);
}}
/>
</span>