diff --git a/webapp/static/assets/js/color-mode-switcher.js b/webapp/static/assets/js/color-mode-switcher.js new file mode 100644 index 0000000..4367519 --- /dev/null +++ b/webapp/static/assets/js/color-mode-switcher.js @@ -0,0 +1,37 @@ +'use strict' +/* eslint-env browser */ + +/** + * Get user preferred theme from their past choice or browser + * @returns {String} User preferred theme + */ +function getPreferredTheme () { + const storedTheme = localStorage.getItem('theme') + if (storedTheme) { + return storedTheme + } + // Privacy-hardened browsers always return light + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' +} + +// Change body theme early to prevent flash +let currentTheme = getPreferredTheme() +document.documentElement.setAttribute('data-bs-theme', currentTheme) + +// On browser color-scheme change, update +window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { + currentTheme = getPreferredTheme() + document.documentElement.setAttribute('data-bs-theme', currentTheme) +}) + +window.addEventListener('load', () => { + // Toggle on T key, ignore input fields or key repeat + document.addEventListener('keydown', e => { + if (e.target.tagName !== 'INPUT' && !e.repeat && !e.ctrlKey && e.key === 't') { + currentTheme = currentTheme === 'light' ? 'dark' : 'light' + document.documentElement.setAttribute('data-bs-theme', currentTheme) + localStorage.setItem('theme', currentTheme) + e.preventDefault() + } + }) +}) diff --git a/webapp/templates/index.html b/webapp/templates/index.html index 0491646..0873d47 100644 --- a/webapp/templates/index.html +++ b/webapp/templates/index.html @@ -1,5 +1,5 @@ - +
@@ -11,6 +11,7 @@ + @@ -102,6 +103,7 @@