Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow overriding of theme background and foreground colors #6244

Closed
mackelito opened this issue Aug 3, 2017 · 43 comments
Closed

Allow overriding of theme background and foreground colors #6244

mackelito opened this issue Aug 3, 2017 · 43 comments
Assignees
Labels
area: theming feature This issue represents a new feature or feature request rather than a bug or bug fix help wanted The team would appreciate a PR from the community to address this issue P4 A relatively minor issue that is not relevant to core functions

Comments

@mackelito
Copy link

Bug, feature request, or proposal:

proposal

What is the expected behavior?

Add documentation on how to set background in a custom theme to https://material.angular.io/guide/theming

What is the current behavior?

No docs

What are the steps to reproduce?

https://material.angular.io/guide/theming

Providing a Plunker (or similar) is the best way to get the team to see your issue.
Plunker template: https://goo.gl/DlHd6U

What is the use-case or motivation for changing an existing behavior?

Makes it easier to customise themes

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

Is there anything else we should know?

@jelbourn jelbourn added docs This issue is related to documentation help wanted The team would appreciate a PR from the community to address this issue P4 A relatively minor issue that is not relevant to core functions labels Aug 17, 2017
@literalpie
Copy link
Contributor

Should developers be encouraged to set background colors of a theme? Or do we just want documentation on using the background color from a theme?

put differently:
Do we want to (a) show people how to change the value of map-get($theme, background), or do we want to (b) document that map-get($theme, background) can be used?

@fabienbranchel
Copy link

@literalpie : I'd like to know how to set background colors of a theme when I create it.

@literalpie
Copy link
Contributor

literalpie commented Jan 28, 2018

@fabienbranchel
If you want to set the background colors, you likely want to customize the entire background and foreground palette by emulating the mat-light-theme or mat-dark-theme functions with your own replacement. Your replacement would include your own palettes instead of the mat-light-theme-foreground and background palettes.

example: https://stackblitz.com/edit/angular-material-custom-background?file=theme.scss

I don't know if this method is recommended or officially supported - therefore, I'm not sure if it should be added to the documentation. It seems to me like it would be a better fit for a blog post.

@intellix
Copy link

intellix commented Apr 8, 2019

Would be nice if those 2 functions were similar to how red has defaults to allow overriding without copy/pasting:

// Creates a container object for a light theme to be given to individual component theme mixins.
@function mat-light-theme($primary, $accent, $warn: mat-palette($mat-red), $foreground: mat-palette($mat-light-theme-foreground), $background: mat-palette($mat-light-theme-background)) {
  @return (
    primary: $primary,
    accent: $accent,
    warn: $warn,
    is-dark: false,
    foreground: $foreground,
    background: $background,
  );
}

// Creates a container object for a dark theme to be given to individual component theme mixins.
@function mat-dark-theme($primary, $accent, $warn: mat-palette($mat-red), $foreground: mat-palette($mat-dark-theme-foreground), $background: mat-palette($mat-dark-theme-background)) {
  @return (
    primary: $primary,
    accent: $accent,
    warn: $warn,
    is-dark: true,
    foreground: $foreground,
    background: $background,
  );
}

Or better yet, just don't use those functions:

$my-dark-theme: (
  primary: $my-primary,
  accent: $my-accent,
  warn: $my-warn,
  is-dark: true,
  foreground: $my-dark-theme-foreground,
  background: $my-dark-theme-background,
);

$my-light-theme: (
  primary: $my-primary,
  accent: $my-accent,
  warn: $my-warn,
  is-dark: false,
  foreground: $my-light-theme-foreground,
  background: $my-light-theme-background,
);

To be honest whilst reading into all of the helpers the mat-light-theme() and mat-dark-theme() functions add an extra layer of complexity that doesn't add anything IMO

@ktsangop
Copy link

ktsangop commented Jun 5, 2019

I have also struggled to find a way to set the app background, and unfortunately the proposed solutions do not work if the app is not wrapped in a material component.

For example, in @literalpie 's example, the app is wrapped inside a mat-sidenav-container component.

The only way i have found to set the background for app-root, is to inculde the following in your styles.scss file (or whatever the name of the file that you declare on your angular.json definition)

app-root {
  background: map-get($mat-dark-theme-background, background );
}

