Skip to content

Commit a12d729

Browse files
committed
fix(material/tooltip): decouple removal logic from change detection
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.
1 parent 4caf039 commit a12d729

File tree

13 files changed

+371
-219
lines changed

13 files changed

+371
-219
lines changed

src/material-experimental/mdc-tooltip/testing/tooltip-harness.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export class MatTooltipHarness extends _MatTooltipHarnessBase {
1414
protected _optionalPanel =
1515
this.documentRootLocatorFactory().locatorForOptional('.mat-mdc-tooltip');
1616
static hostSelector = '.mat-mdc-tooltip-trigger';
17+
protected _hiddenClass = 'mat-mdc-tooltip-hide';
1718

1819
/**
1920
* Gets a `HarnessPredicate` that can be used to search
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
<div
2+
#tooltip
23
class="mdc-tooltip mdc-tooltip--shown mat-mdc-tooltip"
34
[ngClass]="tooltipClass"
4-
[class.mdc-tooltip--multiline]="_isMultiline"
5-
[@state]="_visibility"
6-
(@state.start)="_animationStart()"
7-
(@state.done)="_animationDone($event)">
5+
[class._mat-animation-noopable]="_animationMode === 'NoopAnimations'"
6+
[class.mdc-tooltip--multiline]="_isMultiline">
87
<div class="mdc-tooltip__surface mdc-tooltip__surface-animation">{{message}}</div>
98
</div>

src/material-experimental/mdc-tooltip/tooltip.scss

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,46 @@
1111
// depending on the state of the overlay. For tooltips the overlay panel should never enable
1212
// pointer events. To overwrite the inline CSS from the overlay reference `!important` is needed.
1313
pointer-events: none !important;
14+
15+
opacity: 0;
16+
transform: scale(0.8);
17+
18+
// Use a very short animation if animations are disabled so the `animationend` event still fires.
19+
&._mat-animation-noopable {
20+
animation-duration: 1ms;
21+
}
22+
}
23+
24+
// TODO(crisbeto): we may be able to use MDC directly for these animations.
25+
26+
@keyframes mat-mdc-tooltip-show {
27+
0% {
28+
opacity: 0;
29+
transform: scale(0.8);
30+
}
31+
32+
100% {
33+
opacity: 1;
34+
transform: scale(1);
35+
}
36+
}
37+
38+
@keyframes mat-mdc-tooltip-hide {
39+
0% {
40+
opacity: 1;
41+
transform: scale(1);
42+
}
43+
44+
100% {
45+
opacity: 0;
46+
transform: scale(0.8);
47+
}
48+
}
49+
50+
.mat-mdc-tooltip-show {
51+
animation: mat-mdc-tooltip-show 150ms cubic-bezier(0, 0, 0.2, 1) forwards;
52+
}
53+
54+
.mat-mdc-tooltip-hide {
55+
animation: mat-mdc-tooltip-hide 75ms cubic-bezier(0.4, 0, 1, 1) forwards;
1456
}

0 commit comments

Comments
 (0)