From f27ab0ecba561b130b4b3d22e130ee232908d70f Mon Sep 17 00:00:00 2001
From: Dalton <daltojohnso@users.noreply.github.com>
Date: Tue, 4 Jan 2022 09:12:08 -0800
Subject: [PATCH] Show dimension/table info popover immediately when one is
 already visible (#19521)

---
 .../DimensionInfoPopover.tsx                    | 17 +++++++++++++++++
 .../TableInfoPopover/TableInfoPopover.tsx       | 17 +++++++++++++++++
 .../components/Popover/TippyPopover.tsx         |  4 +++-
 3 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/frontend/src/metabase/components/MetadataInfo/DimensionInfoPopover/DimensionInfoPopover.tsx b/frontend/src/metabase/components/MetadataInfo/DimensionInfoPopover/DimensionInfoPopover.tsx
index 19a5e4f8eb8..8484830e053 100644
--- a/frontend/src/metabase/components/MetadataInfo/DimensionInfoPopover/DimensionInfoPopover.tsx
+++ b/frontend/src/metabase/components/MetadataInfo/DimensionInfoPopover/DimensionInfoPopover.tsx
@@ -1,5 +1,6 @@
 import React from "react";
 import PropTypes from "prop-types";
+import { hideAll } from "tippy.js";
 
 import Dimension from "metabase-lib/lib/Dimension";
 import TippyPopver, {
@@ -22,6 +23,8 @@ type Props = { dimension: Dimension } & Pick<
   "children" | "placement"
 >;
 
+const className = "dimension-info-popover";
+
 function DimensionInfoPopover({ dimension, children, placement }: Props) {
   // avoid a scenario where we may have a Dimension instance but not enough metadata
   // to even show a display name (probably indicative of a bug)
@@ -29,10 +32,24 @@ function DimensionInfoPopover({ dimension, children, placement }: Props) {
 
   return hasMetadata ? (
     <TippyPopver
+      className={className}
       delay={isCypressActive ? 0 : POPOVER_DELAY}
       interactive
       placement={placement || "left-start"}
       content={<WidthBoundDimensionInfo dimension={dimension} />}
+      onTrigger={instance => {
+        const dimensionInfoPopovers = document.querySelectorAll(
+          `.${className}[data-state~='visible']`,
+        );
+
+        // if a dimension info popovers are already visible, hide them and show this popover immediately
+        if (dimensionInfoPopovers.length > 0) {
+          hideAll({
+            exclude: instance,
+          });
+          instance.show();
+        }
+      }}
     >
       {children}
     </TippyPopver>
diff --git a/frontend/src/metabase/components/MetadataInfo/TableInfoPopover/TableInfoPopover.tsx b/frontend/src/metabase/components/MetadataInfo/TableInfoPopover/TableInfoPopover.tsx
index a563687636e..1677c3f018b 100644
--- a/frontend/src/metabase/components/MetadataInfo/TableInfoPopover/TableInfoPopover.tsx
+++ b/frontend/src/metabase/components/MetadataInfo/TableInfoPopover/TableInfoPopover.tsx
@@ -1,5 +1,6 @@
 import React from "react";
 import PropTypes from "prop-types";
+import { hideAll } from "tippy.js";
 
 import TippyPopver, {
   ITippyPopoverProps,
@@ -21,16 +22,32 @@ type Props = { tableId: number } & Pick<
   "children" | "placement" | "offset"
 >;
 
+const className = "table-info-popover";
+
 function TableInfoPopover({ tableId, children, placement, offset }: Props) {
   placement = placement || "left-start";
 
   return tableId != null ? (
     <TippyPopver
+      className={className}
       interactive
       delay={POPOVER_DELAY}
       placement={placement}
       offset={offset}
       content={<WidthBoundTableInfo tableId={tableId} />}
+      onTrigger={instance => {
+        const dimensionInfoPopovers = document.querySelectorAll(
+          `.${className}[data-state~='visible']`,
+        );
+
+        // if a dimension info popover is already visible, hide it and show this one immediately
+        if (dimensionInfoPopovers.length > 0) {
+          hideAll({
+            exclude: instance,
+          });
+          instance.show();
+        }
+      }}
     >
       {children}
     </TippyPopver>
diff --git a/frontend/src/metabase/components/Popover/TippyPopover.tsx b/frontend/src/metabase/components/Popover/TippyPopover.tsx
index ee64db490df..2b2279675aa 100644
--- a/frontend/src/metabase/components/Popover/TippyPopover.tsx
+++ b/frontend/src/metabase/components/Popover/TippyPopover.tsx
@@ -1,6 +1,7 @@
 import React, { useState, useMemo } from "react";
 import PropTypes from "prop-types";
 import * as Tippy from "@tippyjs/react";
+import cx from "classnames";
 
 import { isReducedMotionPreferred } from "metabase/lib/dom";
 import EventSandbox from "metabase/components/EventSandbox";
@@ -22,6 +23,7 @@ const propTypes = {
 };
 
 function TippyPopover({
+  className,
   disableContentSandbox,
   lazy = true,
   content,
@@ -55,7 +57,7 @@ function TippyPopover({
 
   return (
     <TippyComponent
-      className="popover"
+      className={cx("popover", className)}
       theme="popover"
       arrow={false}
       offset={OFFSET}
-- 
GitLab