Skip to content

Commit d098bd2

Browse files
authored
refactor(material/sidenav): switch to tokens API (#27468)
Reworks the sidenav to use the new tokens theming API.
1 parent 8b06180 commit d098bd2

File tree

3 files changed

+156
-75
lines changed

3 files changed

+156
-75
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
@use 'sass:color';
2+
@use 'sass:map';
3+
@use 'sass:meta';
4+
@use '../../token-utils';
5+
@use '../../../theming/theming';
6+
@use '../../../style/sass-utils';
7+
8+
// The prefix used to generate the fully qualified name for tokens in this file.
9+
$prefix: (mat, sidenav);
10+
11+
// Tokens that can't be configured through Angular Material's current theming API,
12+
// but may be in a future version of the theming API.
13+
@function get-unthemable-tokens() {
14+
@return (
15+
// Currently zero, but it appears to be relevant for M3.
16+
// See: https://m3.material.io/components/navigation-drawer/overview
17+
container-shape: 0,
18+
);
19+
}
20+
21+
// Tokens that can be configured through Angular Material's color theming API.
22+
@function get-color-tokens($config) {
23+
$is-dark: map.get($config, is-dark);
24+
$foreground: map.get($config, foreground);
25+
$background: map.get($config, background);
26+
$scrim-opacity: 0.6;
27+
$scrim-color: theming.get-color-from-palette($background, card, $scrim-opacity);
28+
$fallback-scrim-color: if($is-dark, rgba(#fff, $scrim-opacity), rgba(#000, $scrim-opacity));
29+
30+
@return (
31+
container-divider-color: theming.get-color-from-palette($foreground, divider),
32+
container-background-color: theming.get-color-from-palette($background, dialog),
33+
container-text-color: theming.get-color-from-palette($foreground, text),
34+
content-background-color: theming.get-color-from-palette($background, background),
35+
content-text-color: theming.get-color-from-palette($foreground, text),
36+
37+
// We use invert() here to have the darken the background color expected to be used.
38+
// If the background is light, we use a dark backdrop. If the background is dark, we
39+
// use a light backdrop. If the value isn't a color, Sass will throw an error so we
40+
// fall back to something generic.
41+
scrim-color: if(meta.type-of($scrim-color) == color,
42+
color.invert($scrim-color), $fallback-scrim-color),
43+
);
44+
}
45+
46+
// Tokens that can be configured through Angular Material's typography theming API.
47+
@function get-typography-tokens($config) {
48+
@return ();
49+
}
50+
51+
// Tokens that can be configured through Angular Material's density theming API.
52+
@function get-density-tokens($config) {
53+
@return ();
54+
}
55+
56+
// Combines the tokens generated by the above functions into a single map with placeholder values.
57+
// This is used to create token slots.
58+
@function get-token-slots() {
59+
@return sass-utils.deep-merge-all(
60+
get-unthemable-tokens(),
61+
get-color-tokens(token-utils.$placeholder-color-config),
62+
get-typography-tokens(token-utils.$placeholder-typography-config),
63+
get-density-tokens(token-utils.$placeholder-density-config)
64+
);
65+
}

src/material/sidenav/_sidenav-theme.scss

Lines changed: 6 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,14 @@
1-
@use 'sass:color';
2-
@use 'sass:map';
3-
@use 'sass:meta';
4-
@use '../core/style/private';
51
@use '../core/theming/theming';
2+
@use '../core/tokens/m2/mat/sidenav' as tokens-mat-sidenav;
3+
@use '../core/tokens/token-utils';
4+
@use '../core/style/sass-utils';
65

76
@mixin color($config-or-theme) {
87
$config: theming.get-color-config($config-or-theme);
9-
$primary: map.get($config, primary);
10-
$accent: map.get($config, accent);
11-
$warn: map.get($config, warn);
12-
$background: map.get($config, background);
13-
$foreground: map.get($config, foreground);
148

15-
$drawer-background-color: theming.get-color-from-palette($background, dialog);
16-
$drawer-container-background-color: theming.get-color-from-palette($background, background);
17-
$drawer-push-background-color: theming.get-color-from-palette($background, dialog);
18-
$drawer-side-border: solid 1px theming.get-color-from-palette($foreground, divider);
19-
20-
.mat-drawer-container {
21-
background-color: $drawer-container-background-color;
22-
color: theming.get-color-from-palette($foreground, text);
23-
}
24-
25-
.mat-drawer {
26-
background-color: $drawer-background-color;
27-
color: theming.get-color-from-palette($foreground, text);
28-
29-
&.mat-drawer-push {
30-
background-color: $drawer-push-background-color;
31-
}
32-
33-
&:not(.mat-drawer-side) {
34-
// The elevation of z-16 is noted in the design specifications.
35-
// See https://material.io/design/components/navigation-drawer.html
36-
@include private.private-theme-elevation(16, $config);
37-
}
38-
}
39-
40-
.mat-drawer-side {
41-
border-right: $drawer-side-border;
42-
43-
&.mat-drawer-end {
44-
border-left: $drawer-side-border;
45-
border-right: none;
46-
}
47-
}
48-
49-
[dir='rtl'] .mat-drawer-side {
50-
border-left: $drawer-side-border;
51-
border-right: none;
52-
53-
&.mat-drawer-end {
54-
border-left: none;
55-
border-right: $drawer-side-border;
56-
}
57-
}
58-
59-
.mat-drawer-backdrop.mat-drawer-shown {
60-
$opacity: 0.6;
61-
$backdrop-color: theming.get-color-from-palette($background, card, $opacity);
62-
63-
@if (meta.type-of($backdrop-color) == color) {
64-
// We use invert() here to have the darken the background color expected to be used. If the
65-
// background is light, we use a dark backdrop. If the background is dark,
66-
// we use a light backdrop.
67-
background-color: color.invert($backdrop-color);
68-
}
69-
@else {
70-
// If we couldn't resolve the backdrop color to a color value, fall back to using
71-
// `opacity` to make it opaque since its end value could be a solid color.
72-
background-color: $backdrop-color;
73-
opacity: $opacity;
74-
}
9+
@include sass-utils.current-selector-or-root() {
10+
@include token-utils.create-token-values(tokens-mat-sidenav.$prefix,
11+
tokens-mat-sidenav.get-color-tokens($config));
7512
}
7613
}
7714

src/material/sidenav/drawer.scss

Lines changed: 85 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
@use '@angular/cdk';
22

3+
@use '../core/tokens/m2/mat/sidenav' as tokens-mat-sidenav;
4+
@use '../core/tokens/token-utils';
35
@use '../core/style/variables';
46
@use '../core/style/layout-common';
7+
@use '../core/style/elevation';
58

69
$drawer-content-z-index: 1;
710
$drawer-side-drawer-z-index: 2;
@@ -25,6 +28,12 @@ $drawer-over-drawer-z-index: 4;
2528
// the application content does not get messed up with our own CSS.
2629
@include drawer-stacking-context();
2730

31+
@include token-utils.use-tokens(
32+
tokens-mat-sidenav.$prefix, tokens-mat-sidenav.get-token-slots()) {
33+
@include token-utils.create-token-slot(color, content-text-color);
34+
@include token-utils.create-token-slot(background-color, content-background-color);
35+
}
36+
2837
box-sizing: border-box;
2938
-webkit-overflow-scrolling: touch;
3039

@@ -74,6 +83,11 @@ $drawer-over-drawer-z-index: 4;
7483

7584
&.mat-drawer-shown {
7685
visibility: visible;
86+
87+
@include token-utils.use-tokens(
88+
tokens-mat-sidenav.$prefix, tokens-mat-sidenav.get-token-slots()) {
89+
@include token-utils.create-token-slot(background-color, scrim-color);
90+
}
7791
}
7892

7993
.mat-drawer-transition & {
@@ -108,7 +122,20 @@ $drawer-over-drawer-z-index: 4;
108122
.mat-drawer {
109123
$high-contrast-border: solid 1px currentColor;
110124

125+
// The elevation of z-16 is noted in the design specifications.
126+
// See https://material.io/design/components/navigation-drawer.html
127+
@include elevation.elevation(16);
111128
@include drawer-stacking-context($drawer-over-drawer-z-index);
129+
@include token-utils.create-token-values(
130+
tokens-mat-sidenav.$prefix, tokens-mat-sidenav.get-unthemable-tokens());
131+
132+
@include token-utils.use-tokens(
133+
tokens-mat-sidenav.$prefix, tokens-mat-sidenav.get-token-slots()) {
134+
@include token-utils.create-token-slot(color, container-text-color);
135+
@include token-utils.create-token-slot(background-color, container-background-color);
136+
@include token-utils.create-token-slot(border-top-right-radius, container-shape);
137+
@include token-utils.create-token-slot(border-bottom-right-radius, container-shape);
138+
}
112139

113140
display: block;
114141
position: absolute;
@@ -120,6 +147,7 @@ $drawer-over-drawer-z-index: 4;
120147
overflow-y: auto; // TODO(kara): revisit scrolling behavior for drawers
121148
transform: translate3d(-100%, 0, 0);
122149

150+
123151
&, [dir='rtl'] &.mat-drawer-end {
124152
@include cdk.high-contrast(active, off) {
125153
border-right: $high-contrast-border;
@@ -140,15 +168,34 @@ $drawer-over-drawer-z-index: 4;
140168
&.mat-drawer-end {
141169
right: 0;
142170
transform: translate3d(100%, 0, 0);
171+
172+
@include token-utils.use-tokens(
173+
tokens-mat-sidenav.$prefix, tokens-mat-sidenav.get-token-slots()) {
174+
@include token-utils.create-token-slot(border-top-left-radius, container-shape);
175+
@include token-utils.create-token-slot(border-bottom-left-radius, container-shape);
176+
border-top-right-radius: 0;
177+
border-bottom-right-radius: 0;
178+
}
143179
}
144180

145181
[dir='rtl'] & {
146-
transform: translate3d(100%, 0, 0);
147-
148-
&.mat-drawer-end {
149-
left: 0;
150-
right: auto;
151-
transform: translate3d(-100%, 0, 0);
182+
@include token-utils.use-tokens(
183+
tokens-mat-sidenav.$prefix, tokens-mat-sidenav.get-token-slots()) {
184+
@include token-utils.create-token-slot(border-top-left-radius, container-shape);
185+
@include token-utils.create-token-slot(border-bottom-left-radius, container-shape);
186+
border-top-right-radius: 0;
187+
border-bottom-right-radius: 0;
188+
transform: translate3d(100%, 0, 0);
189+
190+
&.mat-drawer-end {
191+
@include token-utils.create-token-slot(border-top-right-radius, container-shape);
192+
@include token-utils.create-token-slot(border-bottom-right-radius, container-shape);
193+
border-top-left-radius: 0;
194+
border-bottom-left-radius: 0;
195+
left: 0;
196+
right: auto;
197+
transform: translate3d(-100%, 0, 0);
198+
}
152199
}
153200
}
154201

@@ -164,6 +211,38 @@ $drawer-over-drawer-z-index: 4;
164211
}
165212
}
166213

214+
.mat-drawer-side {
215+
box-shadow: none;
216+
217+
@include token-utils.use-tokens(
218+
tokens-mat-sidenav.$prefix, tokens-mat-sidenav.get-token-slots()) {
219+
@include token-utils.create-token-slot(border-right-color, container-divider-color);
220+
border-right-width: 1px;
221+
border-right-style: solid;
222+
223+
&.mat-drawer-end {
224+
@include token-utils.create-token-slot(border-left-color, container-divider-color);
225+
border-left-width: 1px;
226+
border-left-style: solid;
227+
border-right: none;
228+
}
229+
230+
[dir='rtl'] & {
231+
@include token-utils.create-token-slot(border-left-color, container-divider-color);
232+
border-left-width: 1px;
233+
border-left-style: solid;
234+
border-right: none; // Clears the default LTR border.
235+
236+
&.mat-drawer-end {
237+
@include token-utils.create-token-slot(border-right-color, container-divider-color);
238+
border-right-width: 1px;
239+
border-right-style: solid;
240+
border-left: none;
241+
}
242+
}
243+
}
244+
}
245+
167246
// Note that this div isn't strictly necessary on all browsers, however we need it in
168247
// order to avoid a layout issue in Chrome. The issue is that in RTL mode the browser doesn't
169248
// account for the sidenav's scrollbar while positioning, which ends up pushing it partially

0 commit comments

Comments
 (0)