Skip to content

Commit 7e9878c

Browse files
authored
fix(material/card): tokenize the card elevation (#26770)
* fix(material/card): tokenize the card elevation * fix(material/card): fix lint
1 parent 468c4dc commit 7e9878c

File tree

5 files changed

+141
-98
lines changed

5 files changed

+141
-98
lines changed

src/material/card/_card-theme.scss

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
@use '../core/theming/theming';
2-
@use '../core/style/private';
32
@use '../core/typography/typography';
43
@use '../core/tokens/token-utils';
54
@use '../core/tokens/m2/mat/card' as tokens-mat-card;
@@ -10,31 +9,29 @@
109

1110
@mixin color($config-or-theme) {
1211
$config: theming.get-color-config($config-or-theme);
13-
$mdc-elevated-card-color-tokens: tokens-mdc-elevated-card.get-color-tokens($config);
14-
$mdc-outlined-card-color-tokens: tokens-mdc-outlined-card.get-color-tokens($config);
12+
$mdc-elevated-card-color-tokens: token-utils.resolve-elevation(
13+
tokens-mdc-elevated-card.get-color-tokens($config),
14+
container-elevation,
15+
container-shadow-color
16+
);
17+
$mdc-outlined-card-color-tokens: token-utils.resolve-elevation(
18+
tokens-mdc-outlined-card.get-color-tokens($config),
19+
container-elevation,
20+
container-shadow-color,
21+
);
1522
$mat-card-color-tokens: tokens-mat-card.get-color-tokens($config);
1623

1724
// Add values for card tokens.
1825
.mat-mdc-card {
1926
@include mdc-elevated-card-theme.theme($mdc-elevated-card-color-tokens);
2027
@include mdc-outlined-card-theme.theme($mdc-outlined-card-color-tokens);
2128
@include token-utils.create-token-values(tokens-mat-card.$prefix, $mat-card-color-tokens);
22-
23-
// TODO(mmalerba): This should be based on tokens, but the elevation tokens don't seem to be
24-
// working currently. They wind up setting values like `box-shadow: var(--e); --e: 1`
25-
@include private.private-theme-elevation(1, $config);
26-
}
27-
28-
.mat-mdc-card-outlined {
29-
// TODO(mmalerba): This should be based on tokens, but the elevation tokens don't seem to be
30-
// working currently. They wind up setting values like `box-shadow: var(--e); --e: 1`
31-
@include private.private-theme-elevation(0, $config);
3229
}
3330
}
3431

3532
@mixin typography($config-or-theme) {
3633
$config: typography.private-typography-to-2018-config(
37-
theming.get-typography-config($config-or-theme));
34+
theming.get-typography-config($config-or-theme));
3835
$mdc-elevated-card-typography-tokens: tokens-mdc-elevated-card.get-typography-tokens($config);
3936
$mdc-outlined-card-typography-tokens: tokens-mdc-outlined-card.get-typography-tokens($config);
4037
$mat-card-typography-tokens: tokens-mat-card.get-typography-tokens($config);

src/material/card/card.scss

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
@use 'sass:map';
12
@use '@material/card' as mdc-card;
23
@use '@material/card/elevated-card-theme' as mdc-elevated-card-theme;
34
@use '@material/card/outlined-card-theme' as mdc-outlined-card-theme;
@@ -17,7 +18,18 @@
1718

1819
.mat-mdc-card {
1920
// Add the official slots for the MDC elevated-card.
20-
@include mdc-elevated-card-theme.theme-styles($mdc-elevated-card-token-slots);
21+
@include mdc-elevated-card-theme.theme-styles(map.merge($mdc-elevated-card-token-slots, (
22+
// MDC emits the box-shadow on .mdc-card, so the full selector would be
23+
// `.mat-mdc-card .mdc-card` which is incorrect. We emit the elevation slot ourselves instead.
24+
container-elevation: null,
25+
container-shadow-color: null,
26+
)));
27+
28+
// Emit the elevation slot directly on .mat-mdc-card.
29+
@include token-utils.use-tokens(
30+
tokens-mdc-elevated-card.$prefix, $mdc-elevated-card-token-slots) {
31+
@include token-utils.create-token-slot(box-shadow, container-elevation);
32+
}
2133

2234
// Add default values for MDC card tokens that aren't outputted by the theming API.
2335
@include mdc-elevated-card-theme.theme(tokens-mdc-elevated-card.get-unthemable-tokens());
@@ -28,7 +40,19 @@
2840

2941
.mat-mdc-card-outlined {
3042
// Add the official slots for the MDC outlined-card.
31-
@include mdc-outlined-card-theme.theme-styles($mdc-outlined-card-token-slots);
43+
@include mdc-outlined-card-theme.theme-styles(map.merge($mdc-outlined-card-token-slots, (
44+
// MDC emits the box-shadow on .mdc-card, so the full selector would be
45+
// `.mat-mdc-card-outlined .mdc-card` which is incorrect. We emit the elevation slot ourselves
46+
// instead.
47+
container-elevation: null,
48+
container-shadow-color: null,
49+
)));
50+
51+
// Emit the elevation slot directly on .mat-mdc-card-outlined.
52+
@include token-utils.use-tokens(
53+
tokens-mdc-outlined-card.$prefix, $mdc-outlined-card-token-slots) {
54+
@include token-utils.create-token-slot(box-shadow, container-elevation);
55+
}
3256
}
3357

3458
// Add slots for custom Angular Material card tokens.

src/material/core/tokens/_token-utils.scss

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
@use 'sass:map';
2+
@use '@material/elevation/elevation-theme' as mdc-elevation-theme;
23
@use '@material/theme/custom-properties' as mdc-custom-properties;
34
@use '@material/theme/theme' as mdc-theme;
45
@use '@material/theme/keys' as mdc-keys;
@@ -11,33 +12,33 @@ $_placeholder-color-palette: theming.define-palette(palette.$red-palette);
1112
// Placeholder color config that can be passed to token getter functions when generating token
1213
// slots.
1314
$placeholder-color-config: (
14-
primary: $_placeholder-color-palette,
15-
accent: $_placeholder-color-palette,
16-
warn: $_placeholder-color-palette,
17-
is-dark: false,
18-
foreground: palette.$light-theme-foreground-palette,
19-
background: palette.$light-theme-background-palette,
15+
primary: $_placeholder-color-palette,
16+
accent: $_placeholder-color-palette,
17+
warn: $_placeholder-color-palette,
18+
is-dark: false,
19+
foreground: palette.$light-theme-foreground-palette,
20+
background: palette.$light-theme-background-palette,
2021
);
2122

2223
$_placeholder-typography-level-config: mdc-helpers.typography-config-level-from-mdc(body1);
2324

2425
// Placeholder typography config that can be passed to token getter functions when generating token
2526
// slots.
2627
$placeholder-typography-config: (
27-
font-family: Roboto,
28-
headline-1: $_placeholder-typography-level-config,
29-
headline-2: $_placeholder-typography-level-config,
30-
headline-3: $_placeholder-typography-level-config,
31-
headline-4: $_placeholder-typography-level-config,
32-
headline-5: $_placeholder-typography-level-config,
33-
headline-6: $_placeholder-typography-level-config,
34-
subtitle-1: $_placeholder-typography-level-config,
35-
subtitle-2: $_placeholder-typography-level-config,
36-
body-1: $_placeholder-typography-level-config,
37-
body-2: $_placeholder-typography-level-config,
38-
caption: $_placeholder-typography-level-config,
39-
button: $_placeholder-typography-level-config,
40-
overline: $_placeholder-typography-level-config,
28+
font-family: Roboto,
29+
headline-1: $_placeholder-typography-level-config,
30+
headline-2: $_placeholder-typography-level-config,
31+
headline-3: $_placeholder-typography-level-config,
32+
headline-4: $_placeholder-typography-level-config,
33+
headline-5: $_placeholder-typography-level-config,
34+
headline-6: $_placeholder-typography-level-config,
35+
subtitle-1: $_placeholder-typography-level-config,
36+
subtitle-2: $_placeholder-typography-level-config,
37+
body-1: $_placeholder-typography-level-config,
38+
body-2: $_placeholder-typography-level-config,
39+
caption: $_placeholder-typography-level-config,
40+
button: $_placeholder-typography-level-config,
41+
overline: $_placeholder-typography-level-config,
4142
);
4243

4344
// Placeholder density config that can be passed to token getter functions when generating token
@@ -94,3 +95,15 @@ $_component-prefix: null;
9495
}
9596
@return $result;
9697
}
98+
99+
// MDC doesn't currently handle elevation tokens properly. As a temporary workaround we can combine
100+
// the elevation and shadow-color tokens into a full box-shadow and use it as the value for the
101+
// elevation token.
102+
@function resolve-elevation($tokens, $elevation-token, $shadow-color-token) {
103+
$elevation: map.get($tokens, $elevation-token);
104+
$shadow-color: map.get($tokens, $shadow-color-token);
105+
@return map.merge($tokens, (
106+
$elevation-token: mdc-elevation-theme.elevation-box-shadow($elevation, $shadow-color),
107+
$shadow-color-token: null,
108+
));
109+
}
Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
@use 'sass:map';
2+
@use '../../../style/elevation';
23
@use '../../../theming/theming';
34
@use '../../token-utils';
45

