Change:
Native browser tooltips and many custom ones (Figma, Discord, Edge tabs) keep the tooltip element visible when moving between elements. Would be nice to do the same, to make mouse exploration even snappier. Discord icon bar: ! macOS dock: !
cc as this discussion was spawned off cc as owner of the hover widget cc as we talked about this a few times and he brought it up most recently in the team chat
fyi I'm the main hover widget person This seems doable, needs some thinking on how this would be exposed in the API. It's also a feature of native browser tooltips when hovering from one element with to another.
Thanks for confirmation :)

Discussion:
private readonly hover = this._register(new MutableDisposable<IDisposable>()); private readonly showHoverScheduler = new RunOnceScheduler(() => this.showHover(), 0); <ins> private static _hoverLeaveTime = 0; </ins> constructor( action: ActivityAction, options: IActivityActionViewItemOptions,

this.hoverDisposables.clear(); this.updateTitle(); <del> this.hoverDisposables.add(addDisposableListener(this.container, EventType.MOUSE_OVER, () => { </del> <ins> this.hoverDisposables.add(addDisposableListener(this.label, EventType.MOUSE_OVER, () => { </ins> if (!this.showHoverScheduler.isScheduled()) { <del> this.showHoverScheduler.schedule(this.configurationService.getValue<number>('workbench.hover.delay')); </del> <ins> if (Date.now() - ActivityActionViewItem._hoverLeaveTime < 200) { this.showHover(true); } else { this.showHoverScheduler.schedule(this.configurationService.getValue<number>('workbench.hover.delay')); } </ins> } }, true)); <del> this.hoverDisposables.add(addDisposableListener(this.container, EventType.MOUSE_LEAVE, () => { </del> <ins> this.hoverDisposables.add(addDisposableListener(this.label, EventType.MOUSE_LEAVE, () => { ActivityActionViewItem._hoverLeaveTime = Date.now(); </ins> this.hover.value = undefined; this.showHoverScheduler.cancel(); }, true));

})); } <del> private showHover(): void { </del> <ins> private showHover(skipFadeInAnimation: boolean = false): void { </ins> if (this.hover.value) { return; }

hoverPosition, text: this.computeTitle(), showPointer: true, <del> compact: true </del> <ins> compact: true, skipFadeInAnimation </ins> }); }

* Whether to show a compact hover */ compact?: boolean; <ins> /** * Whether to skip the fade in animation, this should be used when hovering from one hover to * another in the same group so it looks like the hover is moving from one element to the other. */ skipFadeInAnimation?: boolean; </ins> } export interface IHoverAction {

if (options.compact) { this._hover.containerDomNode.classList.add('workbench-hover', 'compact'); } <ins> if (options.skipFadeInAnimation) { this._hover.containerDomNode.classList.add('skip-fade-in'); } </ins> if (options.additionalClasses) { this._hover.containerDomNode.classList.add(...options.additionalClasses); }

position: relative; font-size: 13px; line-height: 19px; <del> animation: fadein 100ms linear; </del> /* Must be higher than sash's z-index and terminal canvases */ z-index: 40; overflow: hidden; max-width: 700px; } <ins> .monaco-workbench .workbench-hover:not(.skip-fade-in) { animation: fadein 100ms linear; } </ins> .monaco-workbench .workbench-hover.compact { font-size: 12px; }