How to set background palette in custom theme of Angular Material?
Asked Answered
P

4

6

I currently define a custom theme finishing with something like:

$my-material-theme: mat.define-light-theme((
    color: (
      primary: $my-material-primary,
      accent: $my-material-accent,
      warn: $my-material-warn,
    ),
    typography: $my-material-font
));


@include mat.all-component-themes($my-material-theme);

All works properly. Still I noticed that some components were using a background-color different from what I used on the application and after some research, though that the following would further customise the theme:

$my-material-theme: mat.define-light-theme((
    color: (
      primary: $my-material-primary,
      accent: $my-material-accent,
      warn: $my-material-warn,
      background: $my-material-background
    ),
    typography: $my-material-font
));


@include mat.all-component-themes($my-material-theme);

, where obviously I defined the new background palette. After testing I see that it doesn't work as mat.define-light-theme seems to be dropping the background key internally and instead using an internal one. I'm not that familiar with Sass or material, and I would like be able to also define the background key introducing the least change on my code, using current version of Angular Material. Thanks in advance.

Postern answered 3/12, 2021 at 6:40 Comment(1)
have you tried to add foreground to your theme?Werner
B
7

I just had the same problem. From what I saw the background used is generated internaly as you said. The only way I found to override it, is to set the value in the returned $my-material-theme map.

Using the map set/get functions is pretty ugly, but with something like this you can override the background value, in this example to "red" :

$backgroundColor: red;
$color: map.get($my-material-theme, "color");
$colorBackground: map.get($color, "background");
$colorBackground: map.set($colorBackground, "background", 
$backgroundColor);
$color: map.set($color, "background", $colorBackground);
$my-material-theme: map.set($my-material-theme, "color", $color);

Then you can use the modified $my-material-theme the same way you did:

@include mat.all-component-themes($my-material-theme);
Benzel answered 17/1, 2022 at 15:41 Comment(0)
D
3

On Angular 16 with Material 16, if you have background/foreground setup as the following:

@use '@angular/material' as mat;
@use "sass:map";

// ...

// Background for dark theme.
$custom-dark-theme-background: (
  status-bar: black,
  app-bar:    map.get(mat.$grey-palette, 900),
  background: #28364a,
  hover:      rgba(white, 0.04),
  card:       #415267,
  dialog:     map.get(mat.$grey-palette, 800),
  disabled-button: rgba(white, 0.12),
  raised-button: map.get(mat.$grey-palette, 800),
  focused-button: $light-focused,
  selected-button: map.get(mat.$grey-palette, 900),
  selected-disabled-button: map.get(mat.$grey-palette, 800),
  disabled-button-toggle: black,
  unselected-chip: map.get(mat.$grey-palette, 700),
  disabled-list-option: #28364a,
  tooltip: #616161,
);

// Foreground for dark theme.
$custom-dark-theme-foreground: (
  base:              white,
  divider:           $light-dividers,
  dividers:          $light-dividers,
  disabled:          $light-disabled-text,
  disabled-button:   rgba(white, 0.3),
  disabled-text:     $light-disabled-text,
  elevation:         black,
  hint-text:         $light-disabled-text,
  secondary-text:    $light-secondary-text,
  icon:              white,
  icons:             white,
  text:              white,
  slider-min:        white,
  slider-off:        rgba(white, 0.3),
  slider-off-active: rgba(white, 0.3),
);

Define the dark theme:

$custom-dark-theme: mat.define-dark-theme((
    color: (
        primary: $custom-dark-primary,
        accent: $custom-dark-accent,
        warn: $custom-dark-warn
    )
));

Adding @debug $custom-dark-theme; to the scss file after the above is a good way to see what color options can be passed in the first block of code above.

Then manually set the background and foreground. The non-color versions appear to be the ones that are actively used but I'm setting both to match the 'new' color theme definition style.

