Skip to content

Commit de7c3db

Browse files
authored
refactor(material/table): switch to tokens API (#27192)
Reworks the Material table to use the new tokens API.
1 parent 18400e7 commit de7c3db

File tree

4 files changed

+227
-55
lines changed

4 files changed

+227
-55
lines changed

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,21 @@ $_component-prefix: null;
7171

7272
// Emits a slot for the given token, provided that it has a non-null value in the token map passed
7373
// to `use-tokens`.
74-
@mixin create-token-slot($property, $token) {
74+
@mixin create-token-slot($property, $token, $emit-fallback: false) {
7575
@if $_component-prefix == null or $_tokens == null {
7676
@error '`create-token-slot` must be used within `use-tokens`';
7777
}
7878
@if map.get($_tokens, $token) != null {
79-
$value: mdc-custom-properties.create('#{$_component-prefix}-#{$token}');
79+
$fallback: null;
80+
81+
@if ($emit-fallback == true) {
82+
$fallback: map.get($_tokens, $token);
83+
}
84+
@else if ($emit-fallback) {
85+
$fallback: $emit-fallback;
86+
}
87+
88+
$value: mdc-custom-properties.create('#{$_component-prefix}-#{$token}', $fallback: $fallback);
8089
@include mdc-theme.property($property, $value);
8190
}
8291
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
@use 'sass:map';
2+
@use '../../../theming/theming';
3+
@use '../../../typography/typography-utils';
4+
@use '../../token-utils';
5+
@use '../../../style/sass-utils';
6+
7+
// The prefix used to generate the fully qualified name for tokens in this file.
8+
$prefix: (mat, table);
9+
10+
// Tokens that can't be configured through Angular Material's current theming API,
11+
// but may be in a future version of the theming API.
12+
@function get-unthemable-tokens() {
13+
@return (
14+
row-item-outline-width: 1px,
15+
);
16+
}
17+
18+
// Tokens that can be configured through Angular Material's color theming API.
19+
@function get-color-tokens($config) {
20+
$foreground: map.get($config, foreground);
21+
$background: map.get($config, background);
22+
23+
@return (
24+
background-color: theming.get-color-from-palette($background, 'card'),
25+
26+
header-headline-color: theming.get-color-from-palette($foreground, text),
27+
row-item-label-text-color: theming.get-color-from-palette($foreground, text),
28+
row-item-outline-color: theming.get-color-from-palette($foreground, divider),
29+
);
30+
}
31+
32+
// Tokens that can be configured through Angular Material's typography theming API.
33+
@function get-typography-tokens($config) {
34+
$fallback-font: typography-utils.font-family($config);
35+
$cell-font-family: typography-utils.font-family($config, body-2) or $fallback-font;
36+
$cell-line-height: typography-utils.line-height($config, body-2);
37+
$cell-font-size: typography-utils.font-size($config, body-2);
38+
$cell-font-weight: typography-utils.font-weight($config, body-2);
39+
$cell-letter-spacing: typography-utils.letter-spacing($config, body-2);
40+
41+
@return (
42+
header-headline-font: typography-utils.font-family($config, subtitle-2) or $fallback-font,
43+
header-headline-line-height: typography-utils.line-height($config, subtitle-2),
44+
header-headline-size: typography-utils.font-size($config, subtitle-2),
45+
header-headline-weight: typography-utils.font-weight($config, subtitle-2),
46+
header-headline-tracking: typography-utils.letter-spacing($config, subtitle-2),
47+
48+
// Plain cells and footer cells have the same typography.
49+
row-item-label-text-font: $cell-font-family,
50+
row-item-label-text-line-height: $cell-line-height,
51+
row-item-label-text-size: $cell-font-size,
52+
row-item-label-text-weight: $cell-font-weight,
53+
row-item-label-text-tracking: $cell-letter-spacing,
54+
55+
footer-supporting-text-font: $cell-font-family,
56+
footer-supporting-text-line-height: $cell-line-height,
57+
footer-supporting-text-size: $cell-font-size,
58+
footer-supporting-text-weight: $cell-font-weight,
59+
footer-supporting-text-tracking: $cell-letter-spacing,
60+
);
61+
}
62+
63+
// Tokens that can be configured through Angular Material's density theming API.
64+
@function get-density-tokens($config) {
65+
$scale: theming.clamp-density($config, -4);
66+
$header-scale: (
67+
0: 56px,
68+
-1: 52px,
69+
-2: 48px,
70+
-3: 44px,
71+
-4: 40px
72+
);
73+
$cell-scale: (
74+
0: 52px,
75+
-1: 48px,
76+
-2: 44px,
77+
-3: 40px,
78+
-4: 36px
79+
);
80+
81+
@return (
82+
header-container-height: map.get($header-scale, $scale),
83+
footer-container-height: map.get($cell-scale, $scale),
84+
row-item-container-height: map.get($cell-scale, $scale),
85+
);
86+
}
87+
88+
// Combines the tokens generated by the above functions into a single map with placeholder values.
89+
// This is used to create token slots.
90+
@function get-token-slots() {
91+
@return sass-utils.deep-merge-all(
92+
get-unthemable-tokens(),
93+
get-color-tokens(token-utils.$placeholder-color-config),
94+
get-typography-tokens(token-utils.$placeholder-typography-config),
95+
get-density-tokens(token-utils.$placeholder-density-config)
96+
);
97+
}

src/material/table/_table-theme.scss

Lines changed: 24 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,44 @@
1-
@use 'sass:map';
2-
@use '@material/theme/theme-color' as mdc-theme-color;
3-
@use '@material/data-table/data-table' as mdc-data-table;
4-
@use '@material/data-table' as mdc-data-table-theme;
1+
@use '../core/tokens/m2/mat/table' as tokens-mat-table;
52
@use '../core/theming/theming';
6-
@use '../core/mdc-helpers/mdc-helpers';
73
@use '../core/typography/typography';
4+
@use '../core/tokens/token-utils';
85

9-
@mixin color($config-or-theme) {
10-
$config: theming.get-color-config($config-or-theme);
11-
// Save original values of MDC global variables. We need to save these so we can restore the
12-
// variables to their original values and prevent unintended side effects from using this mixin.
13-
$orig-selected-row-fill-color: mdc-data-table-theme.$selected-row-fill-color;
14-
$orig-divider-color: mdc-data-table-theme.$divider-color;
15-
$orig-row-hover-fill-color: mdc-data-table-theme.$row-hover-fill-color;
16-
$orig-header-row-text-color: mdc-data-table-theme.$header-row-text-color;
17-
$orig-row-text-color: mdc-data-table-theme.$row-text-color;
18-
$orig-stroke-color: mdc-data-table-theme.$stroke-color;
19-
20-
@include mdc-helpers.using-mdc-theme($config) {
21-
mdc-data-table-theme.$selected-row-fill-color: rgba(mdc-theme-color.prop-value(primary), 0.04);
22-
mdc-data-table-theme.$divider-color: rgba(mdc-theme-color.prop-value(on-surface), 0.12);
23-
mdc-data-table-theme.$row-hover-fill-color: rgba(mdc-theme-color.prop-value(on-surface), 0.04);
24-
mdc-data-table-theme.$header-row-text-color: rgba(mdc-theme-color.prop-value(on-surface), 0.87);
25-
mdc-data-table-theme.$row-text-color: rgba(mdc-theme-color.prop-value(on-surface), 0.87);
26-
mdc-data-table-theme.$stroke-color: rgba(mdc-theme-color.prop-value(on-surface), 0.12);
27-
28-
@include mdc-data-table.table-styles($query: mdc-helpers.$mdc-theme-styles-query);
6+
@mixin _output-tokens {
7+
@if (&) {
8+
@content;
9+
}
10+
@else {
11+
html {
12+
@content;
13+
}
2914
}
15+
}
3016

31-
// Restore original values of MDC global variables.
32-
mdc-data-table-theme.$selected-row-fill-color: $orig-selected-row-fill-color;
33-
mdc-data-table-theme.$divider-color: $orig-divider-color;
34-
mdc-data-table-theme.$row-hover-fill-color: $orig-row-hover-fill-color;
35-
mdc-data-table-theme.$header-row-text-color: $orig-header-row-text-color;
36-
mdc-data-table-theme.$row-text-color: $orig-row-text-color;
37-
mdc-data-table-theme.$stroke-color: $orig-stroke-color;
17+
@mixin color($config-or-theme) {
18+
$config: theming.get-color-config($config-or-theme);
3819

39-
.mat-mdc-table {
40-
$background: map.get($config, background);
41-
background: theming.get-color-from-palette($background, 'card');
20+
@include _output-tokens {
21+
@include token-utils.create-token-values(tokens-mat-table.$prefix,
22+
tokens-mat-table.get-color-tokens($config));
4223
}
4324
}
4425

4526
@mixin typography($config-or-theme) {
4627
$config: typography.private-typography-to-2018-config(
4728
theming.get-typography-config($config-or-theme));
48-
@include mdc-helpers.using-mdc-typography($config) {
49-
@include mdc-data-table.table-styles($query: mdc-helpers.$mdc-typography-styles-query);
29+
30+
@include _output-tokens {
31+
@include token-utils.create-token-values(tokens-mat-table.$prefix,
32+
tokens-mat-table.get-typography-tokens($config));
5033
}
5134
}
5235

5336
@mixin density($config-or-theme) {
5437
$density-scale: theming.get-density-config($config-or-theme);
55-
.mat-mdc-table {
56-
@include mdc-data-table-theme.density($density-scale,
57-
$query: mdc-helpers.$mdc-base-styles-query);
38+
39+
@include _output-tokens {
40+
@include token-utils.create-token-values(tokens-mat-table.$prefix,
41+
tokens-mat-table.get-density-tokens($density-scale));
5842
}
5943
}
6044

src/material/table/table.scss

Lines changed: 95 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,40 @@
11
@use '@material/data-table/data-table' as mdc-data-table;
2+
@use '@material/data-table/data-table-cell' as mdc-data-table-cell;
3+
@use '@material/data-table/data-table-header-cell' as mdc-data-table-header-cell;
4+
@use '@material/data-table' as mdc-data-table-theme;
5+
@use '@material/typography/typography' as mdc-typography;
26
@use '../core/mdc-helpers/mdc-helpers';
7+
@use '../core/tokens/token-utils';
8+
@use '../core/tokens/m2/mat/table' as tokens-mat-table;
39
@use './table-flex-styles';
410

5-
@include mdc-helpers.disable-mdc-fallback-declarations {
6-
@include mdc-data-table.table-styles(
7-
$query: mdc-helpers.$mdc-base-styles-without-animation-query);
8-
@include table-flex-styles.private-table-flex-styles();
9-
}
10-
1111
.mat-mdc-table-sticky {
1212
// Note that the table can either set this class or an inline style to make something sticky.
1313
// We set the style as `!important` so that we get an identical specificity in both cases
1414
// and to avoid cases where user styles have a higher specificity.
1515
position: sticky !important;
1616
}
1717

18+
@mixin _cell-border {
19+
@include token-utils.create-token-slot(border-bottom-color, row-item-outline-color, true);
20+
@include token-utils.create-token-slot(border-bottom-width, row-item-outline-width, true);
21+
border-bottom-style: solid;
22+
}
23+
24+
@include mdc-data-table.static-styles($query: mdc-helpers.$mdc-base-styles-query);
25+
@include mdc-data-table-cell.static-styles($query: mdc-helpers.$mdc-base-styles-query);
26+
@include mdc-data-table-header-cell.static-styles($query: mdc-helpers.$mdc-base-styles-query);
27+
@include mdc-data-table-theme.cell-padding(
28+
$leading-padding: mdc-data-table-theme.$cell-leading-padding,
29+
$trailing-padding: mdc-data-table-theme.$cell-trailing-padding,
30+
$query: mdc-helpers.$mdc-base-styles-query
31+
);
32+
@include table-flex-styles.private-table-flex-styles();
33+
1834
.mat-mdc-table {
35+
@include token-utils.create-token-values(
36+
tokens-mat-table.$prefix, tokens-mat-table.get-unthemable-tokens());
37+
1938
// MDC Table applies `table-layout: fixed`, but this is a backwards incompatible
2039
// change since the table did not previously apply it.
2140
// TODO: Add a mixin to MDC to set the layout instead of including this override,
@@ -25,6 +44,76 @@
2544
// The MDC table does not allow text to wrap within the cell. This allows for text to
2645
// wrap when the cell reaches its maximum width.
2746
white-space: normal;
47+
48+
@include token-utils.use-tokens(tokens-mat-table.$prefix, tokens-mat-table.get-token-slots()) {
49+
@include token-utils.create-token-slot(background-color, background-color);
50+
}
51+
}
52+
53+
@include mdc-helpers.disable-mdc-fallback-declarations {
54+
@include token-utils.use-tokens(tokens-mat-table.$prefix, tokens-mat-table.get-token-slots()) {
55+
// TODO(crisbeto): these tokens have default values in order to make the initial token
56+
// work easier to land in g3. Eventually we should remove them.
57+
.mat-mdc-header-row {
58+
@include mdc-typography.smooth-font();
59+
@include token-utils.create-token-slot(height, header-container-height, 56px);
60+
@include token-utils.create-token-slot(color, header-headline-color, true);
61+
@include token-utils.create-token-slot(font-family, header-headline-font, true);
62+
@include token-utils.create-token-slot(line-height, header-headline-line-height);
63+
@include token-utils.create-token-slot(font-size, header-headline-size, 14px);
64+
@include token-utils.create-token-slot(font-weight, header-headline-weight, 500);
65+
}
66+
67+
.mat-mdc-row {
68+
@include token-utils.create-token-slot(height, row-item-container-height, 52px);
69+
@include token-utils.create-token-slot(color, row-item-label-text-color, true);
70+
}
71+
72+
// Note that while it's redundant to apply the typography both to the row
73+
// and the content element since the cell inherit from both of them,
74+
// applying it only to one results in sub-pixel differences in the
75+
// letter spacing which leads to a lot of internal screenshot diffs.
76+
.mat-mdc-row,
77+
.mdc-data-table__content {
78+
@include mdc-typography.smooth-font();
79+
@include token-utils.create-token-slot(font-family, row-item-label-text-font, true);
80+
@include token-utils.create-token-slot(line-height, row-item-label-text-line-height);
81+
@include token-utils.create-token-slot(font-size, row-item-label-text-size, 14px);
82+
@include token-utils.create-token-slot(font-weight, row-item-label-text-weight);
83+
}
84+
85+
.mat-mdc-footer-row {
86+
@include mdc-typography.smooth-font();
87+
@include token-utils.create-token-slot(height, footer-container-height, 52px);
88+
@include token-utils.create-token-slot(color, row-item-label-text-color, true);
89+
@include token-utils.create-token-slot(font-family, footer-supporting-text-font, true);
90+
@include token-utils.create-token-slot(line-height, footer-supporting-text-line-height);
91+
@include token-utils.create-token-slot(font-size, footer-supporting-text-size, 14px);
92+
@include token-utils.create-token-slot(font-weight, footer-supporting-text-weight);
93+
@include token-utils.create-token-slot(letter-spacing, footer-supporting-text-tracking);
94+
}
95+
96+
.mat-mdc-header-cell {
97+
@include _cell-border;
98+
@include token-utils.create-token-slot(letter-spacing, header-headline-tracking);
99+
font-weight: inherit;
100+
line-height: inherit;
101+
}
102+
103+
.mat-mdc-cell {
104+
@include _cell-border;
105+
@include token-utils.create-token-slot(letter-spacing, row-item-label-text-tracking);
106+
line-height: inherit;
107+
108+
.mdc-data-table__row:last-child & {
109+
border-bottom: none;
110+
}
111+
}
112+
113+
.mat-mdc-footer-cell {
114+
@include token-utils.create-token-slot(letter-spacing, row-item-label-text-tracking);
115+
}
116+
}
28117
}
29118

30119
// MDC table rows are styled with a top border, whereas our legacy flex table styles rows with
@@ -43,13 +132,6 @@ mat-row.mat-mdc-row, mat-header-row.mat-mdc-header-row, mat-footer-row.mat-mdc-f
43132
background: inherit;
44133
}
45134

46-
// Disable hover styling while MDC uses an opacity for its color.
47-
// When the hover style is used with sticky cells, the opacity shows the cells overlapping.
48-
.mat-mdc-table .mat-mdc-row:hover,
49-
.mat-mdc-table .mat-mdc-footer-row:hover {
50-
background-color: inherit;
51-
}
52-
53135
// Flex rows should not set a definite height, but instead stretch to the height of their
54136
// children. Otherwise, the cells grow larger than the row and the layout breaks.
55137
.mat-mdc-table mat-header-row.mat-mdc-header-row,

0 commit comments

Comments
 (0)