summaryrefslogtreecommitdiff
path: root/assets/js/theme-switcher.js
diff options
context:
space:
mode:
Diffstat (limited to 'assets/js/theme-switcher.js')
-rw-r--r--assets/js/theme-switcher.js101
1 files changed, 101 insertions, 0 deletions
diff --git a/assets/js/theme-switcher.js b/assets/js/theme-switcher.js
new file mode 100644
index 0000000..0cca832
--- /dev/null
+++ b/assets/js/theme-switcher.js
@@ -0,0 +1,101 @@
+/*
+ * Theme switcher
+ *
+ * Pico.css - https://picocss.com
+ * Copyright 2019-2022 - Licensed under MIT
+ */
+
+const themeSwitcher = {
+ // Config
+ _scheme: 'auto',
+ change: {
+ light: '<i>Turn on dark mode</i>',
+ dark: '<i>Turn off dark mode</i>',
+ },
+ buttonsTarget: '.theme-switcher',
+ localStorageKey: 'picoPreferedColorScheme',
+
+ // Init
+ init() {
+ this.scheme = this.schemeFromLocalStorage;
+ this.initSwitchers();
+ },
+
+ // Get color scheme from local storage
+ get schemeFromLocalStorage() {
+ if (typeof window.localStorage !== 'undefined') {
+ if (window.localStorage.getItem(this.localStorageKey) !== null) {
+ return window.localStorage.getItem(this.localStorageKey);
+ }
+ }
+ return this._scheme;
+ },
+
+ // Prefered color scheme
+ get preferedColorScheme() {
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
+ },
+
+ // Init switchers
+ initSwitchers() {
+ const buttons = document.querySelectorAll(this.buttonsTarget);
+ buttons.forEach(button => {
+ button.addEventListener('click', () => {
+ this.scheme == 'dark' ? this.scheme = 'light' : this.scheme = 'dark';
+ }, false);
+ });
+ },
+
+ // Add new button
+ addButton(config) {
+ let button = document.createElement(config.tag);
+ button.className = config.class;
+ document.querySelector(config.target).appendChild(button);
+ },
+
+ // Set scheme
+ set scheme(scheme) {
+ if (scheme == 'auto') {
+ this.preferedColorScheme == 'dark' ? this._scheme = 'dark' : this._scheme = 'light';
+ }
+ else if (scheme == 'dark' || scheme == 'light') {
+ this._scheme = scheme;
+ }
+ this.applyScheme();
+ this.schemeToLocalStorage();
+ },
+
+ // Get scheme
+ get scheme() {
+ return this._scheme;
+ },
+
+ // Apply scheme
+ applyScheme() {
+ document.querySelector('html').setAttribute('data-theme', this.scheme);
+ const buttons = document.querySelectorAll(this.buttonsTarget);
+ buttons.forEach(
+ button => {
+ const text = this.scheme == 'dark' ? this.change.dark : this.change.light;
+ button.innerHTML = text;
+ button.setAttribute('aria-label', text.replace(/<[^>]*>?/gm, ''));
+ }
+ );
+ },
+
+ // Store scheme to local storage
+ schemeToLocalStorage() {
+ if (typeof window.localStorage !== 'undefined') {
+ window.localStorage.setItem(this.localStorageKey, this.scheme);
+ }
+ },
+};
+
+window.addEventListener('load', function () {
+ themeSwitcher.addButton({
+ tag: 'BUTTON',
+ class: 'contrast switcher theme-switcher',
+ target: 'body',
+ });
+ themeSwitcher.init();
+});