Skip to content

Commit f4d0c39

Browse files
Merge pull request #17129 from IgniteUI/rivanova/fix-tooltip-close-17114-21.1.x
fix(tooltip): cancel pending show if pointer is not on the target - 21.1.x
2 parents 44e7bc7 + 38cfe61 commit f4d0c39

File tree

2 files changed

+49
-8
lines changed

2 files changed

+49
-8
lines changed

projects/igniteui-angular/directives/src/directives/tooltip/tooltip-target.directive.ts

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {
2-
Directive, OnInit, OnDestroy, Output, ElementRef, ViewContainerRef,
2+
Directive, OnInit, OnDestroy, Output, ViewContainerRef,
33
Input, EventEmitter, booleanAttribute, TemplateRef, ComponentRef, Renderer2,
44
EnvironmentInjector,
55
createComponent,
@@ -380,6 +380,7 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
380380
private _positionSettings: PositionSettings = TooltipPositionSettings;
381381
private _showTriggers = new Set(['pointerenter']);
382382
private _hideTriggers = new Set(['pointerleave', 'click']);
383+
private _pendingShowTrigger: string | null = null;
383384

384385
private _abortController = new AbortController();
385386

@@ -400,15 +401,20 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
400401
/**
401402
* @hidden
402403
*/
403-
public onShow(): void {
404-
this._checksBeforeShowing(() => this._showOnInteraction());
404+
public onShow(event?: Event): void {
405+
this._checksBeforeShowing(() => this._showOnInteraction(event));
405406
}
406407

407408
/**
408409
* @hidden
409410
*/
410-
public onHide(): void {
411-
if (this.tooltipDisabled || this.target.collapsed) {
411+
public onHide(event?: Event): void {
412+
if (this.target.collapsed) {
413+
this._cancelPendingShow(event);
414+
return;
415+
}
416+
417+
if (this.tooltipDisabled) {
412418
return;
413419
}
414420

@@ -538,7 +544,7 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
538544
}, withDelay ? this.hideDelay : 0);
539545
}
540546

541-
private _showTooltip(withDelay: boolean, withEvents: boolean): void {
547+
private _showTooltip(withDelay: boolean, withEvents: boolean, triggerEvent?: Event): void {
542548
if (!this.target.collapsed && !this._isForceClosed) {
543549
return;
544550
}
@@ -555,17 +561,19 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
555561
}
556562

557563
this._evaluateStickyState();
564+
this._pendingShowTrigger = triggerEvent?.type ?? null;
558565

559566
this.target.timeoutId = setTimeout(() => {
560567
// Call open() of IgxTooltipDirective
568+
this._pendingShowTrigger = null;
561569
this.target.open(this._mergedOverlaySettings);
562570
}, withDelay ? this.showDelay : 0);
563571
}
564572

565573

566-
private _showOnInteraction(): void {
574+
private _showOnInteraction(triggerEvent?: Event): void {
567575
this._stopTimeoutAndAnimation();
568-
this._showTooltip(true, true);
576+
this._showTooltip(true, true, triggerEvent);
569577
}
570578

571579
private _hideOnInteraction(): void {
@@ -594,6 +602,26 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
594602
this.target.stopAnimations();
595603
}
596604

605+
/**
606+
* Used when a hide trigger occurs before the tooltip opens.
607+
* Clears the pending timeout and resets the tracked show trigger
608+
* so the tooltip does not open after the user has already left the target.
609+
*/
610+
private _cancelPendingShow(event?: Event): void {
611+
if (!this.target.timeoutId) {
612+
return;
613+
}
614+
615+
// Keep same-event show/hide trigger combinations acting as toggle behavior.
616+
if (event?.type && event.type === this._pendingShowTrigger) {
617+
return;
618+
}
619+
620+
clearTimeout(this.target.timeoutId);
621+
this.target.timeoutId = null;
622+
this._pendingShowTrigger = null;
623+
}
624+
597625
/**
598626
* Used when a single tooltip is used for multiple targets.
599627
*/

projects/igniteui-angular/directives/src/directives/tooltip/tooltip.directive.spec.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,19 @@ describe('IgxTooltip', () => {
519519
flush();
520520
verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, false);
521521
}));
522+
523+
it('should not open when pointer leaves before the show delay elapses', fakeAsync(() => {
524+
tooltipTarget.showDelay = 500;
525+
fix.detectChanges();
526+
527+
hoverElement(button);
528+
tick(300);
529+
verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, false);
530+
531+
unhoverElement(button);
532+
tick(300);
533+
verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, false);
534+
}));
522535
});
523536
});
524537

0 commit comments

Comments
 (0)