Skip to content

Commit 8a32172

Browse files
authored
fix(material/card): refactor to depend on @angular/material/core/tokens (#26674)
* fix(material/card): refactor to depend on @angular/material/core/tokens * add card tokens with placeholder values * add styles for token slots and values to card * fill in real token values and fix card appearance * address feedback * add custom tokens for Angular Material only features
1 parent 94e6c94 commit 8a32172

File tree

8 files changed

+357
-79
lines changed

8 files changed

+357
-79
lines changed

src/material/card/_card-theme.scss

Lines changed: 42 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,65 @@
11
@use '../core/theming/theming';
2-
@use '../core/mdc-helpers/mdc-helpers';
32
@use '../core/style/private';
43
@use '../core/typography/typography';
4+
@use '../core/tokens/token-utils';
5+
@use '../core/tokens/m2/mat/card' as tokens-mat-card;
6+
@use '../core/tokens/m2/mdc/elevated-card' as tokens-mdc-elevated-card;
7+
@use '../core/tokens/m2/mdc/outlined-card' as tokens-mdc-outlined-card;
58
@use '@material/card/elevated-card-theme' as mdc-elevated-card-theme;
69
@use '@material/card/outlined-card-theme' as mdc-outlined-card-theme;
7-
@use '@material/typography' as mdc-typography;
8-
@use '@material/theme/theme-color' as mdc-theme-color;
9-
@use 'sass:color';
10-
@use 'sass:map';
11-
@use 'sass:meta';
1210

1311
@mixin color($config-or-theme) {
1412
$config: theming.get-color-config($config-or-theme);
15-
$foreground: map.get($config, foreground);
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);
15+
$mat-card-color-tokens: tokens-mat-card.get-color-tokens($config);
1616

17-
@include mdc-helpers.using-mdc-theme($config) {
18-
$on-surface: mdc-theme-color.prop-value(on-surface);
19-
$surface: mdc-theme-color.prop-value(surface);
17+
// Add values for card tokens.
18+
.mat-mdc-card {
19+
@include mdc-elevated-card-theme.theme($mdc-elevated-card-color-tokens);
20+
@include mdc-outlined-card-theme.theme($mdc-outlined-card-color-tokens);
21+
@include token-utils.create-token-values(tokens-mat-card.$prefix, $mat-card-color-tokens);
2022

21-
.mat-mdc-card {
22-
// MDC's theme has `container-elevation` and `container-shadow-color` tokens, but we can't
23-
// use them because they output under a `.mdc-card` selector whereas the rest of the theme
24-
// isn't under any selector. Even if the mixin is pulled out of the selector, it throws a
25-
// different error.
26-
@include private.private-theme-elevation(1, $config);
27-
@include mdc-elevated-card-theme.theme((
28-
container-color: $surface,
29-
));
30-
}
31-
32-
.mat-mdc-card-outlined {
33-
@include private.private-theme-elevation(0, $config);
34-
@include mdc-outlined-card-theme.theme((
35-
outline-color: if(
36-
meta.type-of($on-surface) == color and meta.type-of($surface) == color,
37-
color.mix($on-surface, $surface, 12%),
38-
$on-surface
39-
)
40-
));
41-
}
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+
}
4227

43-
// Card subtitles are an Angular Material construct (not MDC), so we explicitly set their
44-
// color to secondary text here.
45-
.mat-mdc-card-subtitle {
46-
color: theming.get-color-from-palette($foreground, secondary-text);
47-
}
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);
4832
}
4933
}
5034

5135
@mixin typography($config-or-theme) {
5236
$config: typography.private-typography-to-2018-config(
53-
theming.get-typography-config($config-or-theme));
54-
@include mdc-helpers.using-mdc-typography($config) {
55-
// Card subtitles and titles are an Angular Material construct (not MDC), so we explicitly
56-
// set their typographic styles here.
57-
.mat-mdc-card-title {
58-
@include mdc-typography.typography(headline6);
59-
}
37+
theming.get-typography-config($config-or-theme));
38+
$mdc-elevated-card-typography-tokens: tokens-mdc-elevated-card.get-typography-tokens($config);
39+
$mdc-outlined-card-typography-tokens: tokens-mdc-outlined-card.get-typography-tokens($config);
40+
$mat-card-typography-tokens: tokens-mat-card.get-typography-tokens($config);
6041

61-
.mat-mdc-card-subtitle {
62-
@include mdc-typography.typography(subtitle2);
63-
}
42+
// Add values for card tokens.
43+
.mat-mdc-card {
44+
@include mdc-elevated-card-theme.theme($mdc-elevated-card-typography-tokens);
45+
@include mdc-outlined-card-theme.theme($mdc-outlined-card-typography-tokens);
46+
@include token-utils.create-token-values(tokens-mat-card.$prefix, $mat-card-typography-tokens);
6447
}
6548
}
6649

