Skip to content

Commit 013fe04

Browse files
authored
fix(material/autocomplete): switch away from animations module (#30356)
Switches the autocomplete away from the animations module. The animations are implemented using CSS instead.
1 parent 4fa46bc commit 013fe04

File tree

7 files changed

+30
-55
lines changed

7 files changed

+30
-55
lines changed

src/material/autocomplete/animations.ts

Lines changed: 0 additions & 36 deletions
This file was deleted.

src/material/autocomplete/autocomplete-trigger.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -736,13 +736,7 @@ export class MatAutocompleteTrigger
736736
) {
737737
this._clearPreviousSelectedOption(null);
738738
this._assignOptionValue(null);
739-
// Wait for the animation to finish before clearing the form control value, otherwise
740-
// the options might change while the animation is running which looks glitchy.
741-
if (panel._animationDone) {
742-
panel._animationDone.pipe(take(1)).subscribe(() => this._onChange(null));
743-
} else {
744-
this._onChange(null);
745-
}
739+
this._onChange(null);
746740
}
747741

748742
this.closePanel();

src/material/autocomplete/autocomplete.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@
66
[class]="_classList"
77
[class.mat-mdc-autocomplete-visible]="showPanel"
88
[class.mat-mdc-autocomplete-hidden]="!showPanel"
9+
[class.mat-autocomplete-panel-animations-enabled]="!_animationsDisabled"
910
[class.mat-primary]="_color === 'primary'"
1011
[class.mat-accent]="_color === 'accent'"
1112
[class.mat-warn]="_color === 'warn'"
1213
[attr.aria-label]="ariaLabel || null"
1314
[attr.aria-labelledby]="_getPanelAriaLabelledby(formFieldId)"
14-
[@panelAnimation]="isOpen ? 'visible' : 'hidden'"
15-
(@panelAnimation.done)="_animationDone.next($event)"
1615
#panel>
1716
<ng-content></ng-content>
1817
</div>

src/material/autocomplete/autocomplete.scss

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,25 @@ div.mat-mdc-autocomplete-panel {
5050
}
5151
}
5252

53+
@keyframes _mat-autocomplete-enter {
54+
from {
55+
opacity: 0;
56+
transform: scaleY(0.8);
57+
}
58+
59+
to {
60+
opacity: 1;
61+
transform: none;
62+
}
63+
}
64+
65+
// Note: the autocomplete intentionally only implements an enter animation.
66+
// The exit animation can look glitchy, because usually selecting an option
67+
// causes the list to change and jump around while it's animating.
68+
.mat-autocomplete-panel-animations-enabled {
69+
animation: _mat-autocomplete-enter 120ms cubic-bezier(0, 0, 0.2, 1);
70+
}
71+
5372
// Prevent the overlay host node from affecting its surrounding layout.
5473
mat-autocomplete {
5574
display: none;

src/material/autocomplete/autocomplete.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3849,6 +3849,8 @@ describe('MatAutocomplete', () => {
38493849

38503850
dispatchFakeEvent(document.querySelector('mat-option')!, 'click');
38513851
fixture.detectChanges();
3852+
fixture.componentInstance.trigger.openPanel();
3853+
fixture.detectChanges();
38523854

38533855
const selectedOption = document.querySelector('mat-option[aria-selected="true"]');
38543856
expect(selectedOption).withContext('Expected an option to be selected.').not.toBeNull();
@@ -3875,6 +3877,8 @@ describe('MatAutocomplete', () => {
38753877

38763878
dispatchFakeEvent(document.querySelector('mat-option')!, 'click');
38773879
fixture.detectChanges();
3880+
fixture.componentInstance.trigger.openPanel();
3881+
fixture.detectChanges();
38783882

38793883
const selectedOption = document.querySelector('mat-option[aria-selected="true"]');
38803884
expect(selectedOption).withContext('Expected an option to be selected.').not.toBeNull();

src/material/autocomplete/autocomplete.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
import {
10+
ANIMATION_MODULE_TYPE,
1011
AfterContentInit,
1112
ChangeDetectionStrategy,
1213
ChangeDetectorRef,
@@ -25,7 +26,6 @@ import {
2526
booleanAttribute,
2627
inject,
2728
} from '@angular/core';
28-
import {AnimationEvent} from '@angular/animations';
2929
import {
3030
MAT_OPTGROUP,
3131
MAT_OPTION_PARENT_COMPONENT,
@@ -35,7 +35,6 @@ import {
3535
} from '@angular/material/core';
3636
import {_IdGenerator, ActiveDescendantKeyManager} from '@angular/cdk/a11y';
3737
import {Platform} from '@angular/cdk/platform';
38-
import {panelAnimation} from './animations';
3938
import {Subscription} from 'rxjs';
4039

4140
/** Event object that is emitted when an autocomplete option is selected. */
@@ -109,18 +108,15 @@ export function MAT_AUTOCOMPLETE_DEFAULT_OPTIONS_FACTORY(): MatAutocompleteDefau
109108
'class': 'mat-mdc-autocomplete',
110109
},
111110
providers: [{provide: MAT_OPTION_PARENT_COMPONENT, useExisting: MatAutocomplete}],
112-
animations: [panelAnimation],
113111
})
114112
export class MatAutocomplete implements AfterContentInit, OnDestroy {
115113
private _changeDetectorRef = inject(ChangeDetectorRef);
116114
private _elementRef = inject<ElementRef<HTMLElement>>(ElementRef);
117115
protected _defaults = inject<MatAutocompleteDefaultOptions>(MAT_AUTOCOMPLETE_DEFAULT_OPTIONS);
118-
116+
protected _animationsDisabled =
117+
inject(ANIMATION_MODULE_TYPE, {optional: true}) === 'NoopAnimations';
119118
private _activeOptionChanges = Subscription.EMPTY;
120119

121-
/** Emits when the panel animation is done. Null if the panel doesn't animate. */
122-
_animationDone = new EventEmitter<AnimationEvent>();
123-
124120
/** Manages active item in option list based on key events. */
125121
_keyManager: ActiveDescendantKeyManager<MatOption>;
126122

@@ -282,7 +278,6 @@ export class MatAutocomplete implements AfterContentInit, OnDestroy {
282278
ngOnDestroy() {
283279
this._keyManager?.destroy();
284280
this._activeOptionChanges.unsubscribe();
285-
this._animationDone.complete();
286281
}
287282

288283
/**

tools/public_api_guard/material/autocomplete.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import { ActiveDescendantKeyManager } from '@angular/cdk/a11y';
88
import { AfterContentInit } from '@angular/core';
99
import { AfterViewInit } from '@angular/core';
10-
import { AnimationEvent as AnimationEvent_2 } from '@angular/animations';
1110
import { ControlValueAccessor } from '@angular/forms';
1211
import { ElementRef } from '@angular/core';
1312
import { EventEmitter } from '@angular/core';
@@ -57,7 +56,8 @@ export const MAT_AUTOCOMPLETE_VALUE_ACCESSOR: any;
5756
// @public
5857
export class MatAutocomplete implements AfterContentInit, OnDestroy {
5958
constructor(...args: unknown[]);
60-
_animationDone: EventEmitter<AnimationEvent_2>;
59+
// (undocumented)
60+
protected _animationsDisabled: boolean;
6161
ariaLabel: string;
6262
ariaLabelledby: string;
6363
autoActiveFirstOption: boolean;

0 commit comments

Comments
 (0)