I am trying to implement the ability to switch between the Dark and Light Angular material theme. Here is the Stackblitz demo.
The issue is, if I set the Dark theme as default, then it is applied correctly but when I switch to the Light theme, then it is applied partially. Similarly, if I set the Light theme as default, then the Dark theme is applied partially.
As seen in the screenshot below, light-theme CSS is unable to override the default theme:
What is the issue here?
src\app@theme\styles_variables.scss:
@use "@angular/material" as mat;
$light-primary-palette: (
...light-primary-colors-range...
);
$light-accent-palette: (
...light-accent-colors-range...
);
$dark-primary-palette: (
...dark-primary-colors-range...
);
$dark-accent-palette: (
...dark-accent-colors-range...
);
src\app@theme\styles_theme.scss:
@use 'sass:map';
@forward './variables';
@use '@angular/material' as mat;
@use './variables' as variables;
$light-primary: mat.define-palette(variables.$light-primary-palette);
$light-accent: mat.define-palette(variables.$light-accent-palette);
$light-warn: mat.define-palette(mat.$red-palette);
$light-theme: mat.define-light-theme(
(
color: (
primary: $light-primary,
accent: $light-accent,
warn: $light-warn,
),
)
);
$dark-primary: mat.define-palette(variables.$dark-primary-palette);
$dark-accent: mat.define-palette(variables.$dark-accent-palette);
$dark-warn: mat.define-palette(mat.$red-palette);
$dark-theme: mat.define-dark-theme(
(
color: (
primary: $dark-primary,
accent: $dark-accent,
warn: $dark-warn,
),
)
);
// Apply the dark theme by default
@include mat.all-component-themes($dark-theme);
// Include the light color styles inside of a block with a CSS class. You can make this
// CSS class whatever you want. In this example, any component inside of an element with
// `.light-theme` will be affected by this alternate light theme instead of the default dark theme.
.light-theme {
@include mat.all-component-themes($light-theme);
}
src\styles.scss:
@use "./app/@theme/styles/theme";
src\app@theme\theme.service.ts:
export class ThemeService {
private _lightTheme = new BehaviorSubject<boolean>(false);
private _activeTheme = new BehaviorSubject<Theme>(Theme.Light);
isLightTheme$ = this._lightTheme.asObservable();
activeTheme$ = this._activeTheme.asObservable();
setLightTheme(isLightTheme: boolean): void {
this._lightTheme.next(isLightTheme);
if (isLightTheme) {
this._activeTheme.next(Theme.Dark);
} else {
this._activeTheme.next(Theme.Light);
}
}
}
src\app\app.module.ts:
export class AppModule {
constructor(
overlayContainer: OverlayContainer,
private _themeService: ThemeService
) {
this._themeService.isLightTheme$.subscribe((isLightTheme) => {
if (isLightTheme) {
overlayContainer.getContainerElement().classList.add('.light-theme');
}
});
}
}
src\app@theme\components\header\header.component.html:
<mat-toolbar class="header" *subscribe="isLightTheme$; let isLightTheme">
<span class="spacer"></span>
<mat-slide-toggle
[color]="'warn'"
[checked]="isLightTheme"
(change)="toggleDarkTheme($event.checked)"
>{{ isLightTheme ? "Light Theme" : "Dark Theme" }}</mat-slide-toggle
>
</mat-toolbar>
src\app@theme\components\header\header.component.ts:
export class HeaderComponent {
isLightTheme$: Observable<boolean> = this._themeService.isLightTheme$;
constructor(private _themeService: ThemeService) {}
public toggleDarkTheme(checked: boolean) {
this._themeService.setLightTheme(checked);
}
}