summaryrefslogtreecommitdiff
path: root/assets/js/theme-switcher.js
blob: f2e58f6e4681163ecbe516846c333f6ffab92851 (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*
 * 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);
    }
  },
};

themeSwitcher.addButton({
  tag: 'BUTTON',
  class: 'contrast switcher theme-switcher',
  target: 'body',
});
themeSwitcher.init();