diff options
author | Alexander Neonxp Kiryukhin <i@neonxp.ru> | 2024-11-03 20:08:36 +0300 |
---|---|---|
committer | Alexander Neonxp Kiryukhin <i@neonxp.ru> | 2024-11-03 20:08:36 +0300 |
commit | 59c7d4567380d1a9c80e96eb958fdbdd512ce006 (patch) | |
tree | 65410cfc10dbc7d060ec23be110662d9b7f6b0e9 /themes/hugo-theme-stack/assets/ts/colorScheme.ts |
новая жизнь блога
Diffstat (limited to 'themes/hugo-theme-stack/assets/ts/colorScheme.ts')
-rw-r--r-- | themes/hugo-theme-stack/assets/ts/colorScheme.ts | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/themes/hugo-theme-stack/assets/ts/colorScheme.ts b/themes/hugo-theme-stack/assets/ts/colorScheme.ts new file mode 100644 index 0000000..978e98e --- /dev/null +++ b/themes/hugo-theme-stack/assets/ts/colorScheme.ts @@ -0,0 +1,92 @@ +type colorScheme = 'light' | 'dark' | 'auto'; + +class StackColorScheme { + private localStorageKey = 'StackColorScheme'; + private currentScheme: colorScheme; + private systemPreferScheme: colorScheme; + + constructor(toggleEl: HTMLElement) { + this.bindMatchMedia(); + this.currentScheme = this.getSavedScheme(); + if (window.matchMedia('(prefers-color-scheme: dark)').matches === true) + this.systemPreferScheme = 'dark' + else + this.systemPreferScheme = 'light'; + + this.dispatchEvent(document.documentElement.dataset.scheme as colorScheme); + + if (toggleEl) + this.bindClick(toggleEl); + + if (document.body.style.transition == '') + document.body.style.setProperty('transition', 'background-color .3s ease'); + } + + private saveScheme() { + localStorage.setItem(this.localStorageKey, this.currentScheme); + } + + private bindClick(toggleEl: HTMLElement) { + toggleEl.addEventListener('click', (e) => { + if (this.isDark()) { + /// Disable dark mode + this.currentScheme = 'light'; + } + else { + this.currentScheme = 'dark'; + } + + this.setBodyClass(); + + if (this.currentScheme == this.systemPreferScheme) { + /// Set to auto + this.currentScheme = 'auto'; + } + + this.saveScheme(); + }) + } + + private isDark() { + return (this.currentScheme == 'dark' || this.currentScheme == 'auto' && this.systemPreferScheme == 'dark'); + } + + private dispatchEvent(colorScheme: colorScheme) { + const event = new CustomEvent('onColorSchemeChange', { + detail: colorScheme + }); + window.dispatchEvent(event); + } + + private setBodyClass() { + if (this.isDark()) { + document.documentElement.dataset.scheme = 'dark'; + } + else { + document.documentElement.dataset.scheme = 'light'; + } + + this.dispatchEvent(document.documentElement.dataset.scheme as colorScheme); + } + + private getSavedScheme(): colorScheme { + const savedScheme = localStorage.getItem(this.localStorageKey); + + if (savedScheme == 'light' || savedScheme == 'dark' || savedScheme == 'auto') return savedScheme; + else return 'auto'; + } + + private bindMatchMedia() { + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => { + if (e.matches) { + this.systemPreferScheme = 'dark'; + } + else { + this.systemPreferScheme = 'light'; + } + this.setBodyClass(); + }); + } +} + +export default StackColorScheme; |