mirror of
https://github.com/penpot/penpot.git
synced 2026-04-25 11:18:36 +00:00
🐛 Fix tooltip appearing two times when nested elements (#9031)
This commit is contained in:
parent
c02f0a2bc9
commit
09fca1c820
@ -17,8 +17,52 @@
|
|||||||
|
|
||||||
(def ^:private ^:const overlay-offset 32)
|
(def ^:private ^:const overlay-offset 32)
|
||||||
|
|
||||||
|
;; Global state for tooltip coordination
|
||||||
(defonce active-tooltip (atom nil))
|
(defonce active-tooltip (atom nil))
|
||||||
|
|
||||||
|
;; Registry of visible tooltips to detect nested tooltips
|
||||||
|
;; Map: tooltip-id -> trigger-element
|
||||||
|
(defonce ^:private tooltip-registry (atom {}))
|
||||||
|
|
||||||
|
;; Track tooltips that are "about to show" - used to prevent race conditions
|
||||||
|
;; when both parent and child schedule their show at the same time.
|
||||||
|
;; Map: tooltip-id -> trigger-element
|
||||||
|
(defonce ^:private pending-tooltips (atom {}))
|
||||||
|
|
||||||
|
(defn- mark-pending
|
||||||
|
"Mark a tooltip as pending (scheduled to show soon).
|
||||||
|
Used to detect potential nested tooltips during race condition window."
|
||||||
|
[tooltip-id trigger-el]
|
||||||
|
(swap! pending-tooltips assoc tooltip-id trigger-el))
|
||||||
|
|
||||||
|
(defn- clear-pending
|
||||||
|
"Clear the pending state (tooltip showed or cancelled)."
|
||||||
|
[tooltip-id]
|
||||||
|
(swap! pending-tooltips dissoc tooltip-id))
|
||||||
|
|
||||||
|
(defn- register-tooltip
|
||||||
|
"Register this tooltip in the global registry when it becomes visible.
|
||||||
|
Used to detect nested tooltips."
|
||||||
|
[tooltip-id trigger-el]
|
||||||
|
(swap! tooltip-registry assoc tooltip-id trigger-el)
|
||||||
|
(clear-pending tooltip-id))
|
||||||
|
|
||||||
|
(defn- unregister-tooltip
|
||||||
|
"Unregister this tooltip from the global registry when it hides."
|
||||||
|
[tooltip-id]
|
||||||
|
(swap! tooltip-registry dissoc tooltip-id)
|
||||||
|
(clear-pending tooltip-id))
|
||||||
|
|
||||||
|
(defn- has-descendant-tooltip?
|
||||||
|
"Check if there's a registered or pending tooltip that is a descendant of trigger-el.
|
||||||
|
If so, we should NOT show the parent tooltip."
|
||||||
|
[trigger-el]
|
||||||
|
(let [all-tooltips (merge @tooltip-registry @pending-tooltips)]
|
||||||
|
(some (fn [[_ entry-el]]
|
||||||
|
(when (some? entry-el)
|
||||||
|
(dom/child? entry-el trigger-el)))
|
||||||
|
all-tooltips)))
|
||||||
|
|
||||||
(defn- clear-schedule
|
(defn- clear-schedule
|
||||||
[ref]
|
[ref]
|
||||||
(when-let [schedule (mf/ref-val ref)]
|
(when-let [schedule (mf/ref-val ref)]
|
||||||
@ -191,15 +235,27 @@
|
|||||||
(when-not (.-hidden js/document)
|
(when-not (.-hidden js/document)
|
||||||
(let [trigger-el (mf/ref-val trigger-ref)]
|
(let [trigger-el (mf/ref-val trigger-ref)]
|
||||||
(clear-schedule schedule-ref)
|
(clear-schedule schedule-ref)
|
||||||
(add-schedule schedule-ref (d/nilv delay 300)
|
|
||||||
(fn []
|
;; Check if there's a registered or pending tooltip that is a descendant of our trigger.
|
||||||
(when-let [active @active-tooltip]
|
;; If so, skip showing this tooltip and let the innermost one show instead.
|
||||||
(when (not= (:id active) tooltip-id)
|
(when-not (has-descendant-tooltip? trigger-el)
|
||||||
(when-let [tooltip-el (dom/get-element (:id active))]
|
;; Mark as pending BEFORE scheduling (helps prevent race conditions)
|
||||||
(dom/set-css-property! tooltip-el "display" "none"))
|
(mark-pending tooltip-id trigger-el)
|
||||||
(reset! active-tooltip nil)))
|
|
||||||
(reset! active-tooltip {:id tooltip-id :trigger trigger-el})
|
(add-schedule schedule-ref (d/nilv delay 300)
|
||||||
(reset! visible* true)))))))
|
(fn []
|
||||||
|
;; Double-check: don't show if another tooltip is now visible
|
||||||
|
(when-let [active @active-tooltip]
|
||||||
|
(when (not= (:id active) tooltip-id)
|
||||||
|
(when-let [tooltip-el (dom/get-element (:id active))]
|
||||||
|
(dom/set-css-property! tooltip-el "display" "none"))
|
||||||
|
(reset! active-tooltip nil)))
|
||||||
|
|
||||||
|
;; Register this tooltip as visible
|
||||||
|
(register-tooltip tooltip-id trigger-el)
|
||||||
|
|
||||||
|
(reset! active-tooltip {:id tooltip-id :trigger trigger-el})
|
||||||
|
(reset! visible* true))))))))
|
||||||
|
|
||||||
on-show-focus
|
on-show-focus
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@ -215,6 +271,10 @@
|
|||||||
(fn []
|
(fn []
|
||||||
(clear-schedule schedule-ref)
|
(clear-schedule schedule-ref)
|
||||||
(reset! visible* false)
|
(reset! visible* false)
|
||||||
|
|
||||||
|
;; Unregister from the global registry
|
||||||
|
(unregister-tooltip tooltip-id)
|
||||||
|
|
||||||
(when (= (:id @active-tooltip) tooltip-id)
|
(when (= (:id @active-tooltip) tooltip-id)
|
||||||
(reset! active-tooltip nil))))
|
(reset! active-tooltip nil))))
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user