@@ -17,7 +17,6 @@ import {
1717import { ESCAPE , hasModifierKey } from '@angular/cdk/keycodes' ;
1818import { BreakpointObserver , Breakpoints , BreakpointState } from '@angular/cdk/layout' ;
1919import {
20- ConnectedPosition ,
2120 FlexibleConnectedPositionStrategy ,
2221 HorizontalConnectionPos ,
2322 OriginConnectionPosition ,
@@ -27,6 +26,7 @@ import {
2726 ScrollStrategy ,
2827 VerticalConnectionPos ,
2928 ConnectionPositionPair ,
29+ ConnectedPosition ,
3030} from '@angular/cdk/overlay' ;
3131import { Platform , normalizePassiveListenerOptions } from '@angular/cdk/platform' ;
3232import { ComponentPortal , ComponentType } from '@angular/cdk/portal' ;
@@ -207,6 +207,10 @@ export abstract class _MatTooltipBase<T extends _TooltipComponentBase>
207207 }
208208 set hideDelay ( value : NumberInput ) {
209209 this . _hideDelay = coerceNumberProperty ( value ) ;
210+
211+ if ( this . _tooltipInstance ) {
212+ this . _tooltipInstance . _mouseLeaveHideDelay = this . _hideDelay ;
213+ }
210214 }
211215 private _hideDelay = this . _defaultOptions . hideDelay ;
212216
@@ -376,14 +380,16 @@ export abstract class _MatTooltipBase<T extends _TooltipComponentBase>
376380 this . _detach ( ) ;
377381 this . _portal =
378382 this . _portal || new ComponentPortal ( this . _tooltipComponent , this . _viewContainerRef ) ;
379- this . _tooltipInstance = overlayRef . attach ( this . _portal ) . instance ;
380- this . _tooltipInstance
383+ const instance = ( this . _tooltipInstance = overlayRef . attach ( this . _portal ) . instance ) ;
384+ instance . _triggerElement = this . _elementRef . nativeElement ;
385+ instance . _mouseLeaveHideDelay = this . _hideDelay ;
386+ instance
381387 . afterHidden ( )
382388 . pipe ( takeUntil ( this . _destroyed ) )
383389 . subscribe ( ( ) => this . _detach ( ) ) ;
384390 this . _setTooltipClass ( this . _tooltipClass ) ;
385391 this . _updateTooltipMessage ( ) ;
386- this . _tooltipInstance ! . show ( delay ) ;
392+ instance . show ( delay ) ;
387393 }
388394
389395 /** Hides the tooltip after the delay in ms, defaults to tooltip-delay-hide or 0ms if no input */
@@ -687,7 +693,15 @@ export abstract class _MatTooltipBase<T extends _TooltipComponentBase>
687693 const exitListeners : ( readonly [ string , EventListenerOrEventListenerObject ] ) [ ] = [ ] ;
688694 if ( this . _platformSupportsMouseEvents ( ) ) {
689695 exitListeners . push (
690- [ 'mouseleave' , ( ) => this . hide ( ) ] ,
696+ [
697+ 'mouseleave' ,
698+ event => {
699+ const newTarget = ( event as MouseEvent ) . relatedTarget as Node | null ;
700+ if ( ! newTarget || ! this . _overlayRef ?. overlayElement . contains ( newTarget ) ) {
701+ this . hide ( ) ;
702+ }
703+ } ,
704+ ] ,
691705 [ 'wheel' , event => this . _wheelListener ( event as WheelEvent ) ] ,
692706 ) ;
693707 } else if ( this . touchGestures !== 'off' ) {
@@ -824,6 +838,12 @@ export abstract class _TooltipComponentBase implements OnDestroy {
824838 /** Property watched by the animation framework to show or hide the tooltip */
825839 _visibility : TooltipVisibility = 'initial' ;
826840
841+ /** Element that caused the tooltip to open. */
842+ _triggerElement : HTMLElement ;
843+
844+ /** Amount of milliseconds to delay the closing sequence. */
845+ _mouseLeaveHideDelay : number ;
846+
827847 /** Whether interactions on the page should close the tooltip */
828848 private _closeOnInteraction : boolean = false ;
829849
@@ -885,6 +905,7 @@ export abstract class _TooltipComponentBase implements OnDestroy {
885905 clearTimeout ( this . _showTimeoutId ) ;
886906 clearTimeout ( this . _hideTimeoutId ) ;
887907 this . _onHide . complete ( ) ;
908+ this . _triggerElement = null ! ;
888909 }
889910
890911 _animationStart ( ) {
@@ -923,6 +944,12 @@ export abstract class _TooltipComponentBase implements OnDestroy {
923944 this . _changeDetectorRef . markForCheck ( ) ;
924945 }
925946
947+ _handleMouseLeave ( { relatedTarget} : MouseEvent ) {
948+ if ( ! relatedTarget || ! this . _triggerElement . contains ( relatedTarget as Node ) ) {
949+ this . hide ( this . _mouseLeaveHideDelay ) ;
950+ }
951+ }
952+
926953 /**
927954 * Callback for when the timeout in this.show() gets completed.
928955 * This method is only needed by the mdc-tooltip, and so it is only implemented
@@ -946,6 +973,7 @@ export abstract class _TooltipComponentBase implements OnDestroy {
946973 // Forces the element to have a layout in IE and Edge. This fixes issues where the element
947974 // won't be rendered if the animations are disabled or there is no web animations polyfill.
948975 '[style.zoom]' : '_visibility === "visible" ? 1 : null' ,
976+ '(mouseleave)' : '_handleMouseLeave($event)' ,
949977 'aria-hidden' : 'true' ,
950978 } ,
951979} )
0 commit comments