Skip to content

Commit 03d00f5

Browse files
committed
fix(material/menu): update elevation logic for M3
The menu has some logic to increase its elevation depending on it depth which hasn't worked since we introduced M3. These changes update it to account for a different base elevation.
1 parent a4846a9 commit 03d00f5

File tree

4 files changed

+32
-15
lines changed

4 files changed

+32
-15
lines changed

src/material/core/tokens/m2/mat/_menu.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ $prefix: (mat, menu);
1818
item-trailing-spacing: 16px,
1919
item-with-icon-leading-spacing: 16px,
2020
item-with-icon-trailing-spacing: 16px,
21+
// Note that this uses a value, rather than a computed box-shadow, because we use
22+
// the value at runtime to determine which shadow to set based on the menu's depth.
23+
base-elevation-level: 8,
2124
);
2225
}
2326

src/material/core/tokens/m3/mat/_menu.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ $prefix: (mat, menu);
3535
item-with-icon-leading-spacing: token-utils.hardcode(12px, $exclude-hardcoded),
3636
item-with-icon-trailing-spacing: token-utils.hardcode(12px, $exclude-hardcoded),
3737
container-color: map.get($systems, md-sys-color, surface-container),
38+
// Note that this uses a value, rather than a computed box-shadow, because we use
39+
// the value at runtime to determine which shadow to set based on the menu's depth.
40+
base-elevation-level: token-utils.hardcode(2, $exclude-hardcoded),
3841
)
3942
);
4043