67-
@mixin density($config-or-theme) {}
50+
@mixin density($config-or-theme) {
51+
$density-scale: theming.get-density-config($config-or-theme);
52+
$mdc-elevated-card-density-tokens: tokens-mdc-elevated-card.get-density-tokens($density-scale);
53+
$mdc-outlined-card-density-tokens: tokens-mdc-outlined-card.get-density-tokens($density-scale);
54+
$mat-card-density-tokens: tokens-mat-card.get-density-tokens($density-scale);
55+
56+
// Add values for card tokens.
57+
.mat-mdc-card {
58+
@include mdc-elevated-card-theme.theme($mdc-elevated-card-density-tokens);
59+
@include mdc-outlined-card-theme.theme($mdc-outlined-card-density-tokens);
60+
@include token-utils.create-token-values(tokens-mat-card.$prefix, $mat-card-density-tokens);
61+
}
62+
}
6863

6964
@mixin theme($theme-or-color-config) {
7065
$theme: theming.private-legacy-get-theme($theme-or-color-config);

src/material/card/card.scss

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,65 @@
11
@use '@material/card' as mdc-card;
2-
@use '@material/card/variables' as mdc-card-variables;
32
@use '@material/card/elevated-card-theme' as mdc-elevated-card-theme;
43
@use '@material/card/outlined-card-theme' as mdc-outlined-card-theme;
5-
@use '../core/mdc-helpers/mdc-helpers';
4+
@use '@material/theme/custom-properties' as mdc-custom-properties;
5+
@use '../core/tokens/token-utils';
6+
@use '../core/tokens/m2/mat/card' as tokens-mat-card;
7+
@use '../core/tokens/m2/mdc/elevated-card' as tokens-mdc-elevated-card;
8+
@use '../core/tokens/m2/mdc/outlined-card' as tokens-mdc-outlined-card;
69

710
// TODO(jelbourn): move header and title-group styles to their own files.
11+
@include mdc-custom-properties.configure($emit-fallback-values: false, $emit-fallback-vars: false) {
12+
$mdc-elevated-card-token-slots: tokens-mdc-elevated-card.get-token-slots();
13+
$mdc-outlined-card-token-slots: tokens-mdc-outlined-card.get-token-slots();
14+
15+
// Add the MDC card static styles.
16+
@include mdc-card.static-styles();
17+
18+
.mat-mdc-card {
19+
// Add the official slots for the MDC elevated-card.
20+
@include mdc-elevated-card-theme.theme-styles($mdc-elevated-card-token-slots);
21+
22+
// Add default values for MDC card tokens that aren't outputted by the theming API.
23+
@include mdc-elevated-card-theme.theme(tokens-mdc-elevated-card.get-unthemable-tokens());
24+
@include mdc-outlined-card-theme.theme(tokens-mdc-outlined-card.get-unthemable-tokens());
25+
@include token-utils.create-token-values(
26+
tokens-mat-card.$prefix, tokens-mat-card.get-unthemable-tokens());
27+
}
28+
29+
.mat-mdc-card-outlined {
30+
// Add the official slots for the MDC outlined-card.
31+
@include mdc-outlined-card-theme.theme-styles($mdc-outlined-card-token-slots);
32+
}
33+
34+
// Add slots for custom Angular Material card tokens.
35+
@include token-utils.use-tokens(tokens-mat-card.$prefix, tokens-mat-card.get-token-slots()) {
36+
.mat-mdc-card-title {
37+
@include token-utils.create-token-slot(font-family, title-text-font);
38+
@include token-utils.create-token-slot(line-height, title-text-line-height);
39+
@include token-utils.create-token-slot(font-size, title-text-size);
40+
@include token-utils.create-token-slot(letter-spacing, title-text-tracking);
41+
@include token-utils.create-token-slot(font-weight, title-text-weight);
42+
}
43+
44+
.mat-mdc-card-subtitle {
45+
@include token-utils.create-token-slot(color, subtitle-text-color);
46+
@include token-utils.create-token-slot(font-family, subtitle-text-font);
47+
@include token-utils.create-token-slot(line-height, subtitle-text-line-height);
48+
@include token-utils.create-token-slot(font-size, subtitle-text-size);
49+
@include token-utils.create-token-slot(letter-spacing, subtitle-text-tracking);
50+
@include token-utils.create-token-slot(font-weight, subtitle-text-weight);
51+
}
52+
}
53+
}
854

955
// Size of the `mat-card-header` region custom to Angular Material.
1056
$mat-card-header-size: 40px !default;
1157

1258
// Default padding for text content within a card.
1359
$mat-card-default-padding: 16px !default;
1460

15-
@include mdc-helpers.disable-mdc-fallback-declarations {
16-
// Include all MDC card styles except for color and typography.
17-
@include mdc-card.static-styles($query: mdc-helpers.$mdc-base-styles-query);
18-
}
19-
2061
.mat-mdc-card {
2162
position: relative;
22-
23-
@include mdc-helpers.disable-mdc-fallback-declarations {
24-
@include mdc-elevated-card-theme.theme-styles((
25-
container-color: transparent,
26-
container-shape: mdc-card-variables.$shape-radius,
27-
));
28-
}
29-
}
30-
31-
.mat-mdc-card-outlined {
32-
@include mdc-helpers.disable-mdc-fallback-declarations {
33-
@include mdc-outlined-card-theme.theme-styles((
34-
outline-color: transparent,
35-
outline-width: 1px,
36-
));
37-
}
3863
}
3964

4065
// Title text and subtitles text within a card. MDC doesn't have pre-made title sections for cards.

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
@use 'sass:map';
22
@use '@material/theme/custom-properties' as mdc-custom-properties;
33
@use '@material/theme/theme' as mdc-theme;
4+
@use '@material/theme/keys' as mdc-keys;
45
@use '../mdc-helpers/mdc-helpers';
56
@use '../theming/palette';
67
@use '../theming/theming';
@@ -78,3 +79,18 @@ $_component-prefix: null;
7879
@include mdc-theme.property($property, $value);
7980
}
8081
}
82+
83+
@mixin create-token-values($prefix, $tokens) {
84+
@include _configure-token-prefix($prefix...) {
85+
@include mdc-keys.declare-custom-properties($tokens, $_component-prefix);
86+
}
87+
}
88+
89+
// Merges together a list of maps into a single map.
90+
@function merge-all($maps...) {
91+
$result: ();
92+
@each $map in $maps {
93+
$result: map.merge($result, $map);
94+
}
95+
@return $result;
96+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
@use 'sass:map';
2+
@use '../../token-utils';
3+
@use '../../../theming/theming';
4+
@use '../../../typography/typography-utils';
5+
6+
// The prefix used to generate the fully qualified name for tokens in this file.
7+
$prefix: (mat, card);
8+
9+
// Tokens that can't be configured through Angular Material's current theming API,
10+
// but may be in a future version of the theming API.
11+
@function get-unthemable-tokens() {
12+
@return ();
13+
}
14+
15+
// Tokens that can be configured through Angular Material's color theming API.
16+
@function get-color-tokens($config) {
17+
$foreground: map.get($config, foreground);
18+
19+
@return (
20+
// Text color of the card's subtitle.
21+
subtitle-text-color: theming.get-color-from-palette($foreground, secondary-text),
22+
);
23+
}
24+
25+
// Tokens that can be configured through Angular Material's typography theming API.
26+
@function get-typography-tokens($config) {
27+
@return (
28+
// Font family of the card's title.
29+
title-text-font: typography-utils.font-family($config, headline-6)
30+
or typography-utils.font-family($config),
31+
// Line height of the card's title.
32+
title-text-line-height: typography-utils.line-height($config, headline-6),
33+
// Font size of the card's title.
34+
title-text-size: typography-utils.font-size($config, headline-6),
35+
// Letter spacing of the card's title.
36+
title-text-tracking: typography-utils.letter-spacing($config, headline-6),
37+
// Font weight of the card's title.
38+
title-text-weight: typography-utils.font-weight($config, headline-6),
39+
// Font family of the card's subtitle.
40+
subtitle-text-font: typography-utils.font-family($config, subtitle-2)
41+
or typography-utils.font-family($config),
42+
// Line height of the card's subtitle.
43+
subtitle-text-line-height: typography-utils.line-height($config, subtitle-2),
44+
// Font size of the card's subtitle.
45+
subtitle-text-size: typography-utils.font-size($config, subtitle-2),
46+
// Letter spacing of the card's subtitle.
47+
subtitle-text-tracking: typography-utils.letter-spacing($config, subtitle-2),
48+
// Font weight of the card's subtitle.
49+
subtitle-text-weight: typography-utils.font-weight($config, subtitle-2),
50+
);
51+
}
52+
53+
// Tokens that can be configured through Angular Material's density theming API.
54+
@function get-density-tokens($config) {
55+
@return ();
56+
}
57+
58+
// Combines the tokens generated by the above functions into a single map with placeholder values.
59+
// This is used to create token slots.
60+
@function get-token-slots() {
61+
@return token-utils.merge-all(
62+
get-unthemable-tokens(),
63+
get-color-tokens(token-utils.$placeholder-color-config),
64+
get-typography-tokens(token-utils.$placeholder-typography-config),
65+
get-density-tokens(token-utils.$placeholder-density-config)
66+
);
67+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
@use 'sass:map';
2+
@use '../../../theming/theming';
3+
@use '../../token-utils';
4+
5+
// The prefix used to generate the fully qualified name for tokens in this file.
6+
$prefix: (mdc, elevated-card);
7+
8+
// Tokens that can't be configured through Angular Material's current theming API,
9+
// but may be in a future version of the theming API.
10+
//
11+
// Tokens that are available in MDC, but not used in Angular Material should be mapped to `null`.
12+
// `null` indicates that we are intentionally choosing not to emit a slot or value for the token in
13+
// our CSS.
14+
@function get-unthemable-tokens() {
15+
@return (
16+
// The border-radius of the card.
17+
container-shape: 4px,
18+
// =============================================================================================
19+
// = TOKENS NOT USED IN ANGULAR MATERIAL =
20+
// =============================================================================================
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,
25+
// 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,
41+
// Angular Material does not currently support surface tint.
42+
container-surface-tint-layer-color: null,
43+
// MDC does not seem to use these tokens.
44+
icon-color: null,
45+
icon-size: null,
46+
);
47+
}
48+
49+
// Tokens that can be configured through Angular Material's color theming API.
50+
@function get-color-tokens($config) {
51+
$background: map.get($config, background);
52+
53+
@return (
54+
// The background color of the card.
55+
container-color: theming.get-color-from-palette($background, card),
56+
);
57+
}
58+
59+
// Tokens that can be configured through Angular Material's typography theming API.
60+
@function get-typography-tokens($config) {
61+
@return ();
62+
}
63+
64+
// Tokens that can be configured through Angular Material's density theming API.
65+
@function get-density-tokens($config) {
66+
@return ();
67+
}
68+
69+
// Combines the tokens generated by the above functions into a single map with placeholder values.
70+
// This is used to create token slots.
71+
@function get-token-slots() {
72+
@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)
77+
);
78+
}

src/material/core/tokens/m2/mdc/_list.scss

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -207,14 +207,10 @@ $prefix: (mdc, list);
207207
// Combines the tokens generated by the above functions into a single map with placeholder values.
208208
// This is used to create token slots.
209209
@function get-token-slots() {
210-
@return map.merge(
210+
@return token-utils.merge-all(
211211
get-unthemable-tokens(),
212-
map.merge(
213-
get-color-tokens(token-utils.$placeholder-color-config),
214-
map.merge(
215-
get-typography-tokens(token-utils.$placeholder-typography-config),
216-
get-density-tokens(token-utils.$placeholder-density-config)
217-
)
218-
)
212+
get-color-tokens(token-utils.$placeholder-color-config),
213+
get-typography-tokens(token-utils.$placeholder-typography-config),
214+
get-density-tokens(token-utils.$placeholder-density-config)
219215
);
220216
}

0 commit comments

Comments
 (0)