Skip to content

Commit e1d775d

Browse files
authored
fix(material-experimental/mdc-list): support noop animations (#23117)
Fixes that the list animations weren't being disabled with the `NoopAnimationsModule`.
1 parent 8482823 commit e1d775d

File tree

4 files changed

+38
-18
lines changed

4 files changed

+38
-18
lines changed

src/material-experimental/mdc-list/list-base.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
RippleTarget,
3030
setLines,
3131
} from '@angular/material-experimental/mdc-core';
32+
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';
3233
import {numbers} from '@material/ripple';
3334
import {Subscription} from 'rxjs';
3435
import {startWith} from 'rxjs/operators';
@@ -54,12 +55,16 @@ export abstract class MatListItemBase implements AfterContentInit, OnDestroy, Ri
5455
/** Host element for the list item. */
5556
_hostElement: HTMLElement;
5657

58+
/** Whether animations are disabled. */
59+
_noopAnimations: boolean;
60+
5761
@ContentChildren(MatListAvatarCssMatStyler, {descendants: false}) _avatars: QueryList<never>;
5862
@ContentChildren(MatListIconCssMatStyler, {descendants: false}) _icons: QueryList<never>;
5963

6064
@Input()
6165
get disableRipple(): boolean {
62-
return this.disabled || this._disableRipple || this._listBase.disableRipple;
66+
return this.disabled || this._disableRipple || this._listBase.disableRipple ||
67+
this._noopAnimations;
6368
}
6469
set disableRipple(value: boolean) { this._disableRipple = coerceBooleanProperty(value); }
6570
private _disableRipple: boolean = false;
@@ -90,12 +95,14 @@ export abstract class MatListItemBase implements AfterContentInit, OnDestroy, Ri
9095
constructor(public _elementRef: ElementRef<HTMLElement>, protected _ngZone: NgZone,
9196
private _listBase: MatListBase, private _platform: Platform,
9297
@Optional() @Inject(MAT_RIPPLE_GLOBAL_OPTIONS)
93-
globalRippleOptions?: RippleGlobalOptions) {
98+
globalRippleOptions?: RippleGlobalOptions,
99+
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string) {
94100
// We have to clone the object, because we don't want to mutate a global value when we assign
95101
// the `animation` further down. The downside of doing this is that the ripple renderer won't
96102
// pick up dynamic changes to `disabled`, but it's not something we officially support.
97103
this.rippleConfig = {...(globalRippleOptions || {})};
98104
this._hostElement = this._elementRef.nativeElement;
105+
this._noopAnimations = animationMode === 'NoopAnimations';
99106

100107
if (!this.rippleConfig.animation) {
101108
this.rippleConfig.animation = {

src/material-experimental/mdc-list/list-option.scss

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,29 @@
44
@use '../../cdk/a11y';
55
@use './list-option-trailing-avatar-compat';
66

7-
// The MDC-based list-option uses the MDC checkbox for the selection indicators.
8-
// We need to ensure that the checkbox styles are included for the list-option.
9-
@include mdc-checkbox.without-ripple($query: mdc-helpers.$mat-base-styles-query);
10-
117
// For compatibility with the non-MDC list, we support avatars that are shown at the end
128
// of the list option. We create a class similar to MDC's `--trailing-icon` one.
139
@include list-option-trailing-avatar-compat.core-styles($query: mdc-helpers.$mat-base-styles-query);
1410

15-
// The internal checkbox is purely decorative, but because it's an `input`, the user can still
16-
// focus it by tabbing or clicking. Furthermore, `mat-list-option` has the `option` role which
17-
// doesn't allow a nested `input`. We use `display: none` both to remove it from the tab order
18-
// and to prevent focus from reaching it through the screen reader's forms mode. Ideally we'd
19-
// remove the `input` completely, but we can't because MDC uses a `:checked` selector to
20-
// toggle the selected styles.
21-
.mat-mdc-list-option .mdc-checkbox__native-control {
22-
display: none;
11+
.mat-mdc-list-option {
12+
// The MDC-based list-option uses the MDC checkbox for the selection indicators.
13+
// We need to ensure that the checkbox styles are not included for the list-option.
14+
@include mdc-checkbox.without-ripple(
15+
$query: mdc-helpers.$mat-base-styles-without-animation-query);
16+
17+
&:not(._mat-animation-noopable) {
18+
@include mdc-checkbox.without-ripple($query: animation);
19+
}
20+
21+
// The internal checkbox is purely decorative, but because it's an `input`, the user can still
22+
// focus it by tabbing or clicking. Furthermore, `mat-list-option` has the `option` role which
23+
// doesn't allow a nested `input`. We use `display: none` both to remove it from the tab order
24+
// and to prevent focus from reaching it through the screen reader's forms mode. Ideally we'd
25+
// remove the `input` completely, but we can't because MDC uses a `:checked` selector to
26+
// toggle the selected styles.
27+
.mdc-checkbox__native-control {
28+
display: none;
29+
}
2330
}
2431

2532
@include a11y.high-contrast(active, off) {

src/material-experimental/mdc-list/list-option.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
RippleGlobalOptions,
3535
ThemePalette,
3636
} from '@angular/material-experimental/mdc-core';
37+
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';
3738
import {MatListBase, MatListItemBase} from './list-base';
3839
import {LIST_OPTION, ListOption, MatListOptionCheckboxPosition} from './list-option-types';
3940

@@ -81,6 +82,7 @@ export interface SelectionList extends MatListBase {
8182
'[class.mdc-list-item--with-trailing-checkbox]': '_hasCheckboxAt("after")',
8283
'[class.mat-accent]': 'color !== "primary" && color !== "warn"',
8384
'[class.mat-warn]': 'color === "warn"',
85+
'[class._mat-animation-noopable]': '_noopAnimations',
8486
'(blur)': '_handleBlur()',
8587
},
8688
templateUrl: 'list-option.html',
@@ -154,8 +156,9 @@ export class MatListOption extends MatListItemBase implements ListOption, OnInit
154156
platform: Platform,
155157
@Inject(SELECTION_LIST) public _selectionList: SelectionList,
156158
private _changeDetectorRef: ChangeDetectorRef,
157-
@Optional() @Inject(MAT_RIPPLE_GLOBAL_OPTIONS) globalRippleOptions?: RippleGlobalOptions) {
158-
super(element, ngZone, _selectionList, platform, globalRippleOptions);
159+
@Optional() @Inject(MAT_RIPPLE_GLOBAL_OPTIONS) globalRippleOptions?: RippleGlobalOptions,
160+
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string) {
161+
super(element, ngZone, _selectionList, platform, globalRippleOptions, animationMode);
159162

160163
// By default, we mark all options as unselected. The MDC list foundation will
161164
// automatically update the attribute based on selection. Note that we need to

src/material-experimental/mdc-list/list.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
MAT_RIPPLE_GLOBAL_OPTIONS,
2525
RippleGlobalOptions,
2626
} from '@angular/material-experimental/mdc-core';
27+
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';
2728
import {MatListBase, MatListItemBase} from './list-base';
2829

2930
@Component({
@@ -54,6 +55,7 @@ export class MatList extends MatListBase {}
5455
// the trailing meta class. Note that we also add this even if there is no projected `meta`
5556
// content. This is because there is no good way to check for remaining projected content.
5657
'[class.mdc-list-item--with-trailing-meta]': 'lines.length !== 0',
58+
'[class._mat-animation-noopable]': '_noopAnimations',
5759
},
5860
templateUrl: 'list-item.html',
5961
encapsulation: ViewEncapsulation.None,
@@ -69,7 +71,8 @@ export class MatListItem extends MatListItemBase {
6971
ngZone: NgZone,
7072
listBase: MatListBase,
7173
platform: Platform,
72-
@Optional() @Inject(MAT_RIPPLE_GLOBAL_OPTIONS) globalRippleOptions?: RippleGlobalOptions) {
73-
super(element, ngZone, listBase, platform, globalRippleOptions);
74+
@Optional() @Inject(MAT_RIPPLE_GLOBAL_OPTIONS) globalRippleOptions?: RippleGlobalOptions,
75+
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string) {
76+
super(element, ngZone, listBase, platform, globalRippleOptions, animationMode);
7477
}
7578
}

0 commit comments

Comments
 (0)