From 94f0bb48c652ba0ad0225abb2a39af630821f190 Mon Sep 17 00:00:00 2001 From: KPal Date: Wed, 8 Jul 2026 15:13:33 +0100 Subject: [PATCH] fix(inspector): stop multiple tooltips stacking in shared tooltip (#2133) The inspector's reference tooltips all share one Tooltip singleton. Each field appended its own content container on hover; a field destroyed while its tooltip was up never fired hoverend, so its container lingered and stacked with the next one shown. Enforce one-container-at-a-time on the singleton via _shown, checked by DOM parentage rather than a per-closure flag, so it is immune to fields being torn down without a destroy event. --- src/common/pcui/element/element-tooltip.ts | 27 ++++++++++++++++------ 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/common/pcui/element/element-tooltip.ts b/src/common/pcui/element/element-tooltip.ts index cb5d8894e..b6c3752b6 100644 --- a/src/common/pcui/element/element-tooltip.ts +++ b/src/common/pcui/element/element-tooltip.ts @@ -20,6 +20,9 @@ class Tooltip extends Container { } >(); + // the single container currently shown; the singleton shows one at a time (gh 2133) + private _shown: Container | null = null; + /** * Creates new tooltip. * @@ -153,7 +156,6 @@ class Tooltip extends Container { const events = []; let timeout = null; - let appended = false; const defer = () => { if (timeout) { @@ -170,10 +172,16 @@ class Tooltip extends Container { const hover = () => { defer().then(() => { + // drop whatever was shown before. a field destroyed while its tooltip is + // up never fires hoverend, so its container would otherwise linger and + // stack with the next one shown (gh 2133) + if (this._shown && this._shown !== container) { + this.remove(this._shown); + } + this._shown = container; this.hidden = false; - if (!appended) { + if (container.parent !== this) { this.append(container); - appended = true; } this._realign(align, horz, vert); }); @@ -181,11 +189,13 @@ class Tooltip extends Container { const hoverend = () => { defer().then(() => { - this.hidden = true; - if (appended) { - this.remove(container); - appended = false; + // a later hover may have taken the singleton over; leave that one alone + if (this._shown !== container) { + return; } + this.hidden = true; + this.remove(container); + this._shown = null; }); }; @@ -229,6 +239,9 @@ class Tooltip extends Container { events.forEach((evt: EventHandle) => evt.unbind()); arrow.remove(); this.remove(container); + if (this._shown === container) { + this._shown = null; + } this._targets.delete(target); return this;