Skip to content

Commit f7e3c62

Browse files
committed
feat(material/schematics): Update custom theme schematic to work with light-dark and use theme-overrides mixin
1 parent ea0d1ba commit f7e3c62

File tree

2 files changed

+89
-19
lines changed

2 files changed

+89
-19
lines changed

src/material/schematics/ng-generate/theme-color/README.md

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,47 @@ html {
3434
}
3535
```
3636

37-
High contrast override theme mixins are also generated in the file if specified
38-
(`high-contrast-light-theme-overrides` and `high-contrast-dark-theme-overrides`). These mixins
37+
## High contrast override mixins
38+
High contrast override theme mixins are also generated in the file if specified. These mixins
3939
override the system level variables with high contrast equivalent values from your theme. This is
4040
helpful for users who prefer more contrastful colors for either preference or accessibility reasons.
4141

42+
### Creating one theme for light and dark mode
43+
As of v19, the `theme` mixin can create one theme that detects and adapts to a user if they have
44+
light or dark theme with the [`light-dark` function](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/light-dark).
45+
46+
Apply the `high-contrast-overrides(color-scheme)` mixin wrapped inside `@media (prefers-contrast: more)`.
47+
48+
```scss
49+
@use '@angular/material';
50+
@use './path/to/my-theme'; // location of generated file
51+
52+
html {
53+
// Must specify color-scheme for theme mixin to automatically work
54+
color-scheme: light;
55+
56+
// Create one theme that works automatically for light and dark theme
57+
@include material.theme((
58+
color: (
59+
primary: my-theme.$primary-palette,
60+
tertiary: my-theme.$tertiary-palette,
61+
),
62+
typography: Roboto,
63+
density: 0,
64+
));
65+
66+
// Use high contrast values when users prefer contrast
67+
@media (prefers-contrast: more) {
68+
@include my-theme.high-contrast-overrides(color-scheme);
69+
}
70+
}
71+
```
72+
73+
### Creating separate themes for light and dark mode
74+
You can manually define the light theme and dark theme separately. This is recommended if you need
75+
granular control over when to show each specific theme in your application. Prior to v19, this was
76+
the only way to create light and dark themes.
77+
4278
```scss
4379
@use '@angular/material';
4480
@use './path/to/my-theme'; // location of generated file
@@ -49,14 +85,15 @@ html {
4985
color: (
5086
primary: my-theme.$primary-palette,
5187
tertiary: my-theme.$tertiary-palette,
88+
theme-type: light,
5289
),
5390
typography: Roboto,
5491
density: 0,
5592
));
5693

5794
// Use high contrast light theme colors when users prefer contrast
5895
@media (prefers-contrast: more) {
59-
@include my-theme.high-contrast-light-theme-overrides();
96+
@include my-theme.high-contrast-overrides(light);
6097
}
6198

6299
// Apply dark theme when users prefer a dark color scheme
@@ -71,7 +108,7 @@ html {
71108

72109
// Use high contrast dark theme colors when users prefers a dark color scheme and contrast
73110
@media (prefers-contrast: more) {
74-
@include my-theme.high-contrast-dark-theme-overrides();
111+
@include my-theme.high-contrast-overrides(dark);
75112
}
76113
}
77114
}

src/material/schematics/ng-generate/theme-color/index.ts

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,6 @@ function getHighContrastOverides(
236236
overrides.set('surface-dim', hexFromArgb(scheme.surfaceDim));
237237
overrides.set('surface-bright', hexFromArgb(scheme.surfaceBright));
238238
overrides.set('surface-container-lowest', hexFromArgb(scheme.surfaceContainerLowest));
239-
overrides.set('surface-container-lowest', hexFromArgb(scheme.surfaceContainerLow));
240239
overrides.set('surface-container', hexFromArgb(scheme.surfaceContainer));
241240
overrides.set('surface-container-high', hexFromArgb(scheme.surfaceContainerHigh));
242241
overrides.set('surface-container-highest', hexFromArgb(scheme.surfaceContainerHighest));
@@ -278,22 +277,56 @@ function generateHighContrastOverrideMixinsSCSS(
278277
neutralPalette: TonalPalette,
279278
neutralVariantPalette: TonalPalette,
280279
): string {
280+
const lightOverrides = getHighContrastOverides(
281+
primaryPalette,
282+
secondaryPalette,
283+
tertiaryPalette,
284+
neutralPalette,
285+
neutralVariantPalette,
286+
/** isDark **/ false,
287+
);
288+
289+
const darkOverrides = getHighContrastOverides(
290+
primaryPalette,
291+
secondaryPalette,
292+
tertiaryPalette,
293+
neutralPalette,
294+
neutralVariantPalette,
295+
/** isDark **/ true,
296+
);
297+
298+
// Create private function to grab correct values based on theme-type
281299
let scss = '\n';
282-
for (const themeType of ['light', 'dark']) {
283-
const overrides = getHighContrastOverides(
284-
primaryPalette,
285-
secondaryPalette,
286-
tertiaryPalette,
287-
neutralPalette,
288-
neutralVariantPalette,
289-
themeType === 'dark',
290-
);
291-
scss += '\n@mixin high-contrast-' + themeType + '-theme-overrides {\n';
292-
for (const [key, value] of overrides!.entries()) {
293-
scss += ' --mat-sys-' + key + ': ' + value + ';\n';
294-
}
295-
scss += '};\n';
300+
scss += '\n@function _high-contrast-value($light, $dark, $theme-type) {\n';
301+
scss += ' @if ($theme-type == light) {\n';
302+
scss += ' @return $light;\n';
303+
scss += ' }\n';
304+
scss += ' @if ($theme-type == dark) {\n';
305+
scss += ' @return $dark;\n';
306+
scss += ' }\n';
307+
scss += ' @if ($theme-type == color-scheme) {\n';
308+
scss += ' @return light-dark(#{$light}, #{$dark});\n';
309+
scss += ' }\n';
310+
scss +=
311+
" \n@error 'Unknown theme-type #{$theme-type}. Expected light, dark, or color-scheme';\n";
312+
scss += '}\n';
313+
314+
// Create high contrast mixin with theme-type input that can be light, dark, or color-scheme.
315+
scss += '\n@mixin high-contrast-overrides($theme-type) {\n';
316+
scss += ' @include mat.theme-overrides((\n';
317+
for (const [key, value] of lightOverrides!.entries()) {
318+
scss +=
319+
' ' +
320+
key +
321+
': _high-contrast-value(' +
322+
value +
323+
', ' +
324+
darkOverrides.get(key) +
325+
', $theme-type),\n';
296326
}
327+
scss += ' ))\n';
328+
scss += ' }\n';
329+
297330
return scss;
298331
}
299332

0 commit comments

Comments
 (0)