That will work, provided that you have declared the $mat-dark-theme-background map, and it is helpful because you keep your background color declared in one place (theme.scss).

Of course you can provide any color, that is independent of the theme you have created, but this might be harder to maintain.

@literalpie
Copy link
Contributor

@ktsangop I think you're missing this:

Finally, if your app's content is not placed inside of a mat-sidenav-container element, you need to add the mat-app-background class to your wrapper element (for example the body). This ensures that the proper theme background is applied to your page.

source

@literalpie
Copy link
Contributor

literalpie commented Jun 6, 2019

@intellix

To be honest whilst reading into all of the helpers the mat-light-theme() and mat-dark-theme() functions add an extra layer of complexity that doesn't add anything IMO

Are you saying that instead of having the two functions, someone would use the dark theme by passing the foreground and background? I could get on board with that.

@ktsangop
Copy link

ktsangop commented Jun 6, 2019

@ktsangop I think you're missing this:

Finally, if your app's content is not placed inside of a mat-sidenav-container element, you need to add the mat-app-background class to your wrapper element (for example the body). This ensures that the proper theme background is applied to your page.

source

🤦‍♂ OK, i have totally missed that! 🤣

FWIW, my solution, applies the background color even before the app.component is bootstraped, which in my case makes a custom loading spinner i have, being displayed using the theme background color.

Instead, adding the mat-app-background class to the <body> does not have the same effect.

@prabhat22
Copy link

i am trying to use angular material with a theme built in scss,angular,bootstrap , i have install it using npm and add all the neccessary files, also it is not showing any error yet i am not able to use it components

@the-blackpirate
Copy link

Just add Material theming in your angular project.

ng add @angular/material

then choose custom theming option and paste the below code you will get black dark theming and if you wanna customize material color scheme then go to https://material.io and go material color palette and select your custom color scheme for your navbar and button(other components).

@import "~@angular/material/theming";

$custom-typography: mat-typography-config(
$font-family:
"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif"
);

@include mat-core($custom-typography);

$your-app-name-primary: mat-palette($mat-purple, 200);
$your-app-name-accent: mat-palette($mat-teal, 200);
$your-app-name-warn: mat-palette($mat-red);
$your-app-name-theme: mat-dark-theme(
$your-app-name-primary,
$your-app-name-accent,
$your-app-name-warn
);

@include angular-material-theme($your-app-name-theme);

@nair-ayush
Copy link

Just found this thread. I've been trying to figure out themes for a long time. Couldn't find a concrete solution until now. Making it work by adding <mat-sidenav-container> over the app. So thank you @literalpie . But can you give an example of how to add the mat-app-background to the body element?

However, if I don't have enough content on the window then the rest of the background remains white(default color) only. So you would need to modify the style of <mat-sidenav-container> to max out it's height. You can see the app.component.css to look at what I've done.

I have applied the theme toggle in my header and as per Angular Material docs, added an extra class to the div wrapper by adding an id and modifying it's style in theme.service.ts.

custom_theme.scss

@import "~@angular/material/theming";
@include mat-core();

// LIGHT THEME

$light-primary: mat-palette($mat-indigo);
$light-accent: mat-palette($mat-yellow, A200, A100, A400);
$light-warn: mat-palette($mat-red);
$light-theme: mat-light-theme($light-primary, $light-accent, $light-warn);
@include angular-material-theme($light-theme);

// DARK THEME

$dark-primary: mat-palette($mat-grey);
$dark-accent: mat-palette($mat-amber, A200, A100, A400);
$dark-warn: mat-palette($mat-red);
// Create the theme object (a Sass map containing all of the palettes).
$dark-theme: mat-dark-theme($dark-primary, $dark-accent, $dark-warn);

.dark-theme {
  @include angular-material-theme($dark-theme);
}

app.component.html

<div id="alternative-theme">
  <mat-sidenav-container class="app-container">
    <app-header></app-header>
    <router-outlet> </router-outlet>
    <app-footer></app-footer>
  </mat-sidenav-container>
</div>

app.component.css

#alternative-theme {
  display: block;
  height: 100%;
}

.app-container {
  height: inherit;
}

theme.service.ts

import { Injectable } from "@angular/core";
import { OverlayContainer } from "@angular/cdk/overlay";

