Skip to content

Commit

Permalink
fix(tooltip): decouple removal logic from change detection
Browse files Browse the repository at this point in the history
Currently the logic in the tooltip that removes it from the DOM is run either if the trigger is destroyed or the exit animation has finished. The problem is that if the trigger is detached from change detection, but hasn't been destroyed, the exit animation will never run and the element won't be cleaned up. These changes switch to using CSS animations and manipulating the DOM node directly to trigger the animation.

Fixes #19365.
  • Loading branch information
crisbeto committed Jun 9, 2020
1 parent fb814bb commit f31088b
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 128 deletions.
2 changes: 0 additions & 2 deletions src/material/tooltip/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ ng_module(
"//src/cdk/portal",
"//src/cdk/scrolling",
"//src/material/core",
"@npm//@angular/animations",
"@npm//@angular/common",
"@npm//@angular/core",
"@npm//rxjs",
Expand Down Expand Up @@ -65,7 +64,6 @@ ng_test_library(
"//src/cdk/overlay",
"//src/cdk/platform",
"//src/cdk/testing/private",
"@npm//@angular/animations",
"@npm//@angular/platform-browser",
],
)
Expand Down
8 changes: 4 additions & 4 deletions src/material/tooltip/tooltip.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="mat-tooltip"
<div #tooltip
class="mat-tooltip"
[ngClass]="tooltipClass"
[class._mat-animation-noopable]="_animationMode === 'NoopAnimations'"
[class.mat-tooltip-handset]="(_isHandset | async)?.matches"
[@state]="_visibility"
(@state.start)="_animationStart()"
(@state.done)="_animationDone($event)">{{message}}</div>
(animationend)="_animationEnd($event)">{{message}}</div>
42 changes: 42 additions & 0 deletions src/material/tooltip/tooltip.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ $mat-tooltip-handset-margin: 24px;
padding-right: $mat-tooltip-horizontal-padding;
overflow: hidden;
text-overflow: ellipsis;
opacity: 0;
transform: scale(0);

// Use a very short animation if animations are disabled so the `animationend` event still fires.
&._mat-animation-noopable {
animation-duration: 1ms;
}

@include cdk-high-contrast(active, off) {
outline: solid 1px;
Expand All @@ -35,3 +42,38 @@ $mat-tooltip-handset-margin: 24px;
padding-left: $mat-tooltip-handset-horizontal-padding;
padding-right: $mat-tooltip-handset-horizontal-padding;
}

@keyframes mat-tooltip-show {
0% {
opacity: 0;
transform: scale(0);
}

50% {
opacity: 0.5;
transform: scale(0.99);
}

100% {
opacity: 1;
transform: scale(1);
}
}

@keyframes mat-tooltip-hide {
0% {
opacity: 1;
}

100% {
opacity: 0;
}
}

.mat-tooltip-show {
animation: mat-tooltip-show 200ms cubic-bezier(0, 0, 0.2, 1) forwards;
}

.mat-tooltip-hide {
animation: mat-tooltip-hide 100ms cubic-bezier(0, 0, 0.2, 1) forwards;
}
Loading

0 comments on commit f31088b

Please sign in to comment.