feat(theming): land Ant Design v5 overhaul — dynamic themes, real dark mode + massive styling refactor (#31590)

Co-authored-by: Enzo Martellucci <52219496+EnxDev@users.noreply.github.com>
Co-authored-by: Diego Pucci <diegopucci.me@gmail.com>
Co-authored-by: Mehmet Salih Yavuz <salih.yavuz@proton.me>
Co-authored-by: Geido <60598000+geido@users.noreply.github.com>
Co-authored-by: Alexandru Soare <37236580+alexandrusoare@users.noreply.github.com>
Co-authored-by: Damian Pendrak <dpendrak@gmail.com>
Co-authored-by: Pius Iniobong <67148161+payose@users.noreply.github.com>
Co-authored-by: Enzo Martellucci <enzomartellucci@gmail.com>
Co-authored-by: Kamil Gabryjelski <kamil.gabryjelski@gmail.com>
This commit is contained in:
Maxime Beauchemin
2025-06-20 13:38:58 -07:00
committed by GitHub
parent 2cc1ef88c8
commit dd129fa403
1267 changed files with 32958 additions and 23592 deletions

View File

@@ -36,14 +36,17 @@ import {
DatasourceType,
} from '@superset-ui/core';
import { ColumnMeta, isSavedExpression } from '@superset-ui/chart-controls';
import Tabs from 'src/components/Tabs';
import Button from 'src/components/Button';
import { Select } from 'src/components';
import Tabs from '@superset-ui/core/components/Tabs';
import {
Button,
Form,
FormItem,
Select,
SQLEditor,
EmptyState,
} from '@superset-ui/core/components';
import { Form, FormItem } from 'src/components/Form';
import sqlKeywords from 'src/SqlLab/utils/sqlKeywords';
import { SQLEditor } from 'src/components/AsyncAceEditor';
import { EmptyState } from 'src/components/EmptyState';
import { getColumnKeywords } from 'src/explore/controlUtils/getColumnKeywords';
import { StyledColumnOption } from 'src/explore/components/optionRenderers';
import {
@@ -53,10 +56,16 @@ import {
import { ExplorePageState } from 'src/explore/types';
import useResizeButton from './useResizeButton';
const TABS_KEYS = {
SAVED: 'saved',
SIMPLE: 'simple',
SQL_EXPRESSION: 'sqlExpression',
};
const StyledSelect = styled(Select)`
.metric-option {
& > svg {
min-width: ${({ theme }) => `${theme.gridUnit * 4}px`};
min-width: ${({ theme }) => `${theme.sizeUnit * 4}px`};
}
& > .option-label {
overflow: hidden;
@@ -306,164 +315,175 @@ const ColumnSelectPopover = ({
height: ${height}px;
width: ${width}px;
`}
>
<Tabs.TabPane
key="saved"
tab={t('Saved')}
disabled={disabledTabs.has('saved')}
>
{calculatedColumns.length > 0 ? (
<FormItem label={savedExpressionsLabel}>
<StyledSelect
ariaLabel={savedExpressionsLabel}
value={selectedCalculatedColumn?.column_name}
onChange={onCalculatedColumnChange}
allowClear
autoFocus={!selectedCalculatedColumn}
placeholder={t('%s column(s)', calculatedColumns.length)}
options={calculatedColumns.map(calculatedColumn => ({
value: calculatedColumn.column_name,
label:
calculatedColumn.verbose_name ||
calculatedColumn.column_name,
customLabel: (
<StyledColumnOption column={calculatedColumn} showType />
),
key: calculatedColumn.column_name,
}))}
/>
</FormItem>
) : datasourceType === DatasourceType.Table ? (
<EmptyState
image="empty.svg"
size="small"
title={
isTemporal
? t('No temporal columns found')
: t('No saved expressions found')
}
description={
isTemporal
? t(
'Add calculated temporal columns to dataset in "Edit datasource" modal',
)
: t(
'Add calculated columns to dataset in "Edit datasource" modal',
)
}
/>
) : (
<EmptyState
image="empty.svg"
size="small"
title={
isTemporal
? t('No temporal columns found')
: t('No saved expressions found')
}
description={
isTemporal ? (
<>
<span
role="button"
tabIndex={0}
onClick={setDatasetAndClose}
>
{t('Create a dataset')}
</span>{' '}
{t(' to mark a column as a time column')}
</>
items={[
{
key: TABS_KEYS.SAVED,
label: t('Saved'),
disabled: disabledTabs.has('saved'),
children: (
<>
{calculatedColumns.length > 0 ? (
<FormItem label={savedExpressionsLabel}>
<StyledSelect
ariaLabel={savedExpressionsLabel}
value={selectedCalculatedColumn?.column_name}
onChange={onCalculatedColumnChange}
allowClear
autoFocus={!selectedCalculatedColumn}
placeholder={t('%s column(s)', calculatedColumns.length)}
options={calculatedColumns.map(calculatedColumn => ({
value: calculatedColumn.column_name,
label: (
<StyledColumnOption
column={calculatedColumn}
showType
/>
),
key: calculatedColumn.column_name,
}))}
/>
</FormItem>
) : datasourceType === DatasourceType.Table ? (
<EmptyState
image="empty.svg"
size="small"
title={
isTemporal
? t('No temporal columns found')
: t('No saved expressions found')
}
description={
isTemporal
? t(
'Add calculated temporal columns to dataset in "Edit datasource" modal',
)
: t(
'Add calculated columns to dataset in "Edit datasource" modal',
)
}
/>
) : (
<>
<span
role="button"
tabIndex={0}
onClick={setDatasetAndClose}
>
{t('Create a dataset')}
</span>{' '}
{t(' to add calculated columns')}
</>
)
}
/>
)}
</Tabs.TabPane>
<Tabs.TabPane
key="simple"
tab={t('Simple')}
disabled={disabledTabs.has('simple')}
>
{isTemporal && simpleColumns.length === 0 ? (
<EmptyState
image="empty.svg"
size="small"
title={t('No temporal columns found')}
description={
datasourceType === DatasourceType.Table ? (
t('Mark a column as temporal in "Edit datasource" modal')
<EmptyState
image="empty.svg"
size="small"
title={
isTemporal
? t('No temporal columns found')
: t('No saved expressions found')
}
description={
isTemporal ? (
<>
<span
role="button"
tabIndex={0}
onClick={setDatasetAndClose}
>
{t('Create a dataset')}
</span>{' '}
{t(' to mark a column as a time column')}
</>
) : (
<>
<span
role="button"
tabIndex={0}
onClick={setDatasetAndClose}
>
{t('Create a dataset')}
</span>{' '}
{t(' to add calculated columns')}
</>
)
}
/>
)}
</>
),
},
{
key: TABS_KEYS.SIMPLE,
label: t('Simple'),
disabled: disabledTabs.has('simple'),
children: (
<>
{isTemporal && simpleColumns.length === 0 ? (
<EmptyState
image="empty.svg"
size="small"
title={t('No temporal columns found')}
description={
datasourceType === DatasourceType.Table ? (
t(
'Mark a column as temporal in "Edit datasource" modal',
)
) : (
<>
<span
role="button"
tabIndex={0}
onClick={setDatasetAndClose}
>
{t('Create a dataset')}
</span>{' '}
{t(' to mark a column as a time column')}
</>
)
}
/>
) : (
<>
<span
role="button"
tabIndex={0}
onClick={setDatasetAndClose}
>
{t('Create a dataset')}
</span>{' '}
{t(' to mark a column as a time column')}
</>
)
}
/>
) : (
<FormItem label={simpleColumnsLabel}>
<Select
ariaLabel={simpleColumnsLabel}
value={selectedSimpleColumn?.column_name}
onChange={onSimpleColumnChange}
allowClear
autoFocus={!selectedSimpleColumn}
placeholder={t('%s column(s)', simpleColumns.length)}
options={simpleColumns.map(simpleColumn => ({
value: simpleColumn.column_name,
label: simpleColumn.verbose_name || simpleColumn.column_name,
customLabel: (
<StyledColumnOption column={simpleColumn} showType />
),
key: simpleColumn.column_name,
}))}
/>
</FormItem>
)}
</Tabs.TabPane>
<FormItem label={simpleColumnsLabel}>
<Select
ariaLabel={simpleColumnsLabel}
value={selectedSimpleColumn?.column_name}
onChange={onSimpleColumnChange}
allowClear
autoFocus={!selectedSimpleColumn}
placeholder={t('%s column(s)', simpleColumns.length)}
options={simpleColumns.map(simpleColumn => ({
value: simpleColumn.column_name,
label: (
<StyledColumnOption column={simpleColumn} showType />
),
key: simpleColumn.column_name,
}))}
/>
</FormItem>
)}
</>
),
},
{
key: TABS_KEYS.SQL_EXPRESSION,
label: t('Custom SQL'),
disabled: disabledTabs.has('sqlExpression'),
children: (
<>
<SQLEditor
value={
adhocColumn?.sqlExpression ||
selectedSimpleColumn?.column_name ||
selectedCalculatedColumn?.expression
}
onFocus={onSqlEditorFocus}
showLoadingForImport
onChange={onSqlExpressionChange}
width="100%"
height={`${height - 80}px`}
showGutter={false}
editorProps={{ $blockScrolling: true }}
enableLiveAutocompletion
className="filter-sql-editor"
wrapEnabled
ref={sqlEditorRef}
keywords={keywords}
/>
</>
),
},
]}
/>
<Tabs.TabPane
key="sqlExpression"
tab={t('Custom SQL')}
disabled={disabledTabs.has('sqlExpression')}
>
<SQLEditor
value={
adhocColumn?.sqlExpression ||
selectedSimpleColumn?.column_name ||
selectedCalculatedColumn?.expression
}
onFocus={onSqlEditorFocus}
showLoadingForImport
onChange={onSqlExpressionChange}
width="100%"
height={`${height - 80}px`}
showGutter={false}
editorProps={{ $blockScrolling: true }}
enableLiveAutocompletion
className="filter-sql-editor"
wrapEnabled
ref={sqlEditorRef}
keywords={keywords}
/>
</Tabs.TabPane>
</Tabs>
<div>
<Button buttonSize="small" onClick={onResetStateAndClose} cta>
{t('Close')}

View File

@@ -18,14 +18,14 @@
*/
import { useCallback, useState } from 'react';
import { t, styled, useTheme } from '@superset-ui/core';
import { Input } from 'src/components/Input';
import { Tooltip } from 'src/components/Tooltip';
import { Icons } from 'src/components/Icons';
import { Input, Tooltip } from '@superset-ui/core/components';
import { Icons } from '@superset-ui/core/components/Icons';
const StyledInput = styled(Input)`
border-radius: ${({ theme }) => theme.borderRadius};
height: 26px;
padding-left: ${({ theme }) => theme.gridUnit * 2.5}px;
padding-left: ${({ theme }) => theme.sizeUnit * 2.5}px;
border-color: ${({ theme }) => theme.colorSplit};
`;
export const DndColumnSelectPopoverTitle = ({

View File

@@ -25,7 +25,6 @@ import {
QueryFormData,
} from '@superset-ui/core';
import { ColumnMeta } from '@superset-ui/chart-controls';
import { TimeseriesDefaultFormData } from '@superset-ui/plugin-chart-echarts';
import {
fireEvent,
@@ -33,7 +32,7 @@ import {
screen,
within,
} from 'spec/helpers/testing-library';
import type { AsyncAceEditorProps } from 'src/components/AsyncAceEditor';
import type { AsyncAceEditorProps } from '@superset-ui/core/components';
import AdhocMetric from 'src/explore/components/controls/MetricControl/AdhocMetric';
import AdhocFilter from 'src/explore/components/controls/FilterControl/AdhocFilter';
import { Operators } from 'src/explore/constants';
@@ -47,8 +46,8 @@ import { Datasource } from '../../../types';
import { DndItemType } from '../../DndItemType';
import DatasourcePanelDragOption from '../../DatasourcePanel/DatasourcePanelDragOption';
jest.mock('src/components/AsyncAceEditor', () => ({
...jest.requireActual('src/components/AsyncAceEditor'),
jest.mock('@superset-ui/core/components/AsyncAceEditor', () => ({
...jest.requireActual('@superset-ui/core/components/AsyncAceEditor'),
SQLEditor: (props: AsyncAceEditorProps) => (
<div data-test="react-ace">{props.value}</div>
),
@@ -127,7 +126,6 @@ test('renders options with saved metric', async () => {
setup({
formData: {
...baseFormData,
...TimeseriesDefaultFormData,
metrics: ['saved_metric'],
},
}),
@@ -172,7 +170,6 @@ test('renders options with adhoc metric', async () => {
setup({
formData: {
...baseFormData,
...TimeseriesDefaultFormData,
metrics: [adhocMetric],
},
}),
@@ -212,7 +209,6 @@ test('cannot drop a column that is not part of the simple column selection', ()
{setup({
formData: {
...baseFormData,
...TimeseriesDefaultFormData,
metrics: [adhocMetric],
},
columns: [{ column_name: 'order_date' }],
@@ -342,7 +338,6 @@ describe('when disallow_adhoc_metrics is set', () => {
{setup({
formData: {
...baseFormData,
...TimeseriesDefaultFormData,
metrics: [adhocMetric],
},
datasource: {
@@ -391,7 +386,6 @@ describe('when disallow_adhoc_metrics is set', () => {
{setup({
formData: {
...baseFormData,
...TimeseriesDefaultFormData,
metrics: [adhocMetric],
},
datasource: {

View File

@@ -30,7 +30,7 @@ import {
isColumnMeta,
isTemporalColumn,
} from '@superset-ui/chart-controls';
import Modal from 'src/components/Modal';
import { Modal } from '@superset-ui/core/components';
import {
OPERATOR_ENUM_TO_OPERATOR_TYPE,
Operators,

View File

@@ -18,7 +18,7 @@
*/
import { ReactNode, useCallback, useContext, useEffect, useMemo } from 'react';
import { useDrop } from 'react-dnd';
import { t, useTheme } from '@superset-ui/core';
import { t } from '@superset-ui/core';
import ControlHeader from 'src/explore/components/ControlHeader';
import {
AddControlLabel,
@@ -29,7 +29,7 @@ import {
DatasourcePanelDndItem,
DndItemValue,
} from 'src/explore/components/DatasourcePanel/types';
import { Icons } from 'src/components/Icons';
import { Icons } from '@superset-ui/core/components/Icons';
import { DndItemType } from '../../DndItemType';
import { DraggingContext, DropzoneContext } from '../../ExploreContainer';
@@ -54,7 +54,6 @@ export default function DndSelectLabel({
isLoading,
...props
}: DndSelectLabelProps) {
const theme = useTheme();
const canDropProp = props.canDrop;
const canDropValueProp = props.canDropValue;
@@ -100,13 +99,7 @@ export default function DndSelectLabel({
cancelHover={!props.onClickGhostButton}
onClick={props.onClickGhostButton}
>
<Icons.PlusOutlined
iconSize="m"
iconColor={theme.colors.grayscale.light1}
css={theme => ({
margin: `auto ${theme.gridUnit}px auto 0`,
})}
/>
<Icons.PlusOutlined iconSize="m" />
{t(props.ghostButtonText)}
</AddControlLabel>
);

View File

@@ -18,7 +18,7 @@
*/
import { useCallback } from 'react';
import { css, styled, t, useTheme } from '@superset-ui/core';
import { Icons } from 'src/components/Icons';
import { Icons, InfoTooltip } from '@superset-ui/core/components';
import {
CaretContainer,
CloseContainer,
@@ -26,10 +26,9 @@ import {
Label,
} from 'src/explore/components/controls/OptionControls';
import { OptionProps } from 'src/explore/components/controls/DndColumnSelectControl/types';
import { InfoTooltipWithTrigger } from '@superset-ui/chart-controls';
const StyledInfoTooltipWithTrigger = styled(InfoTooltipWithTrigger)`
margin: 0 ${({ theme }) => theme.gridUnit}px;
const StyledInfoTooltip = styled(InfoTooltip)`
margin: 0 ${({ theme }) => theme.sizeUnit}px;
`;
export default function Option({
@@ -71,10 +70,9 @@ export default function Option({
)}
<Label data-test="control-label">{children}</Label>
{(!!datasourceWarningMessage || isExtra) && (
<StyledInfoTooltipWithTrigger
icon="exclamation-triangle"
<StyledInfoTooltip
type="warning"
placement="top"
bsStyle="warning"
tooltip={
datasourceWarningMessage ||
t(`
@@ -89,7 +87,7 @@ export default function Option({
<Icons.RightOutlined
iconSize="m"
css={css`
margin-top: ${theme.gridUnit}px;
margin: ${theme.sizeUnit}px;
`}
iconColor={theme.colors.grayscale.light1}
/>

View File

@@ -28,7 +28,7 @@ import {
OptionProps,
OptionItemInterface,
} from 'src/explore/components/controls/DndColumnSelectControl/types';
import { Tooltip } from 'src/components/Tooltip';
import { Tooltip } from '@superset-ui/core/components';
import { StyledColumnOption } from 'src/explore/components/optionRenderers';
import { styled, isAdhocColumn } from '@superset-ui/core';
import { ColumnMeta } from '@superset-ui/chart-controls';

View File

@@ -29,6 +29,7 @@ import {
POPOVER_INITIAL_HEIGHT,
POPOVER_INITIAL_WIDTH,
} from 'src/explore/constants';
import { Icons } from '@superset-ui/core/components';
const RESIZE_THROTTLE_MS = 50;
@@ -132,14 +133,12 @@ export default function useResizeButton(
}, [onMouseUp]);
return [
// TODO: Remove fa-icon
// eslint-disable-next-line icons/no-fa-icons-usage
<i
<Icons.ArrowsAltOutlined
role="button"
aria-label="Resize"
tabIndex={0}
onMouseDown={onDragDown}
className="fa fa-expand edit-popover-resize text-muted"
className="edit-popover-resize"
/>,
width,
height,