Skip to content

Commit f47f5f9

Browse files
authored
feat(material/schematics): Add CSS output to custom theme schematic (#30004)
1 parent d6b3775 commit f47f5f9

File tree

5 files changed

+1723
-621
lines changed

5 files changed

+1723
-621
lines changed

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

Lines changed: 145 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,64 @@
33
```shell
44
ng generate @angular/material:theme-color
55
```
6-
6+
## Background
77
This schematic allows users to create new Material 3 theme palettes based
88
on custom colors by using [Material Color Utilities](https://github.com/material-foundation/material-color-utilities).
9+
This is an alternative to using the available [predefined theme palettes](https://material.angular.io/guide/theming#prebuilt-color-palettes).
910

1011
The generated [color palettes](https://m3.material.io/styles/color/roles) are
11-
optimized to have enough contrast to be more accessible. See [Science of Color Design](https://material.io/blog/science-of-color-design) for more information about Material's color design.
12+
optimized to have enough contrast to be more accessible. See [Science of Color Design](https://material.io/blog/science-of-color-design)
13+
for more information about Material's color design.
1214

1315
For more customization, custom colors can be also be provided for the
1416
secondary, tertiary, and neutral palette colors. It is recommended to choose colors that
15-
are contrastful, Material has more detailed guidance for [accessible design](https://m3.material.io/foundations/accessible-design/patterns).
17+
are contrastful. Material has more detailed guidance for [accessible design](https://m3.material.io/foundations/accessible-design/patterns).
18+
19+
## Options
20+
21+
### Required
22+
* `primaryColor` - Color to use for app's primary color palette (Note: the other
23+
palettes described in the Material 3 spec will be automatically chosen based on
24+
your primary palette unless specified, to ensure a harmonious color combination).
25+
26+
### Optional
27+
* `secondaryColor` - Color to use for app's secondary color palette. Defaults to
28+
secondary color generated from Material based on the primary.
29+
* `tertiaryColor` - Color to use for app's tertiary color palette. Defaults to
30+
tertiary color generated from Material based on the primary.
31+
* `neutralColor` - Color to use for app's neutral color palette. Defaults to
32+
neutral color generated from Material based on the primary.
33+
* `includeHighContrast` - Whether to define high contrast values for the custom colors in the
34+
generated file. For Sass files a mixin is defined, see the [high contrast override mixins section](#high-contrast-override-mixins)
35+
for more information. Defaults to false.
36+
* `directory` - Relative path to a directory within the project that the
37+
generated theme file should be created in. Defaults to the project root.
38+
* `isScss` - Whether to generate output file in Sass or CSS. Angular recommends generating a Sass
39+
file, see the [file output section](#generated-file-output) below for more information. Defaults to
40+
true.
41+
42+
## Generated file output
43+
The result of running the schematic is a new file with the generated custom colors.
44+
45+
Angular recommendeds generating a Sass file since our theming system Sass APIs are supported and
46+
have benefits such as error handling and relate to the [theming documentation](https://material.angular.io/guide/theming).
47+
If there are ever changes to the theming system or system variable names, your styles will continue
48+
to work and be supported. Color palettes get defined in the generated file that you can pass into
49+
the `theme()` mixin in your own theme file. See the [Sass themes section](#sass-themes) for more
50+
information.
1651

17-
The output of the schematic will create a file named `_theme-colors.scss` at the
18-
specified directory or the project root with the generated palettes. The exported
19-
palettes (`$primary-palette` and `$tertiary-palette`) can be provided to the `theme` mixin within your theme file to use the custom colors.
52+
You can generate a CSS file which defines all the system variables directly. This allows for
53+
applications that do not use Sass to still interact with our theming. See the [CSS themes section](#css-themes)
54+
for more specific information.
55+
56+
## Sass themes
57+
The output of the schematic will create a file named `_theme-colors.scss` at the specified directory
58+
or the project root. The exported palettes (`$primary-palette` and `$tertiary-palette`) can be
59+
provided to the `theme` mixin within your theme file to use the custom colors.
2060

2161
```scss
2262
@use '@angular/material' as mat;
23-
@use './path/to/my-theme'; // location of generated file
63+
@use './path/to/_theme-colors' as my-theme; // location of generated file
2464

2565
html {
2666
@include mat.theme(
@@ -34,104 +74,151 @@ html {
3474
}
3575
```
3676

37-
## High contrast override mixins
77+
### High contrast override mixins
3878
High contrast override theme mixins are also generated in the file if specified. These mixins
3979
override the system level variables with high contrast equivalent values from your theme. This is
4080
helpful for users who prefer more contrastful colors for either preference or accessibility reasons.
4181

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).
82+
To show the high contrast values when user's specify based on their color system preferences, apply
83+
the `high-contrast-overrides()` mixin from the generated file wrapped inside
84+
`@media (prefers-contrast: more)` in your theme file. You can pass in `light`, `dark`, or
85+
`color-scheme`. To see the high contrast values in your application locally, you can [use Chrome DevTools to emulate
86+
the CSS media features](https://developer.chrome.com/docs/devtools/rendering/emulate-css).
87+
88+
```
89+
@media (prefers-contrast: more) {
90+
@include my-theme.high-contrast-overrides(light);
91+
}
92+
```
93+
94+
#### Adaptive high contrast colors for explicit light and dark themes
95+
You can manually define the light theme and dark theme separately. This is recommended if you need
96+
granular control over when to show each specific theme in your application. Prior to v19, this was
97+
the only way to create light and dark themes.
4598

46-
Apply the `high-contrast-overrides(color-scheme)` mixin wrapped inside `@media (prefers-contrast: more)`.
99+
In this example, the colors would automatically change between dark and dark high contrast based on
100+
user's contrast preferences.
47101

48102
```scss
49103
@use '@angular/material';
50104
@use './path/to/my-theme'; // location of generated file
51105

52106
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
107+
// Apply the dark theme by default
57108
@include material.theme((
58109
color: (
59110
primary: my-theme.$primary-palette,
60111
tertiary: my-theme.$tertiary-palette,
112+
theme-type: dark,
61113
),
62114
typography: Roboto,
63115
density: 0,
64116
));
65117

66-
// Use high contrast values when users prefer contrast
118+
// Use high contrast dark theme colors when users prefer contrast
67119
@media (prefers-contrast: more) {
68-
@include my-theme.high-contrast-overrides(color-scheme);
120+
@include my-theme.high-contrast-overrides(dark);
69121
}
70122
}
71123
```
72124

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.
125+
#### Adaptive high contrast colors for adaptive themes
126+
The `theme()` mixin can create one theme that detects and adapts to a user if they have a
127+
light or dark theme by defining `color-scheme`. See the [color-scheme documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme)
128+
and the [theming guide](https://material.angular.io/guide/theming#supporting-light-and-dark-mode)
129+
for more information.
130+
131+
Apply the `high-contrast-overrides(color-scheme)` mixin wrapped inside `@media (prefers-contrast: more)`
132+
to apply the high contrast colors for the current color-scheme.
133+
134+
In this example, the colors would automatically change between light, light high contrast, dark, and
135+
dark high contrast based on user's preferences.
77136

78137
```scss
79138
@use '@angular/material';
80139
@use './path/to/my-theme'; // location of generated file
81140

82141
html {
83-
// Apply the light theme by default
142+
// Must specify color-scheme for theme mixin to automatically work
143+
color-scheme: light dark;
144+
145+
// Create one theme that works automatically for light and dark theme
84146
@include material.theme((
85147
color: (
86148
primary: my-theme.$primary-palette,
87149
tertiary: my-theme.$tertiary-palette,
88-
theme-type: light,
89150
),
90151
typography: Roboto,
91152
density: 0,
92153
));
93154

94-
// Use high contrast light theme colors when users prefer contrast
155+
// Use high contrast values when users prefer contrast
95156
@media (prefers-contrast: more) {
96-
@include my-theme.high-contrast-overrides(light);
157+
@include my-theme.high-contrast-overrides(color-scheme);
97158
}
159+
}
160+
```
98161

99-
// Apply dark theme when users prefer a dark color scheme
100-
@media (prefers-color-scheme: dark) {
101-
@include material.theme((
102-
color: (
103-
primary: my-theme.$primary-palette,
104-
tertiary: my-theme.$tertiary-palette,
105-
theme-type: dark,
106-
),
107-
));
108-
109-
// Use high contrast dark theme colors when users prefers a dark color scheme and contrast
110-
@media (prefers-contrast: more) {
111-
@include my-theme.high-contrast-overrides(dark);
112-
}
113-
}
162+
## CSS themes
163+
The output of the schematic will create a file named `theme.css` at the specified directory or the
164+
project root. The system variables are split up by color, typography,
165+
elevation, shape, and state variables.
166+
167+
These system variables are used throughout the different components, so changing these values will
168+
reflect across all the components. Some of the color system variables are related to other system
169+
variables, so make sure to change corresponding system variables as well.
170+
171+
### Light and dark themes
172+
Color system variables are defined using the CSS [light-dark()](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/light-dark)
173+
function.
174+
175+
The generated CSS file sets `color-scheme` to `light` so the colors will appear as a light
176+
theme by default. Changing the value of `color-scheme` to `dark` shows the dark version of your
177+
application.
178+
179+
To use the user's color scheme preferences automatically, set change the value of `color-scheme` to
180+
`light-dark`. See the [color-scheme documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme)
181+
for more information.
182+
183+
```css
184+
html {
185+
/* COLOR SYSTEM VARIABLES */
186+
color-scheme: light dark; /* Change to `light dark` to automatically toggle between light and dark themes. */
187+
188+
/* Primary palette variables */
189+
--mat-sys-primary: light-dark(#984061, #ffb0c8);
190+
--mat-sys-on-primary: light-dark(#ffffff, #5e1133);
191+
...
114192
}
115193
```
116194

117-
## Options
195+
To change the color preferences in your application locally, you can [use Chrome DevTools to emulate
196+
the CSS media features](https://developer.chrome.com/docs/devtools/rendering/emulate-css).
118197

119-
### Required
120198

121-
* `primaryColor` - Color to use for app's primary color palette (Note: the other
122-
palettes described in the Material 3 spec will be automatically chosen based on
123-
your primary palette unless specified, to ensure a harmonious color combination).
199+
### High contrast media query
200+
High contrast values are defined in the generated CSS file if specified. These color values are
201+
wrapped in a `@media (prefers-contrast: more)` so users only see the higher contrast version of the
202+
colors based on their system settings.
124203

125-
### Optional
204+
```css
205+
html {
206+
/* COLOR SYSTEM VARIABLES */
207+
color-scheme: light;
126208

127-
* `secondaryColor` - Color to use for app's secondary color palette. Defaults to
128-
secondary color generated from Material based on the primary.
129-
* `tertiaryColor` - Color to use for app's tertiary color palette. Defaults to
130-
tertiary color generated from Material based on the primary.
131-
* `neutralColor` - Color to use for app's neutral color palette. Defaults to
132-
neutral color generated from Material based on the primary.
133-
* `includeHighContrast` - Whether to add high contrast override mixins to generated
134-
theme file. Developers can call the mixin when they want to show a high contrast version of their
135-
theme. Defaults to false.
136-
* `directory` - Relative path to a directory within the project that the
137-
generated theme file should be created in. Defaults to the project root.
209+
/* Primary palette variables */
210+
--mat-sys-primary: light-dark(#984061, #ffb0c8);
211+
--mat-sys-on-primary: light-dark(#ffffff, #5e1133);
212+
...
213+
214+
@media (prefers-contrast: more) {
215+
/* Primary palette variables */
216+
--mat-sys-primary: light-dark(#580b2f, #ffebef);
217+
--mat-sys-on-primary: light-dark(#ffffff, #000000);
218+
...
219+
}
220+
}
221+
```
222+
223+
To see the high contrast values in your application locally, you can [use Chrome DevTools to emulate
224+
the CSS media features](https://developer.chrome.com/docs/devtools/rendering/emulate-css).

0 commit comments

Comments
 (0)