enhancement
major
defect
major
minor
minor
#29739
React tooltip stays open at the window's top-left corner when its anchor is removed under the pointer
Found in BOS/Consulting #413 (8.0.0-alpha9).
What happens
A dialog's submit button carries a <tooltip>. The user rests the pointer on it (the tooltip opens), then clicks it. The command closes the dialog. The tooltip stays open, placed at the top-left corner of the window (measured at 1440 x 900: popover at x=8, y=10), over the app bar, until the pointer crosses another element.
Cause
The tooltip manager in tl-react-bridge (#tl-tooltip-host, document-level pointerover/`pointerout` listeners) hides a shown tooltip only on the pointerout of its anchor. An element that is removed while the pointer rests on it sends no pointerout. The pointerover that Chrome dispatches afterwards on the element now under the pointer does not hide it either: the pointerover handler returns early when the new target has no data-tooltip. The popover keeps its detached anchor, and Floating UI (autoUpdate) places it against the zero rectangle of a detached element, which is the top-left corner.
The manager already checks document.contains(anchor) before it shows a pending tooltip, but never again after it is shown.
Every command that closes or re-renders its own surface while the pointer rests on its button does the same.
Proposal
Close the tooltip when its anchor leaves the document, e.g. check anchor.isConnected in autoUpdate's callback or observe the anchor's removal, and/or hide in the pointerover handler when the new target carries no tooltip.
Pietro works around it in script/consulting-tooltip-anchor.js: it tracks the anchor and, when a DOM change removes it, dispatches a pointerout without relatedTarget on the document, which the manager answers by hiding. To be removed when this is fixed.
Lösung
While a tooltip is shown, the tooltip manager (tooltip-host.ts) observes the document with a MutationObserver (child list, whole subtree). As soon as a DOM change disconnects the tooltip's anchor, the tooltip closes immediately, without the close delay. The observer is disconnected whenever no tooltip is shown, so it costs nothing while no tooltip is open.
The pointerover handler stays unchanged: with the anchor observed, a second close path there is not needed.
Applications that work around the defect by dispatching a synthetic pointerout on anchor removal (e.g. script/consulting-tooltip-anchor.js in BOS/Consulting) can drop that script.