diff --git a/src/styles/getTooltipStyles.js b/src/styles/getTooltipStyles.js index 3c8b0ff0a4b3..7b7deb707f84 100644 --- a/src/styles/getTooltipStyles.js +++ b/src/styles/getTooltipStyles.js @@ -49,6 +49,33 @@ function computeHorizontalShift(windowWidth, xOffset, componentWidth, tooltipWid return 0; } +/** + * Determines if there is an overlapping element at the top of a given coordinate. + * + * @param {Number} xOffset - The distance between the left edge of the window + * and the left edge of the wrapped component. + * @param {Number} yOffset - The distance between the top edge of the window + * and the top edge of the wrapped component. + * @returns {Boolean} + */ +function isOverlappingAtTop(xOffset, yOffset) { + if (typeof document.elementFromPoint !== 'function') { + return false; + } + + const element = document.elementFromPoint(xOffset, yOffset); + + if (!element) { + return false; + } + + const rect = element.getBoundingClientRect(); + + // Ensure it's not itself + overlapping with another element by checking if the yOffset is greater than the top of the element + // and less than the bottom of the element + return yOffset > rect.top && yOffset < rect.bottom; +} + /** * Generate styles for the tooltip component. * @@ -86,9 +113,10 @@ export default function getTooltipStyles( manualShiftVertical = 0, ) { // Determine if the tooltip should display below the wrapped component. - // If a tooltip will try to render within GUTTER_WIDTH logical pixels of the top of the screen, + // If either a tooltip will try to render within GUTTER_WIDTH logical pixels of the top of the screen, + // Or the wrapped component is overlapping at top-left with another element // we'll display it beneath its wrapped component rather than above it as usual. - const shouldShowBelow = (yOffset - tooltipHeight) < GUTTER_WIDTH; + const shouldShowBelow = (yOffset - tooltipHeight) < GUTTER_WIDTH || isOverlappingAtTop(xOffset, yOffset); // Determine if we need to shift the tooltip horizontally to prevent it // from displaying too near to the edge of the screen.