From bcd0733a64012c50ed3d61305be290d1d523d252 Mon Sep 17 00:00:00 2001
From: silverwind <me@silverwind.io>
Date: Thu, 11 May 2023 07:40:54 +0200
Subject: [PATCH] Only show one tippy at a time (#24648)

Because our tippy instances have an `interactiveBorder`, it's possible
to bring up two instances at once, which is undesirable.

<img width="256" alt="Screenshot 2023-05-10 at 23 03 04"
src="https://github.com/go-gitea/gitea/assets/115237/3a9a1775-78c1-46d4-a8a5-503ab7dca0d8">

Prevent this by keeping track of visible tippy instances and hiding
others when one is shown. Tippy also has the [singleton
addon](https://atomiks.github.io/tippyjs/v6/addons/#singleton) for the
same purpose, but it's unsuitable to us because we don't init all
tooltips at once.
---
 web_src/js/modules/tippy.js | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/web_src/js/modules/tippy.js b/web_src/js/modules/tippy.js
index 6cec95d76..3a8c7e09c 100644
--- a/web_src/js/modules/tippy.js
+++ b/web_src/js/modules/tippy.js
@@ -1,5 +1,7 @@
 import tippy from 'tippy.js';
 
+const visibleInstances = new Set();
+
 export function createTippy(target, opts = {}) {
   const instance = tippy(target, {
     appendTo: document.body,
@@ -9,6 +11,18 @@ export function createTippy(target, opts = {}) {
     interactiveBorder: 20,
     ignoreAttributes: true,
     maxWidth: 500, // increase over default 350px
+    onHide: (instance) => {
+      visibleInstances.delete(instance);
+    },
+    onDestroy: (instance) => {
+      visibleInstances.delete(instance);
+    },
+    onShow: (instance) => {
+      for (const visibleInstance of visibleInstances) {
+        visibleInstance.hide(); // hide other instances
+      }
+      visibleInstances.add(instance);
+    },
     arrow: `<svg width="16" height="7"><path d="m0 7 8-7 8 7Z" class="tippy-svg-arrow-outer"/><path d="m0 8 8-7 8 7Z" class="tippy-svg-arrow-inner"/></svg>`,
     ...(opts?.role && {theme: opts.role}),
     ...opts,