@@ -14,45 +15,49 @@ $prefix: (mdc, elevated-card);
1415
@function get-unthemable-tokens() {
1516
@return (
1617
// The border-radius of the card.
17-
container-shape: 4px,
18+
container-shape: 4px,
1819
// =============================================================================================
1920
// = TOKENS NOT USED IN ANGULAR MATERIAL =
2021
// =============================================================================================
21-
// TODO(mmalerba): The elevation tokens don't seem to work currently.
22-
// Should work with MDC to figure out what's wrong.
23-
container-elevation: null,
24-
container-shadow-color: null,
2522
// Angular Material's card is not an interactive element, and therefore does not support states.
26-
disabled-container-color: null,
27-
disabled-container-elevation: null,
28-
disabled-container-opacity: null,
29-
dragged-container-elevation: null,
30-
dragged-state-layer-color: null,
31-
dragged-state-layer-opacity: null,
32-
focus-container-elevation: null,
33-
focus-state-layer-color:null,
34-
focus-state-layer-opacity: null,
35-
hover-container-elevation: null,
36-
hover-state-layer-color: null,
37-
hover-state-layer-opacity: null,
38-
pressed-container-elevation: null,
39-
pressed-state-layer-color: null,
40-
pressed-state-layer-opacity: null,
23+
disabled-container-color: null,
24+
disabled-container-elevation: null,
25+
disabled-container-opacity: null,
26+
dragged-container-elevation: null,
27+
dragged-state-layer-color: null,
28+
dragged-state-layer-opacity: null,
29+
focus-container-elevation: null,
30+
focus-state-layer-color:null,
31+
focus-state-layer-opacity: null,
32+
hover-container-elevation: null,
33+
hover-state-layer-color: null,
34+
hover-state-layer-opacity: null,
35+
pressed-container-elevation: null,
36+
pressed-state-layer-color: null,
37+
pressed-state-layer-opacity: null,
4138
// Angular Material does not currently support surface tint.
42-
container-surface-tint-layer-color: null,
39+
container-surface-tint-layer-color: null,
4340
// MDC does not seem to use these tokens.
44-
icon-color: null,
45-
icon-size: null,
41+
icon-color: null,
42+
icon-size: null,
4643
);
4744
}
4845