src/material/menu/menu.spec.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ describe('MDC-based MatMenu', () => {
606606
const panel = overlayContainerElement.querySelector('.mat-mdc-menu-panel')!;
607607

608608
expect(panel.classList).toContain('custom-one');
609-
expect(panel.classList).toContain('mat-elevation-z8');
609+
expect(panel.classList).toContain('mat-elevation-z2');
610610

611611
fixture.componentInstance.panelClass = 'custom-two';
612612
fixture.detectChanges();
@@ -615,8 +615,8 @@ describe('MDC-based MatMenu', () => {
615615
expect(panel.classList).toContain('custom-two');
616616
expect(panel.classList).toContain('mat-mdc-elevation-specific');
617617
expect(panel.classList)
618-
.withContext('Expected mat-elevation-z8 not to be removed')
619-
.toContain('mat-elevation-z8');
618+
.withContext('Expected mat-elevation-z2 not to be removed')
619+
.toContain('mat-elevation-z2');
620620
}));
621621

622622
it('should set the "menu" role on the overlay panel', fakeAsync(() => {
@@ -2369,17 +2369,17 @@ describe('MDC-based MatMenu', () => {
23692369
expect(menus[0].classList).toContain('mat-mdc-elevation-specific');
23702370
expect(menus[0].classList)
23712371
.withContext('Expected root menu to have base elevation.')
2372-
.toContain('mat-elevation-z8');
2372+
.toContain('mat-elevation-z2');
23732373

23742374
expect(menus[1].classList).toContain('mat-mdc-elevation-specific');
23752375
expect(menus[1].classList)
23762376
.withContext('Expected first sub-menu to have base elevation + 1.')
2377-
.toContain('mat-elevation-z9');
2377+
.toContain('mat-elevation-z3');
23782378

23792379
expect(menus[2].classList).toContain('mat-mdc-elevation-specific');
23802380
expect(menus[2].classList)
23812381
.withContext('Expected second sub-menu to have base elevation + 2.')
2382-
.toContain('mat-elevation-z10');
2382+
.toContain('mat-elevation-z4');
23832383
}));
23842384

23852385
it('should update the elevation when the same menu is opened at a different depth', fakeAsync(() => {
@@ -2398,7 +2398,7 @@ describe('MDC-based MatMenu', () => {
23982398
expect(lastMenu.classList).toContain('mat-mdc-elevation-specific');
23992399
expect(lastMenu.classList)
24002400
.withContext('Expected menu to have the base elevation plus two.')
2401-
.toContain('mat-elevation-z10');
2401+
.toContain('mat-elevation-z4');
24022402

24032403
(overlay.querySelector('.cdk-overlay-backdrop')! as HTMLElement).click();
24042404
fixture.detectChanges();
@@ -2417,10 +2417,10 @@ describe('MDC-based MatMenu', () => {
24172417
expect(lastMenu.classList).toContain('mat-mdc-elevation-specific');
24182418
expect(lastMenu.classList)
24192419
.not.withContext('Expected menu not to maintain old elevation.')
2420-
.toContain('mat-elevation-z10');
2420+
.toContain('mat-elevation-z4');
24212421
expect(lastMenu.classList)
24222422
.withContext('Expected menu to have the proper updated elevation.')
2423-
.toContain('mat-elevation-z8');
2423+
.toContain('mat-elevation-z2');
24242424
}));
24252425

24262426
it('should not change focus origin if origin not specified for trigger', fakeAsync(() => {
@@ -2461,7 +2461,7 @@ describe('MDC-based MatMenu', () => {
24612461
expect(menuClasses)
24622462
.withContext('Expected user elevation to be maintained')
24632463
.toContain('mat-elevation-z24');
2464-
expect(menuClasses).not.toContain('mat-elevation-z8', 'Expected no stacked elevation.');
2464+
expect(menuClasses).not.toContain('mat-elevation-z2', 'Expected no stacked elevation.');
24652465
}));
24662466

24672467
it('should close all of the menus when the root is closed programmatically', fakeAsync(() => {
@@ -2762,7 +2762,7 @@ const SIMPLE_MENU_TEMPLATE = `
27622762
<button mat-menu-item>
27632763
<span>Item with text inside span</span>
27642764
</button>
2765-
@for (item of extraItems; track item) {
2765+
@for (item of extraItems; track $index) {
27662766
<button mat-menu-item> {{item}} </button>
27672767
}
27682768
</mat-menu>
@@ -2949,7 +2949,7 @@ class NestedMenuCustomElevation {
29492949
template: `
29502950
<button [matMenuTriggerFor]="root" #rootTriggerEl>Toggle menu</button>
29512951
<mat-menu #root="matMenu">
2952-
@for (item of items; track item) {
2952+
@for (item of items; track $index) {
29532953
<button
29542954
mat-menu-item
29552955
class="level-one-trigger"
@@ -3071,7 +3071,7 @@ class MenuWithCheckboxItems {
30713071
template: `
30723072
<button [matMenuTriggerFor]="menu">Toggle menu</button>
30733073
<mat-menu #menu="matMenu">
3074-
@for (item of items; track item) {
3074+
@for (item of items; track $index) {
30753075
<button [disabled]="item.disabled"mat-menu-item>{{item.label}}</button>
30763076
}
30773077
</mat-menu>
@@ -3092,7 +3092,7 @@ class SimpleMenuWithRepeater {
30923092
<button [matMenuTriggerFor]="menu">Toggle menu</button>
30933093
<mat-menu #menu="matMenu">
30943094
<ng-template matMenuContent>
3095-
@for (item of items; track item) {
3095+
@for (item of items; track $index) {
30963096
<button [disabled]="item.disabled" mat-menu-item>{{item.label}}</button>
30973097
}
30983098
</ng-template>

src/material/menu/menu.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ export class MatMenu implements AfterContentInit, MatMenuPanel<MatMenuItem>, OnI
120120
private _firstItemFocusRef?: AfterRenderRef;
121121
private _previousElevation: string;
122122
private _elevationPrefix = 'mat-elevation-z';
123-
private _baseElevation = 8;
123+
private _baseElevation: number | null = null;
124124

125125
/** All items inside the menu. Includes items nested inside another menu. */
126126
@ContentChildren(MatMenuItem, {descendants: true}) _allItems: QueryList<MatMenuItem>;
@@ -470,6 +470,17 @@ export class MatMenu implements AfterContentInit, MatMenuPanel<MatMenuItem>, OnI
470470
* @param depth Number of parent menus that come before the menu.
471471
*/
472472
setElevation(depth: number): void {
473+
// The base elevation depends on which version of the spec
474+
// we're running so we have to resolve it at runtime.
475+
if (this._baseElevation === null) {
476+
const styles =
477+
typeof getComputedStyle === 'function'
478+
? getComputedStyle(this._elementRef.nativeElement)
479+
: null;
480+
const value = styles?.getPropertyValue('--mat-menu-base-elevation-level') || '8';
481+
this._baseElevation = parseInt(value);
482+
}
483+
473484
// The elevation starts at the base and increases by one for each level.
474485
// Capped at 24 because that's the maximum elevation defined in the Material design spec.
475486
const elevation = Math.min(this._baseElevation + depth, 24);

0 commit comments

Comments
 (0)