$custom-dark-theme: map.set($custom-dark-theme, 'color', 'background', $custom-dark-theme-background);
$custom-dark-theme: map.set($custom-dark-theme, 'background', $custom-dark-theme-background);
$custom-dark-theme: map.set($custom-dark-theme, 'color', 'foreground', $custom-dark-theme-foreground);
$custom-dark-theme: map.set($custom-dark-theme, 'foreground', $custom-dark-theme-foreground);
Deflate answered 5/1 at 16:51 Comment(3)
I'll update the answer, but add @use "sass:map"; to the top of the file/below the @use '@angular/material' as mat; line.Deflate
I am getting an error saying $light-focused is undefined?Subdivide
Looks like that's defined in node_modules\@angular\material\core\theming\_palette.scss ($light-focused: rgba(white, 0.12);) - perhaps the an @use is missing from the custom theme file? You could drop in a static value and see if it fails again later in the file on another variable.Deflate
G
1

You could use this functions to change any params of background or foreground.

@function theme-background-change($theme, $name, $value) {
    $modified-theme: $theme;
    $theme-color: map-get($theme, color);
    $color-background-palette: map-get($theme-color, background);
    @if $color-background-palette {
        $color-background-palette: map-merge($color-background-palette, ($name: $value));
    }
    @if $color-background-palette {
        $modified-theme: map-merge($modified-theme, (color: (background: $color-background-palette)));
    }
    $background-palette: map-get($theme, background);
    @if $background-palette {
        $background-palette: map-merge($background-palette,($name: $value));
    }
    @if $background-palette {
        $modified-theme: map-merge($modified-theme,(background: $background-palette));
    }
    @return $modified-theme;
}

@function theme-foreground-change($theme, $name, $value) {
    $modified-theme: $theme;
    $theme-color: map-get($theme, color);
    $color-foreground-palette: map-get($theme-color, foreground);
    @if $color-foreground-palette {
        $color-foreground-palette: map-merge($color-foreground-palette, ($name: $value));
    }
    @if $color-foreground-palette {
        $modified-theme: map-merge($modified-theme, (color: (foreground: $color-foreground-palette)));
    }
    $foreground-palette: map-get($theme, foreground);
    @if $foreground-palette {
        $foreground-palette: map-merge($foreground-palette,($name: $value));
    } 
    @if $foreground-palette {
        $modified-theme: map-merge($modified-theme,(foreground: $foreground-palette));
    }
    @return $modified-theme;
}

Example usage:

$dark-primary: mat-palette($mat-light-blue, 300, 100, 500);
$dark-accent: mat-palette($mat-yellow, 400, 300, 600);
$dark-warn: mat-palette($mat-red, 400);

$dark-theme: mat-dark-theme($dark-primary, $dark-accent, $dark-warn);

$dark-theme: theme-background-change($dark-theme, 'body', #101010);
$dark-theme: theme-background-change($dark-theme, 'card', #101010);
$dark-theme: theme-background-change($dark-theme, 'hover', rgba(white, 0.06));
Gammon answered 24/1, 2022 at 12:1 Comment(0)
B
0

Modified @Renat Gubaev answer to new scss structure in material 13:

@use 'sass:map';

@function theme-background-change($theme, $name, $value) {
    $modified-theme: $theme;
    $theme-color: map.get($theme, color);
    $color-background-palette: map.get($theme-color, background);
    @if $color-background-palette {
        $color-background-palette: map.merge(
            $color-background-palette,
            (
                $name: $value,
            )
        );
    }
    @if $color-background-palette {
        $modified-theme: map.merge(
            $modified-theme,
            (
                color:
                    map.merge(
                        $theme-color,
                        (
                            background: $color-background-palette,
                        )
                    ),
            )
        );
    }

    $background-palette: map.get($theme, background);
    @if $background-palette {
        $background-palette: map.merge(
            $background-palette,
            (
                $name: $value,
            )
        );
    }
    @if $background-palette {
        $modified-theme: map.merge(
            $modified-theme,
            (
                background: $background-palette,
            )
        );
    }
    @return $modified-theme;
}
Byblow answered 31/1, 2022 at 15:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.