4946
// Tokens that can be configured through Angular Material's color theming API.
5047
@function get-color-tokens($config) {
5148
$background: map.get($config, background);
49+
$foreground: map.get($config, foreground);
50+
$elevation: theming.get-color-from-palette($foreground, elevation);
5251

5352
@return (
5453
// The background color of the card.
55-
container-color: theming.get-color-from-palette($background, card),
54+
container-color: theming.get-color-from-palette($background, card),
55+
// The elevation level of the card.
56+
// (Part of the color tokens because it needs to be combined with the shadow color to generate
57+
// the final box-shadow).
58+
container-elevation: 1,
59+
// The color of the card's shadow.
60+
container-shadow-color: if($elevation != null, $elevation, elevation.$color),
5661
);
5762
}
5863

@@ -70,9 +75,9 @@ $prefix: (mdc, elevated-card);
7075
// This is used to create token slots.
7176
@function get-token-slots() {
7277
@return token-utils.merge-all(
73-
get-unthemable-tokens(),
74-
get-color-tokens(token-utils.$placeholder-color-config),
75-
get-typography-tokens(token-utils.$placeholder-typography-config),
76-
get-density-tokens(token-utils.$placeholder-density-config)
78+
get-unthemable-tokens(),
79+
get-color-tokens(token-utils.$placeholder-color-config),
80+
get-typography-tokens(token-utils.$placeholder-typography-config),
81+
get-density-tokens(token-utils.$placeholder-density-config)
7782
);
7883
}
Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
@use 'sass:map';
2+
@use '../../../style/elevation';
23
@use '../../../theming/theming';
34
@use '../../token-utils';
45

