refactor(Popover): Upgrade Popover to Antd5 (#31973)

Co-authored-by: Geido <60598000+geido@users.noreply.github.com>
This commit is contained in:
Alexandru Soare 2025-02-10 16:38:17 +02:00 committed by GitHub
parent 06f8f8e608
commit 0030f46d2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 157 additions and 228 deletions

View File

@ -161,7 +161,7 @@ describe('Horizontal FilterBar', () => {
cy.getBySel('filter-control-name')
.contains('test_12')
.should('not.be.visible');
cy.get('.ant-popover-inner-content').scrollTo('bottom');
cy.get('.antd5-popover-inner').scrollTo('bottom');
cy.getBySel('filter-control-name').contains('test_12').should('be.visible');
});
@ -226,7 +226,7 @@ describe('Horizontal FilterBar', () => {
cy.getBySel('slice-header').within(() => {
cy.get('.filter-counts').trigger('mouseover');
});
cy.get('.filterStatusPopover').contains('test_9').click();
cy.getBySel('filter-status-popover').contains('test_9').click();
cy.getBySel('dropdown-content').should('be.visible');
cy.get('.ant-select-focused').should('be.visible');
});

View File

@ -456,19 +456,19 @@ export function applyAdvancedTimeRangeFilterOnDashboard(
endRange?: string,
) {
cy.get('.control-label').contains('RANGE TYPE').should('be.visible');
cy.get('.ant-popover-content .ant-select-selector')
cy.get('.antd5-popover-content .ant-select-selector')
.should('be.visible')
.click();
cy.get(`[label="Advanced"]`).should('be.visible').click();
cy.get('.section-title').contains('Advanced Time Range').should('be.visible');
if (startRange) {
cy.get('.ant-popover-inner-content')
cy.get('.antd5-popover-inner-content')
.find('[class^=ant-input]')
.first()
.type(`${startRange}`);
}
if (endRange) {
cy.get('.ant-popover-inner-content')
cy.get('.antd5-popover-inner-content')
.find('[class^=ant-input]')
.last()
.type(`${endRange}`);

View File

@ -555,7 +555,7 @@ export const exploreView = {
timeSection: {
timeRangeFilter: dataTestLocator('time-range-trigger'),
timeRangeFilterModal: {
container: '.ant-popover-content',
container: '.antd5-popover-content',
footer: '.footer',
cancelButton: dataTestLocator('cancel-button'),
configureLastTimeRange: {

View File

@ -17,9 +17,9 @@
* under the License.
*/
import { useEffect, useState } from 'react';
import { Popover } from 'antd';
import { Popover } from 'antd-v5';
import type ReactAce from 'react-ace';
import type { PopoverProps } from 'antd/lib/popover';
import type { PopoverProps } from 'antd-v5/lib/popover';
import { CalculatorOutlined } from '@ant-design/icons';
import { css, styled, useTheme, t } from '@superset-ui/core';
@ -72,7 +72,7 @@ export const SQLPopover = (props: PopoverProps & { sqlExpression: string }) => {
/>
}
placement="bottomLeft"
arrowPointAtCenter
arrow={{ pointAtCenter: true }}
title={t('SQL expression')}
{...props}
>

View File

@ -39,14 +39,18 @@ export const GlobalStyles = () => (
.echarts-tooltip[style*='visibility: hidden'] {
display: none !important;
}
// Ant Design is applying inline z-index styles causing troubles
// TODO: Remove z-indexes when Ant Design is fully upgraded to v5
// Prefer vanilla Ant Design z-indexes that should work out of the box
.ant-popover,
.antd5-dropdown,
.ant-dropdown,
.ant-select-dropdown,
.antd5-modal-wrap,
.antd5-modal-mask,
.antd5-picker-dropdown {
.antd5-picker-dropdown,
.ant-popover,
.antd5-popover {
z-index: ${theme.zIndex.max} !important;
}

View File

@ -137,7 +137,6 @@ const DropdownContainer = forwardRef(
const { current } = ref;
const [itemsWidth, setItemsWidth] = useState<number[]>([]);
const [popoverVisible, setPopoverVisible] = useState(false);
// We use React.useState to be able to mock the state in Jest
const [overflowingIndex, setOverflowingIndex] = useState<number>(-1);
@ -181,11 +180,13 @@ const DropdownContainer = forwardRef(
);
useLayoutEffect(() => {
if (popoverVisible) {
return;
}
const container = current?.children.item(0);
if (container) {
const { children } = container;
const childrenArray = Array.from(children);
// If items length change, add all items to the container
// and recalculate the widths
if (itemsWidth.length !== items.length) {
@ -341,11 +342,7 @@ const DropdownContainer = forwardRef(
<>
<Global
styles={css`
.ant-popover-inner-content {
max-height: ${MAX_HEIGHT}px;
overflow: ${showOverflow ? 'auto' : 'visible'};
padding: ${theme.gridUnit * 3}px ${theme.gridUnit * 4}px;
.antd5-popover-inner {
// Some OS versions only show the scroll when hovering.
// These settings will make the scroll always visible.
::-webkit-scrollbar {
@ -365,11 +362,16 @@ const DropdownContainer = forwardRef(
}
`}
/>
<Popover
overlayInnerStyle={{
maxHeight: `${MAX_HEIGHT}px`,
overflow: showOverflow ? 'auto' : 'visible',
}}
content={popoverContent}
trigger="click"
visible={popoverVisible}
onVisibleChange={visible => setPopoverVisible(visible)}
open={popoverVisible}
onOpenChange={visible => setPopoverVisible(visible)}
placement="bottom"
forceRender={forceRender}
>

View File

@ -17,8 +17,7 @@
* under the License.
*/
import Button from 'src/components/Button';
import { PopoverProps } from 'antd/lib/popover';
import Popover from '.';
import Popover, { PopoverProps } from 'src/components/Popover';
export default {
title: 'Popover',
@ -66,6 +65,8 @@ const TRIGGERS = {
InteractivePopover.args = {
content: 'Popover sample content',
title: 'Popover title',
arrow: true,
color: '#fff',
};
InteractivePopover.argTypes = {
@ -79,4 +80,14 @@ InteractivePopover.argTypes = {
control: { type: 'select' },
options: TRIGGERS.options,
},
arrow: {
name: 'arrow',
control: { type: 'boolean' },
description: "Change arrow's visible state",
},
color: {
name: 'color',
control: { type: 'color' },
description: 'The background color of the popover.',
},
};

View File

@ -21,7 +21,7 @@ import userEvent from '@testing-library/user-event';
import { supersetTheme } from '@superset-ui/core';
import Icons from 'src/components/Icons';
import Button from 'src/components/Button';
import Popover from '.';
import Popover from 'src/components/Popover';
test('should render', () => {
const { container } = render(<Popover />);
@ -29,12 +29,12 @@ test('should render', () => {
});
test('should render a title when visible', () => {
render(<Popover title="Popover title" visible />);
render(<Popover title="Popover title" open />);
expect(screen.getByText('Popover title')).toBeInTheDocument();
});
test('should render some content when visible', () => {
render(<Popover content="Content sample" visible />);
render(<Popover content="Content sample" open />);
expect(screen.getByText('Content sample')).toBeInTheDocument();
});
@ -61,22 +61,22 @@ test('renders with icon child', async () => {
});
test('fires an event when visibility is changed', async () => {
const onVisibleChange = jest.fn();
const onOpenChange = jest.fn();
render(
<Popover
content="Content sample"
title="Popover title"
onVisibleChange={onVisibleChange}
onOpenChange={onOpenChange}
>
<Button>Hover me</Button>
</Popover>,
);
userEvent.hover(screen.getByRole('button'));
await waitFor(() => expect(onVisibleChange).toHaveBeenCalledTimes(1));
await waitFor(() => expect(onOpenChange).toHaveBeenCalledTimes(1));
});
test('renders with theme', () => {
render(<Popover content="Content sample" title="Popover title" visible />);
render(<Popover content="Content sample" title="Popover title" open />);
const title = screen.getByText('Popover title');
expect(title).toHaveStyle({
fontSize: supersetTheme.gridUnit * 3.5,

View File

@ -1,27 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { Popover as AntdPopover } from 'antd';
import type { PopoverProps as AntdPopoverProps } from 'antd/lib/popover';
export interface PopoverProps extends AntdPopoverProps {
forceRender?: boolean;
}
export const Popover = (props: PopoverProps) => <AntdPopover {...props} />;

View File

@ -16,9 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
export type { PopoverProps } from 'antd/lib/popover';
export type { TooltipPlacement } from 'antd/lib/tooltip';
import { Popover as AntdPopover } from 'antd-v5';
import { PopoverProps as AntdPopoverProps } from 'antd-v5/lib/popover';
// Eventually Popover can be wrapped and customized in this file
// for now we're just redirecting
export { Popover as default } from './Popover';
export interface PopoverProps extends AntdPopoverProps {
forceRender?: boolean;
}
const Popover = (props: PopoverProps) => <AntdPopover {...props} />;
export default Popover;

View File

@ -44,7 +44,7 @@ function HeaderWithRadioGroup(props: HeaderWithRadioGroupProps) {
>
<Popover
trigger="click"
visible={popoverVisible}
open={popoverVisible}
content={
<div>
<div
@ -72,7 +72,7 @@ function HeaderWithRadioGroup(props: HeaderWithRadioGroupProps) {
</div>
}
placement="bottomLeft"
arrowPointAtCenter
arrow={{ pointAtCenter: true }}
>
<Icons.SettingOutlined
iconSize="m"

View File

@ -30,7 +30,6 @@ import {
useTheme,
useElementOnScreen,
} from '@superset-ui/core';
import { Global } from '@emotion/react';
import { useDispatch, useSelector } from 'react-redux';
import ErrorBoundary from 'src/components/ErrorBoundary';
import BuilderComponentPane from 'src/dashboard/components/BuilderComponentPane';
@ -653,13 +652,6 @@ const DashboardBuilder = () => {
</Droppable>
</StyledHeader>
<StyledContent fullSizeChartId={fullSizeChartId}>
<Global
styles={css`
// @z-index-above-dashboard-header (100) + 1 = 101
${fullSizeChartId &&
`div > .filterStatusPopover.ant-popover{z-index: 101}`}
`}
/>
{!editMode &&
!topLevelTabs &&
dashboardLayout[DASHBOARD_GRID_ID]?.children?.length === 0 && (

View File

@ -19,8 +19,7 @@
import { RefObject, useEffect, useRef, KeyboardEvent } from 'react';
import { useSelector } from 'react-redux';
import { Global, css } from '@emotion/react';
import { t } from '@superset-ui/core';
import { t, useTheme } from '@superset-ui/core';
import Popover from 'src/components/Popover';
import {
FiltersContainer,
@ -120,7 +119,7 @@ const DetailsPanelPopover = ({
const indicatorKey = (indicator: Indicator): string =>
`${indicator.column} - ${indicator.name}`;
const theme = useTheme();
const content = (
<FiltersDetailsContainer
ref={popoverContentRef}
@ -129,54 +128,6 @@ const DetailsPanelPopover = ({
onKeyDown={handleKeyDown}
role="menu"
>
<Global
styles={theme => css`
.filterStatusPopover {
.ant-popover-inner {
background-color: ${theme.colors.grayscale.dark2}cc;
.ant-popover-inner-content {
padding: ${theme.gridUnit * 2}px;
}
}
&.ant-popover-placement-bottom,
&.ant-popover-placement-bottomLeft,
&.ant-popover-placement-bottomRight {
& > .ant-popover-content > .ant-popover-arrow {
border-top-color: ${theme.colors.grayscale.dark2}cc;
border-left-color: ${theme.colors.grayscale.dark2}cc;
}
}
&.ant-popover-placement-top,
&.ant-popover-placement-topLeft,
&.ant-popover-placement-topRight {
& > .ant-popover-content > .ant-popover-arrow {
border-bottom-color: ${theme.colors.grayscale.dark2}cc;
border-right-color: ${theme.colors.grayscale.dark2}cc;
}
}
&.ant-popover-placement-left,
&.ant-popover-placement-leftTop,
&.ant-popover-placement-leftBottom {
& > .ant-popover-content > .ant-popover-arrow {
border-top-color: ${theme.colors.grayscale.dark2}cc;
border-right-color: ${theme.colors.grayscale.dark2}cc;
}
}
&.ant-popover-placement-right,
&.ant-popover-placement-rightTop,
&.ant-popover-placement-rightBottom {
& > .ant-popover-content > .ant-popover-arrow {
border-bottom-color: ${theme.colors.grayscale.dark2}cc;
border-left-color: ${theme.colors.grayscale.dark2}cc;
}
}
&.ant-popover {
color: ${theme.colors.grayscale.light4};
z-index: 99;
}
}
`}
/>
<div>
{appliedCrossFilterIndicators.length ? (
<div>
@ -224,12 +175,13 @@ const DetailsPanelPopover = ({
return (
<Popover
overlayClassName="filterStatusPopover"
color={`${theme.colors.grayscale.dark2}cc`}
content={content}
visible={popoverVisible}
onVisibleChange={handleVisibility}
open={popoverVisible}
onOpenChange={handleVisibility}
placement="bottomRight"
trigger={['hover']}
data-test="filter-status-popover"
>
{children}
</Popover>

View File

@ -30,7 +30,6 @@ export const FilterCard = ({
placement,
}: FilterCardProps) => {
const [internalIsVisible, setInternalIsVisible] = useState(false);
const hidePopover = () => {
setInternalIsVisible(false);
};
@ -43,15 +42,18 @@ export const FilterCard = ({
return (
<Popover
placement={placement}
overlayClassName="filter-card-popover"
overlayStyle={{
width: '240px',
}}
mouseEnterDelay={0.2}
mouseLeaveDelay={0.2}
onVisibleChange={visible => {
onOpenChange={visible => {
setInternalIsVisible(externalIsVisible && visible);
}}
visible={externalIsVisible && internalIsVisible}
open={externalIsVisible && internalIsVisible}
content={<FilterCardContent filter={filter} hidePopover={hidePopover} />}
getPopupContainer={getPopupContainer ?? (() => document.body)}
arrow={false}
>
{children}
</Popover>

View File

@ -66,32 +66,6 @@ export const chartHeaderStyles = (theme: SupersetTheme) => css`
`;
export const filterCardPopoverStyle = (theme: SupersetTheme) => css`
.filter-card-popover {
width: 240px;
padding: 0;
border-radius: 4px;
&.ant-popover-placement-bottom {
padding-top: ${theme.gridUnit}px;
}
&.ant-popover-placement-left {
padding-right: ${theme.gridUnit * 3}px;
}
.ant-popover-inner {
box-shadow: 0 0 8px rgb(0 0 0 / 10%);
}
.ant-popover-inner-content {
padding: ${theme.gridUnit * 4}px;
}
.ant-popover-arrow {
display: none;
}
}
.filter-card-tooltip {
&.antd5-tooltip-placement-bottom {
padding-top: 0;

View File

@ -27,7 +27,6 @@ import {
TimeFormats,
useTheme,
} from '@superset-ui/core';
import { Global } from '@emotion/react';
import { Column } from 'react-table';
import { debounce } from 'lodash';
import { Input } from 'src/components/Input';
@ -195,13 +194,6 @@ const DataTableTemporalHeaderCell = ({
datasourceId ? ( // eslint-disable-next-line jsx-a11y/no-static-element-interactions
<FormatPickerContainer onClick={e => e.stopPropagation()}>
{/* hack to disable click propagation from popover content to table header, which triggers sorting column */}
<Global
styles={css`
.column-formatting-popover .ant-popover-inner-content {
padding: 0;
}
`}
/>
<FormatPickerLabel>{t('Column Formatting')}</FormatPickerLabel>
<FormatPicker
onChange={onChange}
@ -219,11 +211,10 @@ const DataTableTemporalHeaderCell = ({
return datasourceId ? (
<span>
<Popover
overlayClassName="column-formatting-popover"
trigger="click"
content={overlayContent}
placement="bottomLeft"
arrowPointAtCenter
arrow={{ pointAtCenter: true }}
>
<Icons.SettingOutlined
iconSize="m"

View File

@ -231,8 +231,8 @@ class AnnotationLayerControl extends PureComponent<Props, PopoverState> {
anno,
this.props.annotationError[anno.name],
)}
visible={this.state.popoverVisible[i]}
onVisibleChange={visible => this.handleVisibleChange(visible, i)}
open={this.state.popoverVisible[i]}
onOpenChange={visible => this.handleVisibleChange(visible, i)}
>
<CustomListItem selectable>
<span>{anno.name}</span>
@ -254,9 +254,9 @@ class AnnotationLayerControl extends PureComponent<Props, PopoverState> {
'',
)}
title={t('Add annotation layer')}
visible={this.state.popoverVisible[addLayerPopoverKey]}
open={this.state.popoverVisible[addLayerPopoverKey]}
destroyTooltipOnHide
onVisibleChange={visible =>
onOpenChange={visible =>
this.handleVisibleChange(visible, addLayerPopoverKey)
}
>

View File

@ -51,8 +51,8 @@ export const FormattingPopover = ({
extraColorChoices={extraColorChoices}
/>
}
visible={visible}
onVisibleChange={setVisible}
open={visible}
onOpenChange={setVisible}
trigger={['click']}
overlayStyle={{ width: '450px' }}
{...props}

View File

@ -18,7 +18,7 @@
*/
import { ReactNode } from 'react';
import { PopoverProps } from 'antd/lib/popover';
import { PopoverProps } from 'src/components/Popover';
import { Comparator, ControlComponentProps } from '@superset-ui/chart-controls';
export type ConditionalFormattingConfig = {

View File

@ -47,9 +47,9 @@ const ContourPopoverTrigger = ({
<ControlPopover
trigger="click"
content={popoverContent}
defaultVisible={visible}
visible={visible}
onVisibleChange={setVisibility}
defaultOpen={visible}
open={visible}
onOpenChange={setVisibility}
destroyTooltipOnHide
>
{props.children}

View File

@ -88,7 +88,7 @@ test('Should lock the vertical scroll when the popover is visible', () => {
test('Should place popover at the top', async () => {
const { setStateMock } = setupTest({
...createProps(),
getVisibilityRatio: () => 0.2,
getVisibilityRatio: () => ({ yRatio: 0.2, xRatio: 0.3 }),
});
expect(screen.getByTestId('control-popover')).toBeInTheDocument();
@ -102,21 +102,21 @@ test('Should place popover at the top', async () => {
test('Should place popover at the center', async () => {
const { setStateMock } = setupTest({
...createProps(),
getVisibilityRatio: () => 0.5,
getVisibilityRatio: () => ({ yRatio: 0.5, xRatio: 0.7 }),
});
expect(screen.getByTestId('control-popover')).toBeInTheDocument();
userEvent.click(screen.getByTestId('control-popover'));
await waitFor(() => {
expect(setStateMock).toHaveBeenCalledWith('right');
expect(setStateMock).toHaveBeenCalledWith('left');
});
});
test('Should place popover at the bottom', async () => {
const { setStateMock } = setupTest({
...createProps(),
getVisibilityRatio: () => 0.7,
getVisibilityRatio: () => ({ yRatio: 0.9, xRatio: 0.2 }),
});
expect(screen.getByTestId('control-popover')).toBeInTheDocument();
@ -162,7 +162,7 @@ test('Controlled mode', async () => {
const baseProps = {
...createProps(),
destroyTooltipOnHide: true,
visible: false,
open: false,
};
const { rerender } = setupTest(baseProps);
@ -170,7 +170,7 @@ test('Controlled mode', async () => {
expect(screen.getByTestId('control-popover')).toBeInTheDocument();
expect(screen.queryByText('Control Popover Test')).not.toBeInTheDocument();
rerender(<TestComponent {...baseProps} visible />);
rerender(<TestComponent {...baseProps} open />);
expect(await screen.findByText('Control Popover Test')).toBeInTheDocument();
rerender(<TestComponent {...baseProps} />);

View File

@ -21,49 +21,70 @@ import React, { FC, useCallback, useRef, useEffect, useState } from 'react';
import Popover, {
PopoverProps as BasePopoverProps,
TooltipPlacement,
} from 'src/components/Popover';
import { TooltipPlacement } from 'src/components/Tooltip';
const sectionContainerId = 'controlSections';
export const getSectionContainerElement = () =>
document.getElementById(sectionContainerId)?.lastElementChild as HTMLElement;
const getElementYVisibilityRatioOnContainer = (node: HTMLElement) => {
const getElementVisibilityRatio = (node?: HTMLElement) => {
const containerHeight = window?.innerHeight;
const nodePositionInViewport = node?.getBoundingClientRect()?.top;
if (!containerHeight || !nodePositionInViewport) {
return 0;
const containerWidth = window?.innerWidth;
const rect = node?.getBoundingClientRect();
if (!containerHeight || !containerWidth || !rect?.top) {
return { yRatio: 0, xRatio: 0 };
}
return nodePositionInViewport / containerHeight;
const yRatio = rect.top / containerHeight;
const xRatio = rect.left / containerWidth;
return { yRatio, xRatio };
};
export type PopoverProps = BasePopoverProps & {
getVisibilityRatio?: typeof getElementYVisibilityRatioOnContainer;
getVisibilityRatio?: typeof getElementVisibilityRatio;
};
const ControlPopover: FC<PopoverProps> = ({
getPopupContainer,
getVisibilityRatio = getElementYVisibilityRatioOnContainer,
visible: visibleProp,
getVisibilityRatio = getElementVisibilityRatio,
open: visibleProp,
destroyTooltipOnHide = false,
placement: initialPlacement = 'right',
...props
}) => {
const triggerElementRef = useRef<HTMLElement>();
const [visible, setVisible] = useState(
visibleProp === undefined ? props.defaultVisible : visibleProp,
visibleProp === undefined ? props.defaultOpen : visibleProp,
);
const [placement, setPlacement] = React.useState<TooltipPlacement>('right');
const [placement, setPlacement] =
React.useState<TooltipPlacement>(initialPlacement);
const calculatePlacement = useCallback(() => {
const visibilityRatio = getVisibilityRatio(triggerElementRef.current!);
if (visibilityRatio < 0.35 && placement !== 'rightTop') {
setPlacement('rightTop');
} else if (visibilityRatio > 0.65 && placement !== 'rightBottom') {
setPlacement('rightBottom');
} else {
setPlacement('right');
if (!triggerElementRef.current) return;
const { yRatio, xRatio } = getVisibilityRatio(triggerElementRef.current);
const horizontalPlacement =
xRatio < 0.35 ? 'right' : xRatio > 0.65 ? 'left' : '';
const verticalPlacement = (() => {
if (yRatio < 0.35) return horizontalPlacement ? 'top' : 'bottom';
if (yRatio > 0.65) return horizontalPlacement ? 'bottom' : 'top';
return '';
})();
const newPlacement =
((horizontalPlacement
? horizontalPlacement +
verticalPlacement.charAt(0).toUpperCase() +
verticalPlacement.slice(1)
: verticalPlacement) as TooltipPlacement) || 'left';
if (newPlacement !== placement) {
setPlacement(newPlacement);
}
}, [getVisibilityRatio]);
@ -97,7 +118,7 @@ const ControlPopover: FC<PopoverProps> = ({
}
setVisible(!!visible);
props.onVisibleChange?.(!!visible);
props.onOpenChange?.(!!visible);
},
[props, changeContainerScrollStatus],
);
@ -106,7 +127,7 @@ const ControlPopover: FC<PopoverProps> = ({
(event: KeyboardEvent) => {
if (event.key === 'Escape') {
setVisible(false);
props.onVisibleChange?.(false);
props.onOpenChange?.(false);
}
},
[props],
@ -143,10 +164,10 @@ const ControlPopover: FC<PopoverProps> = ({
return (
<Popover
{...props}
visible={visible}
arrowPointAtCenter
open={visible}
arrow={{ pointAtCenter: true }}
placement={placement}
onVisibleChange={handleOnVisibleChange}
onOpenChange={handleOnVisibleChange}
getPopupContainer={handleGetPopupContainer}
destroyTooltipOnHide={destroyTooltipOnHide}
/>

View File

@ -355,23 +355,24 @@ export default function DateFilterLabel(props: DateFilterControlProps) {
<span className="text">{t('Edit time range')}</span>
</IconWrapper>
);
const popoverContent = (
<ControlPopover
placement="right"
autoAdjustOverflow={false}
trigger="click"
placement="right"
content={overlayContent}
title={title}
defaultVisible={show}
visible={show}
onVisibleChange={toggleOverlay}
defaultOpen={show}
open={show}
onOpenChange={toggleOverlay}
overlayStyle={{ width: '600px' }}
getPopupContainer={triggerNode =>
destroyTooltipOnHide
getPopupContainer={nodeTrigger =>
isOverflowingFilterBar
? (triggerNode.parentNode as HTMLElement)
? (nodeTrigger.parentNode as HTMLElement)
: document.body
}
destroyTooltipOnHide
overlayClassName="time-range-popover"
>
<Tooltip placement="top" title={tooltipTitle}>
<DateLabel

View File

@ -165,9 +165,9 @@ const ColumnSelectPopoverTrigger = ({
<ControlPopover
trigger="click"
content={overlayContent}
defaultVisible={visible}
visible={visible}
onVisibleChange={handleTogglePopover}
defaultOpen={visible}
open={visible}
onOpenChange={handleTogglePopover}
title={popoverTitle}
destroyTooltipOnHide
>

View File

@ -106,9 +106,9 @@ class AdhocFilterPopoverTrigger extends PureComponent<
<ControlPopover
trigger="click"
content={overlayContent}
defaultVisible={visible}
visible={visible}
onVisibleChange={togglePopover}
defaultOpen={visible}
open={visible}
onOpenChange={togglePopover}
destroyTooltipOnHide
>
{this.props.children}

View File

@ -18,7 +18,7 @@
*/
import { ControlHeader } from '@superset-ui/chart-controls';
import { css, styled, t } from '@superset-ui/core';
import { Popover } from 'antd';
import Popover from 'src/components/Popover';
import { FC, useState } from 'react';
import { EditItem, LayerConf, LayerConfigsControlProps } from './types';
import LayerConfigsPopoverContent from './LayerConfigsPopoverContent';
@ -160,7 +160,7 @@ export const LayerConfigsControl: FC<LayerConfigsControlProps> = ({
<div>
<ControlHeader {...controlHeaderProps} />
<Popover
visible={popoverVisible}
open={popoverVisible}
trigger="click"
title={popoverTitle}
placement="right"

View File

@ -18,7 +18,8 @@
*/
import { ControlHeader } from '@superset-ui/chart-controls';
import { css, styled, t } from '@superset-ui/core';
import { Button, Popover } from 'antd';
import Button from 'src/components/Button';
import Popover from 'src/components/Popover';
import { FC, useState } from 'react';
import { mix } from 'polished';
import { MapViewConfigs, MapViewConfigsControlProps } from './types';
@ -159,7 +160,7 @@ export const MapViewControl: FC<MapViewConfigsControlProps> = ({
{isCustomMode() && value && (
<Popover
visible={popoverVisible}
open={popoverVisible}
trigger="click"
title={popoverTitle}
placement="right"

View File

@ -17,7 +17,8 @@
* under the License.
*/
import { css, styled, t } from '@superset-ui/core';
import { Button, Form } from 'antd';
import { Form } from 'src/components/Form';
import Button from 'src/components/Button';
import { FC, useEffect, useState } from 'react';
import { mix } from 'polished';
import { MapViewConfigs, MapViewPopoverContentProps } from './types';

View File

@ -259,9 +259,9 @@ class AdhocMetricPopoverTrigger extends PureComponent<
placement="right"
trigger="click"
content={overlayContent}
defaultVisible={visible}
visible={visible}
onVisibleChange={togglePopover}
defaultOpen={visible}
open={visible}
onOpenChange={togglePopover}
title={popoverTitle}
destroyTooltipOnHide
>

View File

@ -361,8 +361,8 @@ export default class TimeSeriesColumnControl extends Component {
trigger="click"
content={this.renderPopover()}
title={t('Column Configuration')}
visible={this.state.popoverVisible}
onVisibleChange={this.onPopoverVisibleChange}
open={this.state.popoverVisible}
onOpenChange={this.onPopoverVisibleChange}
>
<InfoTooltipWithTrigger
icon="edit"