@Injectable({
  providedIn: "root"
})
export class ThemeService {
  constructor(private overlayContainer: OverlayContainer) {
    this.overlayContainer = overlayContainer;
  }

  setDarkTheme() {
    document.getElementById("alternative-theme").classList.add("dark-theme");
    document.getElementById("footer-text").classList.remove("dark");
    this.overlayContainer.getContainerElement().classList.add("dark-theme");
  }

  setLightTheme() {
    document.getElementById("alternative-theme").classList.remove("dark-theme");
    document.getElementById("footer-text").classList.add("dark");
    this.overlayContainer.getContainerElement().classList.remove("dark-theme");
    document;
  }
}

Is this the best way to toggle between themes or is there a more robust way? I'm just starting with Angular and Material UI and if you have anything to add to the above snippets to make it better will be appreciated. Cheers.

@the-ult
Copy link

the-ult commented Feb 26, 2020

@nair-ayush

Just put the classes on your body or app:

<body class="mat-typography mat-app-background">
    <app-root></app-root>
  </body>

@see https://material.angular.io/guide/theming#using-a-pre-built-theme

Finally, if your app's content is not placed inside of a mat-sidenav-container element, you need to add the mat-app-background class to your wrapper element (for example the body). This ensures that the proper theme background is applied to your page.

@tomasdev
Copy link

tomasdev commented Jul 14, 2020

Adding onto @intellix proposal:

It'd be backwards compatible to change the current mat-light-theme (and mat-dark-theme with the proper methods) implementations to call:

@function mat-light-theme(...) {
  // ...
  $result: $primary;
  @if map_get($primary, color) {
    $color-settings: map_get($primary, color);
    $primary: map_get($color-settings, primary);
    $accent: map_get($color-settings, accent);
    $warn: map_get($color-settings, warn);
    $foreground: map_get($color-settings, foreground);
    $background: map_get($color-settings, background);
    $result: map_merge($result, (color: _mat-create-light-color-config($primary, $accent, $warn, $foreground, $background)));
  }
  @return _mat-create-backwards-compatibility-theme(_mat-validate-theme($result));
}

@function _mat-create-light-color-config($primary, $accent, $warn: null, $foreground: $mat-light-theme-foreground, $background: $mat-light-theme-background) {
  @return (
    primary: $primary,
    accent: $accent,
    warn: if($warn != null, $warn, mat-palette($mat-red)),
    is-dark: false,
    foreground: $foreground,
    background: $background,
  );
}

This way, guarantees that people using the older stuff still works (since it defaults to the global variables) and yet people who want can use the cleaner method:

$theme: mat-light-theme((
  color: (
    primary: $primary,
    accent: $accent,
    warn: $warn,
    background: (
      app-bar: #fff,
    ),
  ),
));

Right now the equivalent of the above usage is:

$mat-light-theme-background: map_merge($mat-light-theme-background, (
  app-bar: #fff,
));

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

@diosney
Copy link

diosney commented Jul 27, 2020

Hopefully this gets added soon.

It is pretty annoying to being able to set primary, accent and warn palettes, and not being able to set the foreground and background ones in an easy and clean way too.

