diff --git a/assets/scripts/features/index.js b/assets/scripts/features/index.js index 9682acf03..9e4fb4ffe 100644 --- a/assets/scripts/features/index.js +++ b/assets/scripts/features/index.js @@ -10,6 +10,10 @@ if (process.env.FEATURE_DARKMODE === '1') { import('./darkmode') } +if (process.env.FEATURE_THEME === '1') { + import('./theme') +} + if (process.env.FEATURE_FLOWCHART === '1') { import('./flowchart') } diff --git a/assets/scripts/features/theme/index.js b/assets/scripts/features/theme/index.js new file mode 100644 index 000000000..3d7ae0830 --- /dev/null +++ b/assets/scripts/features/theme/index.js @@ -0,0 +1,88 @@ +import * as params from '@params'; +const PERSISTENCE_KEY = 'theme-scheme' + +const themeOptions = params.theme || {} +const THEME_DARK = typeof themeOptions.dark === 'undefined' ? true : themeOptions.dark; +const THEME_LIGHT = typeof themeOptions.light === 'undefined' ? true : themeOptions.light; +const THEME_DEFAULT = typeof themeOptions.default === 'undefined' ? "system" : themeOptions.default; + +window.addEventListener('load', async () => { + const menu = document.getElementById('themeMenu') + const $icon = document.getElementById('navbar-theme-icon-svg') + if (menu == null || $icon == null) return + + const btns = menu.getElementsByTagName('a') + const iconMap = Array.from(btns).reduce((map, btn) => { + const $img = btn.getElementsByTagName('img')[0] + map[btn.dataset.scheme] = $img.src + return map + }, {}) + + + function checkScheme(scheme) { + if (THEME_LIGHT === false) return "dark" + if (THEME_DARK === false) return "light" + return scheme + } + + function loadScheme() { + return localStorage.getItem(PERSISTENCE_KEY) || loadDefaultScheme() + } + + function loadDefaultScheme() { + return THEME_DEFAULT || "system" + } + + function saveScheme(scheme) { + localStorage.setItem(PERSISTENCE_KEY, scheme) + } + + function getPreferredColorScheme() { + const isDarkMode = window.matchMedia("(prefers-color-scheme: dark)").matches; + return isDarkMode ? "dark" : "light"; + } + + function setScheme(newScheme) { + let theme = newScheme + if (newScheme === 'system') { + theme = getPreferredColorScheme() + } + // set data-theme attribute on html tag + document.querySelector("html").dataset.theme = theme; + + // update icon + $icon.src = iconMap[newScheme] + + // save preference to local storage + saveScheme(newScheme) + + setImages(theme) + } + + const checkedScheme = checkScheme(loadScheme()) + setScheme(checkedScheme) + + Array.from(menu.getElementsByTagName('a')).forEach((btn) => { + btn.addEventListener('click', () => { + const { scheme } = btn.dataset + setScheme(scheme) + }) + }) +}) + +function setImages(newScheme) { + const els = Array.from(document.getElementsByClassName('logo-holder')); + for (const el of els) { + const light = el.querySelector('.light-logo'); + const dark = el.querySelector('.dark-logo'); + + if (newScheme === "dark" && dark !== null) { + if (light !== null) light.style.display = 'none' + dark.style.display = 'inline' + } + else { + if (light !== null) light.style.display = 'inline' + if (dark !== null) dark.style.display = 'none' + } + } +} \ No newline at end of file diff --git a/exampleSite/hugo.yaml b/exampleSite/hugo.yaml index 88b75b825..65ca04c75 100644 --- a/exampleSite/hugo.yaml +++ b/exampleSite/hugo.yaml @@ -91,9 +91,19 @@ params: # Configure various features of this theme features: - # Enable dark theme - darkMode: + # [Deprecated] Enable dark theme + # This is a deprecated setting, but has not been removed to maintain backward compatibility + # If `theme` is set, the `darkMode` setting will be discarded. + # darkMode: + # enable: true + + # Configure theme color settings + theme: enable: true + services: + light: true # enable light theme. default "true" + dark: true # enable dark theme. default "true" + default: system # can be either light, dark or system. default "system" # Enable and configure portfolio portfolio: diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html index 65f636457..dc1850a3b 100644 --- a/layouts/_default/baseof.html +++ b/layouts/_default/baseof.html @@ -12,7 +12,7 @@ {{- partial "analytics.html" . -}}