@@ -14,54 +15,57 @@ $prefix: (mdc, outlined-card);
1415
@function get-unthemable-tokens() {
1516
@return (
1617
// The border-radius of the card.
17-
container-shape: 4px,
18+
container-shape: 4px,
1819
// The thickness of the card's border.
19-
outline-width: 1px,
20+
outline-width: 1px,
2021
// =============================================================================================
2122
// = TOKENS NOT USED IN ANGULAR MATERIAL =
2223
// =============================================================================================
23-
// TODO(mmalerba): The elevation tokens don't seem to work currently.
24-
// Should work with MDC to figure out what's wrong.
25-
container-elevation: null,
26-
container-shadow-color: null,
2724
// Angular Material's card is not an interactive element, and therefore does not support states.
28-
disabled-container-elevation: null,
29-
disabled-outline-color: null,
30-
disabled-outline-opacity: null,
31-
dragged-container-elevation: null,
32-
dragged-outline-color: null,
33-
dragged-state-layer-color: null,
34-
dragged-state-layer-opacity: null,
35-
focus-container-elevation: null,
36-
focus-outline-color: null,
37-
focus-state-layer-color: null,
38-
focus-state-layer-opacity: null,
39-
hover-container-elevation: null,
40-
hover-outline-color: null,
41-
hover-state-layer-color: null,
42-
hover-state-layer-opacity: null,
43-
pressed-container-elevation: null,
44-
pressed-outline-color: null,
45-
pressed-state-layer-color: null,
46-
pressed-state-layer-opacity: null,
25+
disabled-container-elevation: null,
26+
disabled-outline-color: null,
27+
disabled-outline-opacity: null,
28+
dragged-container-elevation: null,
29+
dragged-outline-color: null,
30+
dragged-state-layer-color: null,
31+
dragged-state-layer-opacity: null,
32+
focus-container-elevation: null,
33+
focus-outline-color: null,
34+
focus-state-layer-color: null,
35+
focus-state-layer-opacity: null,
36+
hover-container-elevation: null,
37+
hover-outline-color: null,
38+
hover-state-layer-color: null,
39+
hover-state-layer-opacity: null,
40+
pressed-container-elevation: null,
41+
pressed-outline-color: null,
42+
pressed-state-layer-color: null,
43+
pressed-state-layer-opacity: null,
4744
// Angular Material does not currently support surface tint.
48-
container-surface-tint-layer-color: null,
45+
container-surface-tint-layer-color: null,
4946
// MDC does not seem to use these tokens.
50-
icon-color: null,
51-
icon-size: null,
47+
icon-color: null,
48+
icon-size: null,
5249
);
5350
}
5451

5552
// Tokens that can be configured through Angular Material's color theming API.
5653
@function get-color-tokens($config) {
5754
$background: map.get($config, background);
5855
$foreground: map.get($config, foreground);
56+
$elevation: theming.get-color-from-palette($foreground, elevation);
5957

6058
@return (
6159
// The background color of the card.
62-
container-color: theming.get-color-from-palette($background, card),
60+
container-color: theming.get-color-from-palette($background, card),
6361
// The border color of the card.
64-
outline-color: theming.get-color-from-palette($foreground, base, 0.12),
62+
outline-color: theming.get-color-from-palette($foreground, base, 0.12),
63+
// The elevation level of the card.
64+
// (Part of the color tokens because it needs to be combined with the shadow color to generate
65+
// the final box-shadow).
66+
container-elevation: 0,
67+
// The color of the card's shadow.
68+
container-shadow-color: if($elevation != null, $elevation, elevation.$color),
6569
);
6670
}
6771

@@ -79,9 +83,9 @@ $prefix: (mdc, outlined-card);
7983
// This is used to create token slots.
8084
@function get-token-slots() {
8185
@return token-utils.merge-all(
82-
get-unthemable-tokens(),
83-
get-color-tokens(token-utils.$placeholder-color-config),
84-
get-typography-tokens(token-utils.$placeholder-typography-config),
85-
get-density-tokens(token-utils.$placeholder-density-config)
86+
get-unthemable-tokens(),
87+
get-color-tokens(token-utils.$placeholder-color-config),
88+
get-typography-tokens(token-utils.$placeholder-typography-config),
89+
get-density-tokens(token-utils.$placeholder-density-config)
8690
);
8791
}

0 commit comments

Comments
 (0)