Skip to content

Commit 0b94209

Browse files
author
Eugene
committed
feat: respect-users-preferred-color-scheme
1 parent 3438194 commit 0b94209

File tree

2 files changed

+37
-23
lines changed

2 files changed

+37
-23
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
<button class="theme-mode-toggle">
2-
<span class="material-icons" *ngIf="!isDarkMode" (click)="toggleThemeMode()"> light_mode </span>
3-
<span class="material-icons" *ngIf="isDarkMode" (click)="toggleThemeMode()"> dark_mode </span>
2+
<span class="material-icons" *ngIf="theme === 'dark'" (click)="toggleTheme()">
3+
light_mode
4+
</span>
5+
<span
6+
class="material-icons"
7+
*ngIf="theme === 'light'"
8+
(click)="toggleTheme()"
9+
>
10+
dark_mode
11+
</span>
412
</button>

src/app/shared/components/theme-mode-toggle/theme-mode-toggle.component.ts

+27-21
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import { DOCUMENT } from '@angular/common';
33
import { MediaMatcher } from '@angular/cdk/layout';
44
import { StorageService } from '../../services/storage.service';
55

6+
type Theme = 'light' | 'dark';
7+
68
@Component({
79
selector: 'app-theme-mode-toggle',
810
templateUrl: './theme-mode-toggle.component.html',
911
styleUrls: ['./theme-mode-toggle.component.scss'],
1012
})
1113
export class ThemeModeToggleComponent implements OnInit {
12-
isDarkMode: boolean;
14+
theme: Theme;
1315

1416
constructor(
1517
@Inject(DOCUMENT)
@@ -19,31 +21,35 @@ export class ThemeModeToggleComponent implements OnInit {
1921
) {}
2022

2123
ngOnInit() {
22-
// This is commented out because by default the theme mode is set to light (at least for now)
23-
// const userPrefersTheme =
24-
// this.mediaMatcher.matchMedia &&
25-
// this.mediaMatcher.matchMedia('(prefers-color-scheme: light)').matches;
26-
// this.setThemeMode(this.getUserSettingsIsDarkMode() || userPrefersTheme);
27-
28-
const isDarkMode = this.getUserSettingsIsDarkMode();
29-
this.setThemeMode(isDarkMode);
24+
const preferredScheme = this.mediaMatcher.matchMedia(
25+
'(prefers-color-scheme: dark)',
26+
);
27+
28+
preferredScheme.onchange = () => {
29+
if (!this.getStoredTheme()) this.toggleTheme(true);
30+
};
31+
32+
const isDarkSchemePreferred = preferredScheme.matches;
33+
const storedTheme = this.getStoredTheme();
34+
35+
this.theme = storedTheme ?? (isDarkSchemePreferred ? 'dark' : 'light');
36+
this.setTheme(this.theme);
3037
}
3138

32-
toggleThemeMode() {
33-
const isDarkMode = !this.isDarkMode;
34-
this.storageService.set('theme-mode', isDarkMode.toString());
35-
this.setThemeMode(isDarkMode);
39+
toggleTheme(skipStorage = false) {
40+
this.theme = this.theme === 'dark' ? 'light' : 'dark';
41+
// NOTE: We should skip saving theme in storage when toggle is caused by matchMedia change event
42+
// Otherwise, once saved, it'll no longer correspond to the system preferences,
43+
// despite the user not touching the toggle button themselves
44+
if (!skipStorage) this.storageService.set('theme', this.theme);
45+
this.setTheme(this.theme);
3646
}
3747

38-
private getUserSettingsIsDarkMode(): boolean {
39-
return this.storageService.get('theme-mode') === 'true';
48+
private getStoredTheme() {
49+
return this.storageService.get('theme') as Theme | null;
4050
}
4151

42-
private setThemeMode(isDarkMode: boolean) {
43-
this.isDarkMode = isDarkMode;
44-
this.document.documentElement.setAttribute(
45-
'mode',
46-
isDarkMode ? 'dark' : 'light',
47-
);
52+
private setTheme(theme: Theme) {
53+
this.document.documentElement.setAttribute('mode', theme);
4854
}
4955
}

0 commit comments

Comments
 (0)