(Right now using the accepted answer at https://stackoverflow.com/questions/43919927/angular-material2-theming-how-to-set-app-background)

@anschm
Copy link

anschm commented May 20, 2021

Can this please added soon. Thx.

@twerske twerske added feature This issue represents a new feature or feature request rather than a bug or bug fix and removed docs This issue is related to documentation labels May 21, 2021
@twerske twerske self-assigned this May 21, 2021
@twerske twerske changed the title Add docs on how to set background in theme Allow overriding of theme background and foreground colors May 24, 2021
@rscircus
Copy link

rscircus commented Jul 8, 2021

It took me days to find this issue from 2017... phew.

@rscircus
Copy link

rscircus commented Jul 8, 2021

OK, I managed to also apply the light/dark toggling to the whole app by putting everything in a container of class 'mat-app-background'.

@rscircus
Copy link

rscircus commented Jul 8, 2021

Like so:

image

@michaelfaith
Copy link

michaelfaith commented Aug 26, 2021

@fabienbranchel
If you want to set the background colors, you likely want to customize the entire background and foreground palette by emulating the mat-light-theme or mat-dark-theme functions with your own replacement. Your replacement would include your own palettes instead of the mat-light-theme-foreground and background palettes.

I actually disagree with this assertion. I've been working through this myself recently, and you pretty much have to dig deeply into the theming api to figure out how to override the base background color. If we could pass some subset of the foreground and background theme object (just the things we care about overriding) into the define theme functions, and those partials are merged with what's being set by default, then that would seem like the best of both worlds. I basically had to do a map.deep-merge, after the theme was defined to augment the background palette that was generated by default. I didn't care about overriding everything, just a handful of surface properties.

@mattiLeBlanc
Copy link

I just want to change the 'text' colour from the 'foreground' map. You used to be able to do it like described here: https://newbedev.com/how-to-change-font-color-of-primary-palette-in-angular-material2
but now that is no longer possible.

Why can't we support something like:

$core-theme: mat.define-light-theme((
  color: (
    primary: $primary,
    accent: $accent,
    warn: $warn,
    foreground: (
      base:              black,
      divider:           $dark-dividers,
      dividers:          $dark-dividers,
      disabled:          $dark-disabled-text,
      disabled-button:   rgba(black, 0.26),
      disabled-text:     $dark-disabled-text,
      elevation:         black,
      hint-text:         $dark-disabled-text,
      secondary-text:    $dark-secondary-text,
      icon:              rgba(black, 0.54),
      icons:             rgba(black, 0.54),
      text:              red,
      // text:              rgba(black, 0.87),
      slider-min:        rgba(black, 0.87),
      slider-off:        rgba(black, 0.26),
      slider-off-active: rgba(black, 0.38),
    )
  )
));

so I can change the text colour to whatever I want.
And yes, the main issue is the mat-drawer-container getting the colour from foreground.text.
I don't really want to CSS hack it is I can do it in a nice way.

@michaelfaith
Copy link

michaelfaith commented Oct 4, 2021

Why can't we support something like:

$core-theme: mat.define-light-theme((
  color: (
    primary: $primary,
    accent: $accent,
    warn: $warn,
    foreground: (
      base:              black,
      divider:           $dark-dividers,
      dividers:          $dark-dividers,
      disabled:          $dark-disabled-text,
      disabled-button:   rgba(black, 0.26),
      disabled-text:     $dark-disabled-text,
      elevation:         black,
      hint-text:         $dark-disabled-text,
      secondary-text:    $dark-secondary-text,
      icon:              rgba(black, 0.54),
      icons:             rgba(black, 0.54),
      text:              red,
      // text:              rgba(black, 0.87),
      slider-min:        rgba(black, 0.87),
      slider-off:        rgba(black, 0.26),
      slider-off-active: rgba(black, 0.38),
    )
  )
));

Yep, passing in the foreground and background overrides, and the define-*-theme function merging those onto the default would be my preference too. The only way I've been able to do it, is use the define function to generate the theme object, and then override those props after the fact. It's hacky, and i'd much prefer a way to do it that's officially supported, but it works for now.

@michaelfaith
Copy link

michaelfaith commented Oct 4, 2021

This function (and the dark theme version) is what would likely need to change, to allow for those parameters, instead of only taking defaults.

@function _mat-create-light-color-config($primary, $accent, $warn: null) {
@return (
primary: $primary,
accent: $accent,
warn: if($warn != null, $warn, define-palette(palette.$red-palette)),
is-dark: false,
foreground: palette.$light-theme-foreground-palette,
background: palette.$light-theme-background-palette,
);
}

Ideally it would start with the defaults and merge in whatever overrides are passed in. So that the entire map doesn't need to be defined.

@lerabela
Copy link

Until a fix is added. just bypass the create theme function in your main style file.

see solution: https://stackblitz.com/edit/angular-material-custom-background?file=theme.scss

@dhutaryan
Copy link

dhutaryan commented Jan 16, 2022

Don't work:

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

$background: map-get($custom-theme, background);
$background: map-merge(
  $background,
  (
    app-bar: red,
    background: #ffffff,
  )
);

$custom-theme: map-merge(
  $custom-theme,
  (
    background: $background,
  )
);

It would be nice to have easy way to change background and foreground

@MikaStark
Copy link

MikaStark commented Jan 20, 2022

I agree that providing a way to easily customizing foreground and background colors would be a blast.
Until now, I use my own theme mixin that override the existing one (in order to stay compatible with Material). But I would prefer Material provide the way to do it properly by passing just foreground and background variables (just like the other colors)
Anyway, if someone is interesting in my code, here it is :

src/app/core/theming/_palette.scss

@use "sass:map";

// Of course you can customize everything ;)

$dark-primary-text: rgba(#000939, 0.87);
$dark-secondary-text: rgba(#000939, 0.54);
$dark-disabled-text: rgba(#000939, 0.38);
$dark-dividers: rgba(#000939, 0.12);
$dark-focused: rgba(#000939, 0.12);
$light-primary-text: white;
$light-secondary-text: rgba(white, 0.7);
$light-disabled-text: rgba(white, 0.5);
$light-dividers: rgba(white, 0.12);
$light-focused: rgba(white, 0.12);

$grey-palette: (
  50: #f7f9ff,
  100: #f1f3fb,
  200: #e8eaf2,
  300: #d9dbe3,
  400: #b5b7bf,
  500: #96979f,
  600: #6d6f76,
  700: #5a5b62,
  800: #3b3d43,
  900: #1b1c22,
  contrast: (
    50: $dark-primary-text,
    100: $dark-primary-text,
    200: $dark-primary-text,
    300: $dark-primary-text,
    400: $dark-primary-text,
    500: $dark-primary-text,
    600: $light-primary-text,
    700: $light-primary-text,
    800: $light-primary-text,
    900: $light-primary-text,
  ),
);

$night-palette: (
  50: #e3ecff,
  100: #bed1e9,
  200: #9eb1ce,
  300: #7c92b2,
  400: #637c9e,
  500: #4a668b,
  600: #3c597a,
  700: #2d4664,
  800: #1e344e,
  900: #0b2137,
  contrast: (
    50: $dark-primary-text,
    100: $dark-primary-text,
    200: $dark-primary-text,
    300: $light-primary-text,
    400: $light-primary-text,
    500: $light-primary-text,
    600: $light-primary-text,
    700: $light-primary-text,
    800: $light-primary-text,
    900: $light-primary-text,
  ),
);

// Background palette for light themes.
$light-theme-background-palette: (
  status-bar: map.get($grey-palette, 300),
  app-bar: white,
  background: map.get($grey-palette, 50),
  hover: rgba(#243b53, 0.04),
  card: white,
  dialog: white,
  disabled-button: rgba(#243b53, 0.12),
  raised-button: white,
  focused-button: $dark-focused,
  selected-button: map.get($grey-palette, 300),
  selected-disabled-button: map.get($grey-palette, 400),
  disabled-button-toggle: map.get($grey-palette, 200),
  unselected-chip: map.get($grey-palette, 200),
  disabled-list-option: map.get($grey-palette, 200),
  tooltip: map.get($grey-palette, 700),
);

// Background palette for dark themes.
$dark-theme-background-palette: (
  status-bar: #0b2844,
  app-bar: map.get($night-palette, 900),
  background: #102a43,
  hover: rgba(white, 0.04),
  card: map.get($night-palette, 800),
  dialog: map.get($night-palette, 800),
  disabled-button: rgba(white, 0.12),
  raised-button: map.get($night-palette, 800),
  focused-button: $light-focused,
  selected-button: map.get($night-palette, 900),
  selected-disabled-button: map.get($night-palette, 800),
  disabled-button-toggle: #243b53,
  unselected-chip: map.get($night-palette, 700),
  disabled-list-option: #243b53,
  tooltip: map.get($night-palette, 700),
);

// Foreground palette for light themes.
$light-theme-foreground-palette: (
  base: #243b53,
  divider: $dark-dividers,
  dividers: $dark-dividers,
  disabled: $dark-disabled-text,
  disabled-button: rgba(#243b53, 0.26),
  disabled-text: $dark-disabled-text,
  elevation: #243b53,
  hint-text: $dark-disabled-text,
  secondary-text: $dark-secondary-text,
  icon: rgba(#243b53, 0.54),
  icons: rgba(#243b53, 0.54),
  text: rgba(#243b53, 0.87),
  slider-min: rgba(#243b53, 0.87),
  slider-off: rgba(#243b53, 0.26),
  slider-off-active: rgba(#243b53, 0.38),
);

// Foreground palette for dark themes.
$dark-theme-foreground-palette: (
  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),
);

src/app/core/theming/_theming.scss

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

@function define-light-theme($config) {
  $theme: mat.define-light-theme($config);
  $color: map.get($theme, color);
  $color: map.merge(
    $color,
    (
      background: palette.$light-theme-background-palette,
      foreground: palette.$light-theme-foreground-palette,
    )
  );
  @return map.merge(
    $theme,
    (
      color: $color,
    )
  );
}

@function define-dark-theme($config) {
  $theme: mat.define-dark-theme($config);
  $color: map.get($theme, color);
  $color: map.merge(
    $color,
    (
      background: palette.$dark-theme-background-palette,
      foreground: palette.$dark-theme-foreground-palette,
    )
  );
  @return map.merge(
    $theme,
    (
      color: $color,
    )
  );
}

core/theming/_index.scss

@forward "palette";
@forward "theming";

// Here you can forward your own themes located in core/themeing/themes
// @forward "themes/xxxx" as xxxx-*;
// ...

src/styles.scss

@use "@angular/material" as mat;
@use "app/core/theming" as app;
@use "sass:map";

@include mat.core();

$app-primary: mat.define-palette(mat.$indigo-palette);
$app-accent: mat.define-palette(mat.$pink-palette);

// Use your own "app" define-light-theme function instead of "mat" one.
$app-theme: app.define-light-theme(
  (
    color: (
      primary: $app-primary,
      accent: $app-accent,
    )
  )
);

@arbiyanto
Copy link

arbiyanto commented Mar 19, 2022

@MikaStark trying to work around with your example in material v13, but it doesn't change anything to the theme.

palette.scss

@use "sass:map";

// Of course you can customize everything ;)

$dark-primary-text: rgba(#000939, 0.87);
$dark-secondary-text: rgba(#000939, 0.54);
$dark-disabled-text: rgba(#000939, 0.38);
$dark-dividers: rgba(#000939, 0.12);
$dark-focused: rgba(#000939, 0.12);
$light-primary-text: white;
$light-secondary-text: rgba(white, 0.7);
$light-disabled-text: rgba(white, 0.5);
$light-dividers: rgba(white, 0.12);
$light-focused: rgba(white, 0.12);

$grey-palette: (
  50: #f8fafc,
  100: #f1f5f9,
  200: #e2e8f0,
  300: #cbd5e1,
  400: #94a3b8,
  500: #64748b,
  600: #475569,
  700: #334155,
  800: #1e293b,
  900: #0f172a,
  contrast: (
    50: $dark-primary-text,
    100: $dark-primary-text,
    200: $dark-primary-text,
    300: $dark-primary-text,
    400: $dark-primary-text,
    500: $dark-primary-text,
    600: $light-primary-text,
    700: $light-primary-text,
    800: $light-primary-text,
    900: $light-primary-text,
  ),
);

$night-palette: (
  50: #f8fafc,
  100: #f1f5f9,
  200: #e2e8f0,
  300: #cbd5e1,
  400: #94a3b8,
  500: #64748b,
  600: #475569,
  700: #334155,
  800: #1e293b,
  900: #0f172a,
  contrast: (
    50: $dark-primary-text,
    100: $dark-primary-text,
    200: $dark-primary-text,
    300: $light-primary-text,
    400: $light-primary-text,
    500: $light-primary-text,
    600: $light-primary-text,
    700: $light-primary-text,
    800: $light-primary-text,
    900: $light-primary-text,
  ),
);

// Background palette for light themes.
$light-theme-background-palette: (
  status-bar: map.get($grey-palette, 300),
  app-bar: white,
  background: map.get($grey-palette, 50),
  hover: rgba(#243b53, 0.04),
  card: white,
  dialog: white,
  disabled-button: rgba(#243b53, 0.12),
  raised-button: white,
  focused-button: $dark-focused,
  selected-button: map.get($grey-palette, 300),
  selected-disabled-button: map.get($grey-palette, 400),
  disabled-button-toggle: map.get($grey-palette, 200),
  unselected-chip: map.get($grey-palette, 200),
  disabled-list-option: map.get($grey-palette, 200),
  tooltip: map.get($grey-palette, 700),
);

// Background palette for dark themes.
$dark-theme-background-palette: (
  status-bar: #0b2844,
  app-bar: map.get($night-palette, 900),
  background: #102a43,
  hover: rgba(white, 0.04),
  card: map.get($night-palette, 800),
  dialog: map.get($night-palette, 800),
  disabled-button: rgba(white, 0.12),
  raised-button: map.get($night-palette, 800),
  focused-button: $light-focused,
  selected-button: map.get($night-palette, 900),
  selected-disabled-button: map.get($night-palette, 800),
  disabled-button-toggle: #243b53,
  unselected-chip: map.get($night-palette, 700),
  disabled-list-option: #243b53,
  tooltip: map.get($night-palette, 700),
);

// Foreground palette for light themes.
$light-theme-foreground-palette: (
  base: #243b53,
  divider: $dark-dividers,
  dividers: $dark-dividers,
  disabled: $dark-disabled-text,
  disabled-button: rgba(#243b53, 0.26),
  disabled-text: $dark-disabled-text,
  elevation: #243b53,
  hint-text: $dark-disabled-text,
  secondary-text: $dark-secondary-text,
  icon: rgba(#243b53, 0.54),
  icons: rgba(#243b53, 0.54),
  text: rgba(#243b53, 0.87),
  slider-min: rgba(#243b53, 0.87),
  slider-off: rgba(#243b53, 0.26),
  slider-off-active: rgba(#243b53, 0.38),
);

// Foreground palette for dark themes.
$dark-theme-foreground-palette: (
  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),
);

theming.scss

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

@function define-light-theme($primary, $accent: null) {
  $theme: mat.define-light-theme($primary, $accent);
  $color: map.get($theme, color);
  $color: map.merge(
    $color,
    (
      background: palette.$light-theme-background-palette,
      foreground: palette.$light-theme-foreground-palette,
    )
  );
  @return map.merge(
    $theme,
    (
      color: $color,
    )
  );
}

@function define-dark-theme($primary, $accent: null) {
  $theme: mat.define-dark-theme($primary, $accent);
  $color: map.get($theme, color);
  $color: map.merge(
    $color,
    (
      background: palette.$dark-theme-background-palette,
      foreground: palette.$dark-theme-foreground-palette,
    )
  );
  @return map.merge(
    $theme,
    (
      color: $color,
    )
  );
}

styles.scss

@use '@angular/material' as mat;
@use "globals/theming" as app;

@include mat.core($custom-typography);
// ... primary accent variables

$dark-theme: app.define-dark-theme($dark-primary, $dark-accent);
@include mat.core-theme($dark-theme);
@include mat.button-theme($dark-theme);
@include mat.expansion-theme($dark-theme);

And I didn't change any code other than the color palette gray and night. But the end result is the component button and the expansion panel color are still same. Is there anything I missed?

@MikaStark
Copy link

@arbiyanto that’s because you are using the old/deprecated way to declare a theme. You provide two arguments to your define theme function instead of providing one which should be a theme config.

$app-dark-theme: app.define-dark-theme(
  (
    color: (
      primary: $app-primary,
      accent: $app-accent,
    )
  )
);

@arbiyanto
Copy link

@MikaStark I see, thanks for the response! it's working now.

@ftaffelt
Copy link

ftaffelt commented May 18, 2022

to mostly reuse the original angular material helper i used this approach to set some colors:

// ex. set custom text and secondary text color to css custom properties variant
// add this after mat.define-light-theme or mat.define-dark-theme and before emitting any component-themes
$custom-theme: map.set($custom-theme, color, foreground, text, var(--text-color));
$custom-theme: map.set($custom-theme, color, foreground, secondary-text, var(--secondary-text-color));

@ibrcic
Copy link

ibrcic commented May 23, 2022

One solution that I found works perfectly and is easy to understand and use is using map.deep-merge() to merge generated theme map with my own overrides. Here is an example of overriding default light theme background and text color:

$theme: mat.define-light-theme(...);

$material-theme-overrides: (
  'color': (
    'background': (
      'background': var(--background),
    ),
    'foreground': (
      'text': var(--text-primary),
    ),
  ),
);

$theme: map.deep-merge($theme, $material-theme-overrides);

map.deep-merge() works similarly to map.merge() except that nested map values are also recursively merged. To check which properties you can actually override, you can check the bottom of this file in source for material theming. https://github.com/angular/components/blob/main/src/material/core/theming/_palette.scss

@Alessandroinfo
Copy link

I still have this issue. Themed Angular Material with mat.define-light-theme and mat.all-component-themes but for the primary button raised the text color is black and not white.

@derSoerrn95
Copy link

derSoerrn95 commented Mar 8, 2023

After days of digging, I finally found @MikaStark's reply. Thanks @MikaStark! At least it would be great if his answer would be mentioned in the official docs.

@Alessandroinfo
Copy link

The answer of @MikaStark don't work for and the primary color text it's still black.

@MikaStark
Copy link

@Alessandroinfo this is an known issue of MDC migration (cf. #26056) that is not related to this issue. The solution I proposed is working.

@Alessandroinfo
Copy link

Alessandroinfo commented Jul 13, 2023

@Alessandroinfo this is an known issue of MDC migration (cf. #26056) that is not related to this issue. The solution I proposed is working.

@MikaStark I tried that here but don't work.

@MikaStark
Copy link

@Alessandroinfo this is an known issue of MDC migration (cf. #26056) that is not related to this issue. The solution I proposed is working.

@MikaStark I tried that here but don't work.

According to your code, you don’t override anything and as I said in my previous post, there is a known issue about contrast colors and buttons. I’m afraid that you are out of this issue scope.

heXXag0n added a commit to heXXag0n/material-theming-easy-background-foreground-colors that referenced this issue Jul 14, 2023
…eground to color object

While declaring the primary, accent and warn via the color object is easy and straight-forward, the configuration of foreground and background proves rather tedious.
This commit adds the ability to declare foreground and background in the color object when defining a theme, even partially, meaning that missing values are taken from the default light or dark theme respectively.

Fixes angular#11390, angular#6244
heXXag0n added a commit to heXXag0n/material-theming-easy-background-foreground-colors that referenced this issue Jul 15, 2023
…eground to color object

While declaring the primary, accent and warn via the color object is easy and straight-forward, the configuration of foreground and background proves rather tedious.
This commit adds the ability to declare foreground and background in the color object when defining a theme, even partially, meaning that missing values are taken from the default light or dark theme respectively.

This commit fixes some possible NPEs in _theming.scss

Fixes angular#11390, angular#6244
@Alessandroinfo
Copy link

@MikaStark i reverted the edit. I've modified the theme like your answer but after i cannot see any color in my material component. As a soon i can I'll edit again and let you see.

@AlonsoK28
Copy link

One solution that I found works perfectly and is easy to understand and use is using map.deep-merge() to merge generated theme map with my own overrides. Here is an example of overriding default light theme background and text color:

$theme: mat.define-light-theme(...);

$material-theme-overrides: (
  'color': (
    'background': (
      'background': var(--background),
    ),
    'foreground': (
      'text': var(--text-primary),
    ),
  ),
);

$theme: map.deep-merge($theme, $material-theme-overrides);

map.deep-merge() works similarly to map.merge() except that nested map values are also recursively merged. To check which properties you can actually override, you can check the bottom of this file in source for material theming. https://github.com/angular/components/blob/main/src/material/core/theming/_palette.scss

using your approach, how we can change the color of a mat-form-field ?

@BenLune
Copy link

BenLune commented Apr 20, 2024

Thanks @ibrcic for your great idea, which works.
It's quite surprising such a standard theming needs is not considered. When we create an app, we need to be able to apply a custom theme, for everything. I think it was protected to prevent people from doing bad things, but we should be able to override it if we need it and we know what we do.

@amysorto
Copy link
Contributor

There is a schematic for custom themes. Also with the addition of #29363 in v19, you will be able to override theme values system values with the theme-overrides mixin. The theming guide will be updated with more details and instructions!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: theming feature This issue represents a new feature or feature request rather than a bug or bug fix help wanted The team would appreciate a PR from the community to address this issue P4 A relatively minor issue that is not relevant to core functions
Projects
None yet
Development

No branches or pull requests