diff --git a/src/material/core/_core-theme.scss b/src/material/core/_core-theme.scss index 7883579a8923..0a7c013f203f 100644 --- a/src/material/core/_core-theme.scss +++ b/src/material/core/_core-theme.scss @@ -1,12 +1,10 @@ @use './theming/theming'; @use './theming/inspection'; @use './theming/validation'; -@use './style/private'; @use './ripple/ripple-theme'; @use './option/option-theme'; @use './option/optgroup-theme'; @use './selection/pseudo-checkbox/pseudo-checkbox-theme'; -@use './style/elevation'; @use './style/sass-utils'; @use './typography/typography'; @use './tokens/token-utils'; @@ -41,6 +39,10 @@ $_has-inserted-loaded-marker: false; @include option-theme.base($theme); @include optgroup-theme.base($theme); @include pseudo-checkbox-theme.base($theme); + @include sass-utils.current-selector-or-root() { + @include token-utils.create-token-values(tokens-mat-app.$prefix, + tokens-mat-app.get-unthemable-tokens()); + } } // The marker is a concrete style no matter which Material version we're targeting. @@ -60,18 +62,6 @@ $_has-inserted-loaded-marker: false; @include token-utils.create-token-values(tokens-mat-app.$prefix, tokens-mat-app.get-color-tokens($theme)); } - - // Provides external CSS classes for each elevation value. Each CSS class is formatted as - // `mat-elevation-z$zValue` where `$zValue` corresponds to the z-space to which the element is - // elevated. - @for $zValue from 0 through 24 { - $selector: elevation.$prefix + $zValue; - // We need the `mat-mdc-elevation-specific`, because some MDC mixins - // come with elevation baked in and we don't have a way of removing it. - .#{$selector}, .mat-mdc-elevation-specific.#{$selector} { - @include private.private-theme-elevation($zValue, $theme); - } - } } } diff --git a/src/material/core/_core.scss b/src/material/core/_core.scss index c6e3056cf53d..ef7bb5287080 100644 --- a/src/material/core/_core.scss +++ b/src/material/core/_core.scss @@ -2,6 +2,7 @@ @use './tokens/m2/mat/app' as tokens-mat-app; @use './tokens/token-utils'; @use './ripple/ripple'; +@use './style/elevation'; @use './focus-indicators/private'; @use './mdc-helpers/mdc-helpers'; @@ -18,13 +19,26 @@ // Wrapper element that provides the theme background when the // user's content isn't inside of a `mat-sidenav-container`. @at-root { - .mat-app-background { - @include mdc-helpers.disable-mdc-fallback-declarations { - @include token-utils.use-tokens(tokens-mat-app.$prefix, tokens-mat-app.get-token-slots()) { - // Note: we need to emit fallback values here to avoid errors in internal builds. + // Note: we need to emit fallback values here to avoid errors in internal builds. + @include mdc-helpers.disable-mdc-fallback-declarations { + @include token-utils.use-tokens(tokens-mat-app.$prefix, tokens-mat-app.get-token-slots()) { + .mat-app-background { @include token-utils.create-token-slot(background-color, background-color, transparent); @include token-utils.create-token-slot(color, text-color, inherit); } + + // Provides external CSS classes for each elevation value. Each CSS class is formatted as + // `mat-elevation-z$zValue` where `$zValue` corresponds to the z-space to which the element + // is elevated. + @for $zValue from 0 through 24 { + $selector: elevation.$prefix + $zValue; + // We need the `mat-mdc-elevation-specific`, because some MDC mixins + // come with elevation baked in and we don't have a way of removing it. + .#{$selector}, .mat-mdc-elevation-specific.#{$selector} { + @include token-utils.create-token-slot(box-shadow, 'elevation-shadow-level-#{$zValue}', + none); + } + } } } } diff --git a/src/material/core/tokens/m2/mat/_app.scss b/src/material/core/tokens/m2/mat/_app.scss index c82a8b4d1ec2..2443e7f10a6f 100644 --- a/src/material/core/tokens/m2/mat/_app.scss +++ b/src/material/core/tokens/m2/mat/_app.scss @@ -1,3 +1,5 @@ +@use '@material/elevation/elevation-theme' as mdc-elevation; +@use 'sass:map'; @use '../../token-utils'; @use '../../../theming/inspection'; @use '../../../style/sass-utils'; @@ -13,10 +15,19 @@ $prefix: (mat, app); // Tokens that can be configured through Angular Material's color theming API. @function get-color-tokens($theme) { - @return ( + $tokens: ( background-color: inspection.get-theme-color($theme, background, background), text-color: inspection.get-theme-color($theme, foreground, text), ); + + @for $zValue from 0 through 24 { + $elevation-color: inspection.get-theme-color($theme, foreground, elevation); + $shadow: mdc-elevation.elevation-box-shadow($zValue, + if($elevation-color == null, elevation.$color, $elevation-color)); + $tokens: map.set($tokens, 'elevation-shadow-level-#{$zValue}', $shadow); + } + + @return $tokens; } // Tokens that can be configured through Angular Material's typography theming API. diff --git a/src/material/core/tokens/m2/mat/_menu.scss b/src/material/core/tokens/m2/mat/_menu.scss index 79c9155eeb26..e3b04cfe5fb5 100644 --- a/src/material/core/tokens/m2/mat/_menu.scss +++ b/src/material/core/tokens/m2/mat/_menu.scss @@ -18,6 +18,9 @@ $prefix: (mat, menu); item-trailing-spacing: 16px, item-with-icon-leading-spacing: 16px, item-with-icon-trailing-spacing: 16px, + // Note that this uses a value, rather than a computed box-shadow, because we use + // the value at runtime to determine which shadow to set based on the menu's depth. + base-elevation-level: 8, ); } diff --git a/src/material/core/tokens/m3/mat/_app.scss b/src/material/core/tokens/m3/mat/_app.scss index 879fdc9570ad..e54826db04c5 100644 --- a/src/material/core/tokens/m3/mat/_app.scss +++ b/src/material/core/tokens/m3/mat/_app.scss @@ -1,4 +1,5 @@ @use 'sass:map'; +@use '@material/elevation' as mdc-elevation; @use '../../token-utils'; // The prefix used to generate the fully qualified name for tokens in this file. @@ -10,10 +11,18 @@ $prefix: (mat, app); /// @param {Map} $token-slots Possible token slots /// @return {Map} A set of custom tokens for the app @function get-tokens($systems, $exclude-hardcoded, $token-slots) { + $shadow-color: map.get($systems, md-sys-color, shadow); $tokens: ( background-color: map.get($systems, md-sys-color, background), text-color: map.get($systems, md-sys-color, on-background), ); + @if ($shadow-color) { + @for $zValue from 0 through 24 { + $shadow: mdc-elevation.elevation-box-shadow($zValue, $shadow-color); + $tokens: map.set($tokens, 'elevation-shadow-level-#{$zValue}', $shadow); + } + } + @return token-utils.namespace-tokens($prefix, $tokens, $token-slots); } diff --git a/src/material/core/tokens/m3/mat/_menu.scss b/src/material/core/tokens/m3/mat/_menu.scss index bbb36c889c4f..ddc173329e55 100644 --- a/src/material/core/tokens/m3/mat/_menu.scss +++ b/src/material/core/tokens/m3/mat/_menu.scss @@ -35,6 +35,9 @@ $prefix: (mat, menu); item-with-icon-leading-spacing: token-utils.hardcode(12px, $exclude-hardcoded), item-with-icon-trailing-spacing: token-utils.hardcode(12px, $exclude-hardcoded), container-color: map.get($systems, md-sys-color, surface-container), + // Note that this uses a value, rather than a computed box-shadow, because we use + // the value at runtime to determine which shadow to set based on the menu's depth. + base-elevation-level: token-utils.hardcode(2, $exclude-hardcoded), ) ); diff --git a/src/material/menu/menu.spec.ts b/src/material/menu/menu.spec.ts index 7e538385988d..2de78b8f76e0 100644 --- a/src/material/menu/menu.spec.ts +++ b/src/material/menu/menu.spec.ts @@ -606,7 +606,7 @@ describe('MDC-based MatMenu', () => { const panel = overlayContainerElement.querySelector('.mat-mdc-menu-panel')!; expect(panel.classList).toContain('custom-one'); - expect(panel.classList).toContain('mat-elevation-z8'); + expect(panel.classList).toContain('mat-elevation-z2'); fixture.componentInstance.panelClass = 'custom-two'; fixture.detectChanges(); @@ -615,8 +615,8 @@ describe('MDC-based MatMenu', () => { expect(panel.classList).toContain('custom-two'); expect(panel.classList).toContain('mat-mdc-elevation-specific'); expect(panel.classList) - .withContext('Expected mat-elevation-z8 not to be removed') - .toContain('mat-elevation-z8'); + .withContext('Expected mat-elevation-z2 not to be removed') + .toContain('mat-elevation-z2'); })); it('should set the "menu" role on the overlay panel', fakeAsync(() => { @@ -2369,17 +2369,17 @@ describe('MDC-based MatMenu', () => { expect(menus[0].classList).toContain('mat-mdc-elevation-specific'); expect(menus[0].classList) .withContext('Expected root menu to have base elevation.') - .toContain('mat-elevation-z8'); + .toContain('mat-elevation-z2'); expect(menus[1].classList).toContain('mat-mdc-elevation-specific'); expect(menus[1].classList) .withContext('Expected first sub-menu to have base elevation + 1.') - .toContain('mat-elevation-z9'); + .toContain('mat-elevation-z3'); expect(menus[2].classList).toContain('mat-mdc-elevation-specific'); expect(menus[2].classList) .withContext('Expected second sub-menu to have base elevation + 2.') - .toContain('mat-elevation-z10'); + .toContain('mat-elevation-z4'); })); it('should update the elevation when the same menu is opened at a different depth', fakeAsync(() => { @@ -2398,7 +2398,7 @@ describe('MDC-based MatMenu', () => { expect(lastMenu.classList).toContain('mat-mdc-elevation-specific'); expect(lastMenu.classList) .withContext('Expected menu to have the base elevation plus two.') - .toContain('mat-elevation-z10'); + .toContain('mat-elevation-z4'); (overlay.querySelector('.cdk-overlay-backdrop')! as HTMLElement).click(); fixture.detectChanges(); @@ -2417,10 +2417,10 @@ describe('MDC-based MatMenu', () => { expect(lastMenu.classList).toContain('mat-mdc-elevation-specific'); expect(lastMenu.classList) .not.withContext('Expected menu not to maintain old elevation.') - .toContain('mat-elevation-z10'); + .toContain('mat-elevation-z4'); expect(lastMenu.classList) .withContext('Expected menu to have the proper updated elevation.') - .toContain('mat-elevation-z8'); + .toContain('mat-elevation-z2'); })); it('should not change focus origin if origin not specified for trigger', fakeAsync(() => { @@ -2461,7 +2461,7 @@ describe('MDC-based MatMenu', () => { expect(menuClasses) .withContext('Expected user elevation to be maintained') .toContain('mat-elevation-z24'); - expect(menuClasses).not.toContain('mat-elevation-z8', 'Expected no stacked elevation.'); + expect(menuClasses).not.toContain('mat-elevation-z2', 'Expected no stacked elevation.'); })); it('should close all of the menus when the root is closed programmatically', fakeAsync(() => { @@ -2762,7 +2762,7 @@ const SIMPLE_MENU_TEMPLATE = ` - @for (item of extraItems; track item) { + @for (item of extraItems; track $index) { } @@ -2949,7 +2949,7 @@ class NestedMenuCustomElevation { template: ` - @for (item of items; track item) { + @for (item of items; track $index) { - @for (item of items; track item) { + @for (item of items; track $index) { } @@ -3092,7 +3092,7 @@ class SimpleMenuWithRepeater { - @for (item of items; track item) { + @for (item of items; track $index) { } diff --git a/src/material/menu/menu.ts b/src/material/menu/menu.ts index c2e0716ec0fe..b625f64727e2 100644 --- a/src/material/menu/menu.ts +++ b/src/material/menu/menu.ts @@ -120,7 +120,7 @@ export class MatMenu implements AfterContentInit, MatMenuPanel, OnI private _firstItemFocusRef?: AfterRenderRef; private _previousElevation: string; private _elevationPrefix = 'mat-elevation-z'; - private _baseElevation = 8; + private _baseElevation: number | null = null; /** All items inside the menu. Includes items nested inside another menu. */ @ContentChildren(MatMenuItem, {descendants: true}) _allItems: QueryList; @@ -470,6 +470,17 @@ export class MatMenu implements AfterContentInit, MatMenuPanel, OnI * @param depth Number of parent menus that come before the menu. */ setElevation(depth: number): void { + // The base elevation depends on which version of the spec + // we're running so we have to resolve it at runtime. + if (this._baseElevation === null) { + const styles = + typeof getComputedStyle === 'function' + ? getComputedStyle(this._elementRef.nativeElement) + : null; + const value = styles?.getPropertyValue('--mat-menu-base-elevation-level') || '8'; + this._baseElevation = parseInt(value); + } + // The elevation starts at the base and increases by one for each level. // Capped at 24 because that's the maximum elevation defined in the Material design spec. const elevation = Math.min(this._baseElevation + depth, 24); diff --git a/src/material/schematics/ng-generate/table/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html.template b/src/material/schematics/ng-generate/table/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html.template index f0c7c4669975..fba358b44012 100644 --- a/src/material/schematics/ng-generate/table/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html.template +++ b/src/material/schematics/ng-generate/table/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html.template @@ -1,4 +1,4 @@ -
+
diff --git a/src/material/tabs/tab-header.html b/src/material/tabs/tab-header.html index 104cd2df74ff..aca77b31e022 100644 --- a/src/material/tabs/tab-header.html +++ b/src/material/tabs/tab-header.html @@ -1,4 +1,3 @@ -