diff --git a/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts index 28354b256d786..f447780e2b2b6 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts +++ b/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts @@ -199,7 +199,7 @@ describe('Time range filter', () => { }); cy.get('[data-test=cancel-button]').click(); cy.wait(500); - cy.get('.ant-popover').should('not.be.visible'); + cy.get('.ant-popover').should('not.exist'); }); }); diff --git a/superset-frontend/src/explore/components/controls/ControlPopover/ControlPopover.tsx b/superset-frontend/src/explore/components/controls/ControlPopover/ControlPopover.tsx index 28dd6e2bd2a23..55391c04c9a57 100644 --- a/superset-frontend/src/explore/components/controls/ControlPopover/ControlPopover.tsx +++ b/superset-frontend/src/explore/components/controls/ControlPopover/ControlPopover.tsx @@ -29,7 +29,7 @@ export const getSectionContainerElement = () => const getElementYVisibilityRatioOnContainer = (node: HTMLElement) => { const containerHeight = window?.innerHeight; - const nodePositionInViewport = node.getBoundingClientRect()?.top; + const nodePositionInViewport = node?.getBoundingClientRect()?.top; if (!containerHeight || !nodePositionInViewport) { return 0; } @@ -45,6 +45,7 @@ const ControlPopover: React.FC = ({ getPopupContainer, getVisibilityRatio = getElementYVisibilityRatioOnContainer, visible: visibleProp, + destroyTooltipOnHide = false, ...props }) => { const triggerElementRef = useRef(); @@ -56,10 +57,9 @@ const ControlPopover: React.FC = ({ const calculatePlacement = useCallback(() => { const visibilityRatio = getVisibilityRatio(triggerElementRef.current!); - - if (visibilityRatio < 0.35) { + if (visibilityRatio < 0.35 && placement !== 'rightTop') { setPlacement('rightTop'); - } else if (visibilityRatio > 0.65) { + } else if (visibilityRatio > 0.65 && placement !== 'rightBottom') { setPlacement('rightBottom'); } else { setPlacement('right'); @@ -68,10 +68,6 @@ const ControlPopover: React.FC = ({ const changeContainerScrollStatus = useCallback( visible => { - if (triggerElementRef.current && visible) { - calculatePlacement(); - } - const element = getSectionContainerElement(); if (element) { element.style.setProperty( @@ -87,9 +83,6 @@ const ControlPopover: React.FC = ({ const handleGetPopupContainer = useCallback( (triggerNode: HTMLElement) => { triggerElementRef.current = triggerNode; - setTimeout(() => { - calculatePlacement(); - }, 0); return getPopupContainer?.(triggerNode) || document.body; }, @@ -140,6 +133,12 @@ const ControlPopover: React.FC = ({ }; }, [handleDocumentKeyDownListener, visible]); + useEffect(() => { + if (visible) { + calculatePlacement(); + } + }, [visible, calculatePlacement]); + return ( = ({ placement={placement} onVisibleChange={handleOnVisibleChange} getPopupContainer={handleGetPopupContainer} + destroyTooltipOnHide={destroyTooltipOnHide} /> ); }; diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx b/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx index ce4c32191d0d2..ca0fa66d2cc09 100644 --- a/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx +++ b/superset-frontend/src/explore/components/controls/DateFilterControl/DateFilterLabel.tsx @@ -156,6 +156,7 @@ export default function DateFilterLabel(props: DateFilterControlProps) { onOpenPopover = noOp, onClosePopover = noOp, overlayStyle = 'Popover', + isOverflowingFilterBar = false, } = props; const defaultTimeFilter = useDefaultTimeFilter(); @@ -356,6 +357,12 @@ export default function DateFilterLabel(props: DateFilterControlProps) { visible={show} onVisibleChange={toggleOverlay} overlayStyle={{ width: '600px' }} + getPopupContainer={triggerNode => + isOverflowingFilterBar + ? (triggerNode.parentNode as HTMLElement) + : document.body + } + destroyTooltipOnHide > void; onClosePopover?: () => void; overlayStyle?: 'Modal' | 'Popover'; + isOverflowingFilterBar?: boolean; } diff --git a/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx b/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx index 07ee6ea828183..fd1530311d5c5 100644 --- a/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx +++ b/superset-frontend/src/filters/components/Time/TimeFilterPlugin.tsx @@ -58,6 +58,7 @@ export default function TimeFilterPlugin(props: PluginFilterTimeProps) { height, filterState, inputRef, + isOverflowingFilterBar = false, } = props; const handleTimeRangeChange = useCallback( @@ -97,6 +98,7 @@ export default function TimeFilterPlugin(props: PluginFilterTimeProps) { onChange={handleTimeRangeChange} onOpenPopover={() => setFilterActive(true)} onClosePopover={() => setFilterActive(false)} + isOverflowingFilterBar={isOverflowingFilterBar} /> diff --git a/superset-frontend/src/filters/components/Time/transformProps.ts b/superset-frontend/src/filters/components/Time/transformProps.ts index 8610cf06600d2..b86a3622486aa 100644 --- a/superset-frontend/src/filters/components/Time/transformProps.ts +++ b/superset-frontend/src/filters/components/Time/transformProps.ts @@ -60,5 +60,6 @@ export default function transformProps(chartProps: ChartProps) { width, inputRef, filterBarOrientation: displaySettings?.filterBarOrientation, + isOverflowingFilterBar: displaySettings?.isOverflowingFilterBar, }; } diff --git a/superset-frontend/src/filters/components/Time/types.ts b/superset-frontend/src/filters/components/Time/types.ts index 4219c7cbb351e..39ee425bb0f23 100644 --- a/superset-frontend/src/filters/components/Time/types.ts +++ b/superset-frontend/src/filters/components/Time/types.ts @@ -39,6 +39,7 @@ export type PluginFilterTimeProps = PluginFilterStylesProps & { formData: PluginFilterSelectQueryFormData; filterState: FilterState; inputRef: RefObject; + isOverflowingFilterBar?: boolean; } & PluginFilterHooks; export const DEFAULT_FORM_DATA: PluginFilterTimeCustomizeProps = {