Skip to content

Commit 3be8f7e

Browse files
authored
docs: Update theming your components guide for M3 and move M2 specific info (#29067)
1 parent c0841f1 commit 3be8f7e

File tree

3 files changed

+385
-208
lines changed

3 files changed

+385
-208
lines changed

guides/material-2.md

Lines changed: 314 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -410,13 +410,6 @@ The example below shows how to customize the color of all buttons inside element
410410
}
411411
```
412412

413-
### Reading hues from palettes
414-
415-
It is possible to read colors from a theme for use in your own components. For more information
416-
about this see our guide on [Theming your own components][reading-colors].
417-
418-
[reading-colors]: https://material.angular.io/guide/theming-your-components#reading-color-values
419-
420413
## Customizing density
421414

422415
Angular Material's density customization is based on the
@@ -556,6 +549,320 @@ Angular strongly discourages, and does not directly support, overriding componen
556549
theming APIs described above. Component DOM structure and CSS classes are considered private
557550
implementation details that may change at any time.
558551

552+
## Theming your components
553+
554+
### Reading values from a theme
555+
556+
As described in this guide, a theme is a Sass map that contains style values to
557+
customize components. Angular Material provides APIs for reading values from this data structure.
558+
559+
#### Reading color values
560+
561+
To read color values from a theme, you can use the `get-theme-color` Sass function. This function
562+
supports reading colors for both the app color palettes (primary, accent, and warn), as well as the
563+
foreground and background palettes. `get-theme-color` takes three arguments: The theme to read from,
564+
the name of the palette, and the name of the color.
565+
566+
Each of the color palettes (primary, accent, and warn) supports reading the following named colors:
567+
568+
| Color Name | Description |
569+
|------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|
570+
| default | The default color from this palette |
571+
| lighter | A lighter version of the color for this palette |
572+
| darker | A darker version of the color for this palette |
573+
| text | The text color for this palette |
574+
| default-contrast | A color that stands out against the this palette's default color |
575+
| lighter-contrast | A color that stands out against the this palette's lighter color |
576+
| darker-contrast | A color that stands out against the this palette's darker color |
577+
| [hue] | The [hue] color for the palette.<br />[hue] can be one of: 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, A100, A200, A400, A700 |
578+
| [hue]-contrast | A color that stands out against the [hue] color for the palette.<br />[hue] can be one of: 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, A100, A200, A400, A700 |
579+
580+
The background palette supports reading the following named colors:
581+
582+
| Color Name | Description |
583+
|--------------------------|----------------------------------------------------|
584+
| status-bar | The background color for a status bar |
585+
| app-bar | The background color for an app bar |
586+
| background | The background color for the app |
587+
| hover | The background color of a hover overlay |
588+
| card | The background color of a card |
589+
| dialog | The background color of a dialog |
590+
| raised-button | The background color of a raised button |
591+
| selected-button | The background color of a selected button |
592+
| selected-disabled-button | The background color of a selected disabled button |
593+
| disabled-button | The background color of a disabled button |
594+
| focused-button | The background color of a focused button |
595+
| disabled-button-toggle | The background color of a disabled button toggle |
596+
| unselected-chip | The background color of an unselected chip |
597+
| disabled-list-option | The background color of a disabled list option |
598+
| tooltip | The background color of a tooltip |
599+
600+
The foreground palette supports reading the following named colors:
601+
602+
| Color name | Description |
603+
|-------------------|----------------------------------------------------------------------------------------------------------|
604+
| base | The base foreground color, can be used to for color mixing or creating a custom opacity foreground color |
605+
| divider | The color of a divider |
606+
| dividers | (Alternate name for divider) |
607+
| disabled-text | The color for disabled text |
608+
| disabled | (Alternate name for disabled-text) |
609+
| disabled-button | The color for disabled button text |
610+
| elevation | The color elevation shadows |
611+
| hint-text | The color for hint text |
612+
| secondary-text | The color for secondary text |
613+
| icon | The color for icons |
614+
| icons | (Alternate name for icon) |
615+
| text | The color for text | |
616+
617+
In addition to reading particular colors, you can use the `get-theme-type` Sass function to
618+
determine the type of theme (either light or dark). This function takes a single argument, the
619+
theme, and returns either `light` or `dark`.
620+
621+
See the below example of reading some colors from a theme:
622+
623+
```scss
624+
$theme: mat.m2-define-dark-theme(...);
625+
626+
$primary-default: mat.get-theme-color($theme, primary, default);
627+
$accent-a100: mat.get-theme-color($theme, accent, A100);
628+
$warn-500-contrast: mat.get-theme-color($theme, warn, 500-contrast);
629+
$foreground-text: mat.get-theme-color($theme, foreground, text);
630+
$background-card: mat.get-theme-color($theme, background, card);
631+
$type: mat.get-theme-type($theme);
632+
$custom-background: if($type == dark, #030, #dfd);
633+
```
634+
635+
#### Reading typography values
636+
637+
To read typography values from a theme, you can use the `get-theme-typography` Sass function. This
638+
function supports reading typography properties from the typography levels defined in the theme.
639+
There are two ways to call the function.
640+
641+
The first way to call it is by passing just the theme and the typography level to get a shorthand
642+
`font` property based on the settings for that level. (Note: `letter-spacing` cannot be expressed in
643+
the `font` shorthand, so it must be applied separately).
644+
645+
The second way to call it is by passing the theme, typography level, and the specific font property
646+
you want: `font-family`, `font-size`, `font-weight`, `line-height`, or `letter-spacing`.
647+
648+
The available typography levels are:
649+
650+
| Name | Description |
651+
|------------|----------------------------------------------------------------------|
652+
| headline-1 | One-off header, usually at the top of the page (e.g. a hero header). |
653+
| headline-2 | One-off header, usually at the top of the page (e.g. a hero header). |
654+
| headline-3 | One-off header, usually at the top of the page (e.g. a hero header). |
655+
| headline-4 | One-off header, usually at the top of the page (e.g. a hero header). |
656+
| headline-5 | Section heading corresponding to the `<h1>` tag. |
657+
| headline-6 | Section heading corresponding to the `<h2>` tag. |
658+
| subtitle-1 | Section heading corresponding to the `<h3>` tag. |
659+
| subtitle-2 | Section heading corresponding to the `<h4>` tag. |
660+
| body-1 | Base body text. |
661+
| body-2 | Secondary body text. |
662+
| caption | Smaller body and hint text. |
663+
| button | Buttons and anchors. |
664+
665+
See the below example of reading some typography settings from a theme:
666+
667+
```scss
668+
$theme: mat.m2-define-dark-theme(...);
669+
670+
body {
671+
font: mat.get-theme-typography($theme, body-1);
672+
letter-spacing: mat.get-theme-typography($theme, body-1, letter-spacing);
673+
}
674+
```
675+
676+
#### Reading density values
677+
678+
To read the density scale from a theme, you can use the `get-theme-density` Sass function. This
679+
function takes a theme and returns the density scale (0, -1, -2, -3, -4, or -5).
680+
681+
See the below example of reading the density scale from a theme:
682+
683+
```scss
684+
$theme: mat.m2-define-dark-theme(...);
685+
686+
$density-scale: mat.get-theme-density($theme);
687+
```
688+
689+
### Checking what dimensions are configured for a theme
690+
691+
Depending on how a theme was created, it may not have configuration data for all theming dimensions
692+
(base, color, typography, density). You can check if a theme has a configuration for a particular
693+
dimension by calling the `theme-has` Sass function, passing the theme and the dimension to check.
694+
695+
See the below example of checking the configured dimensions for a theme:
696+
697+
```scss
698+
$theme: mat.m2-define-dark-theme(...);
699+
700+
$has-base: mat.theme-has($theme, base);
701+
$has-color: mat.theme-has($theme, color);
702+
$has-typography: mat.theme-has($theme, typography);
703+
$has-density: mat.theme-has($theme, density);
704+
```
705+
706+
### Separating theme styles
707+
708+
Angular Material components each have a Sass file that defines mixins for customizing
709+
that component's color and typography. For example, `MatButton` has mixins for `button-color` and
710+
`button-typography`. Each mixin emits all color and typography styles for that component,
711+
respectively.
712+
713+
You can mirror this structure in your components by defining your own mixins. These mixins
714+
should accept an Angular Material theme, from which they can read color and typography values. You
715+
can then include these mixins in your application along with Angular Material's own mixins.
716+
717+
### Step-by-step example
718+
719+
To illustrate participation in Angular Material's theming system, we can look at an example of a
720+
custom carousel component. The carousel starts with a single file, `carousel.scss`, that contains
721+
structural, color, and typography styles. This file is included in the `styleUrls` of the component.
722+
723+
```scss
724+
// carousel.scss
725+
726+
.my-carousel {
727+
display: flex;
728+
font-family: serif;
729+
}
730+
731+
.my-carousel-button {
732+
border-radius: 50%;
733+
color: blue;
734+
}
735+
```
736+
737+
#### Step 1: Extract theme-based styles to a separate file
738+
739+
To change this file to participate in Angular Material's theming system, we split the styles into
740+
two files, with the color and typography styles moved into mixins. By convention, the new file
741+
name ends with `-theme`. Additionally, the file starts with an underscore (`_`), indicating that
742+
this is a Sass partial file. See the [Sass documentation][sass-partials] for more information about
743+
partial files.
744+
745+
[sass-partials]: https://sass-lang.com/guide#topic-4
746+
747+
```scss
748+
// carousel.scss
749+
750+
.my-carousel {
751+
display: flex;
752+
}
753+
754+
.my-carousel-button {
755+
border-radius: 50%;
756+
}
757+
```
758+
759+
```scss
760+
// _carousel-theme.scss
761+
762+
@mixin color($theme) {
763+
.my-carousel-button {
764+
color: blue;
765+
}
766+
}
767+
768+
@mixin typography($theme) {
769+
.my-carousel {
770+
font-family: serif;
771+
}
772+
}
773+
```
774+
775+
#### Step 2: Use values from the theme
776+
777+
Now that theme theme-based styles reside in mixins, we can extract the values we need from the
778+
theme passed into the mixins.
779+
780+
```scss
781+
// _carousel-theme.scss
782+
783+
@use 'sass:map';
784+
@use '@angular/material' as mat;
785+
786+
@mixin color($theme) {
787+
.my-carousel-button {
788+
// Read the 500 hue from the primary color palette.
789+
color: mat.get-theme-color($theme, primary, 500);
790+
}
791+
}
792+
793+
@mixin typography($theme) {
794+
.my-carousel {
795+
// Get the headline font from the theme.
796+
font: mat.get-theme-typography($theme, headline-1);
797+
}
798+
}
799+
```
800+
801+
#### Step 3: Add a theme mixin
802+
803+
For convenience, we can add a `theme` mixin that includes both color and typography.
804+
This theme mixin should only emit the styles for each color and typography, respectively, if they
805+
have a config specified.
806+
807+
```scss
808+
// _carousel-theme.scss
809+
810+
@use 'sass:map';
811+
@use '@angular/material' as mat;
812+
813+
@mixin color($theme) {
814+
.my-carousel-button {
815+
// Read the 500 hue from the primary color palette.
816+
color: mat.get-theme-color($theme, primary, 500);
817+
}
818+
}
819+
820+
@mixin typography($theme) {
821+
.my-carousel {
822+
// Get the headline font from the theme.
823+
font: mat.get-theme-typography($theme, headline-1);
824+
}
825+
}
826+
827+
@mixin theme($theme) {
828+
@if mat.theme-has($theme, color) {
829+
@include color($theme);
830+
}
831+
832+
@if mat.theme-has($theme, typography) {
833+
@include typography($theme);
834+
}
835+
}
836+
```
837+
838+
#### Step 4: Include the theme mixin in your application
839+
840+
Now that you've defined the carousel component's theme mixin, you can include this mixin along with
841+
the other theme mixins in your application.
842+
843+
```scss
844+
@use '@angular/material' as mat;
845+
@use './path/to/carousel-theme' as carousel;
846+
847+
@include mat.core();
848+
849+
$my-primary: mat.m2-define-palette(mat.$m2-indigo-palette, 500);
850+
$my-accent: mat.m2-define-palette(mat.$m2-pink-palette, A200, A100, A400);
851+
852+
$my-theme: mat.m2-define-light-theme((
853+
color: (
854+
primary: $my-primary,
855+
accent: $my-accent,
856+
),
857+
typography: mat.m2-define-typography-config(
858+
$font-family: serif,
859+
),
860+
));
861+
862+
@include mat.all-component-themes($my-theme);
863+
@include carousel.theme($my-theme);
864+
```
865+
559866
## How to migrate an app from Material 2 to Material 3
560867

561868
Angular Material does not offer an automated migration from M2 to M3 because the design of your app

0 commit comments

Comments
 (0)