]> git.openstreetmap.org Git - nominatim-ui.git/blob - src/color-mode-toggler.js
Merge remote-tracking branch 'upstream/master'
[nominatim-ui.git] / src / color-mode-toggler.js
1 /*!
2  * https://getbootstrap.com/docs/5.3/customize/color-modes/#javascript
3  *
4  * Color mode toggler for Bootstrap's docs (https://getbootstrap.com/)
5  * Copyright 2011-2025 The Bootstrap Authors
6  * Licensed under the Creative Commons Attribution 3.0 Unported License.
7  */
8
9 export function initColorToggler() {
10
11   const getStoredTheme = () => localStorage.getItem('theme')
12   const setStoredTheme = theme => localStorage.setItem('theme', theme)
13
14   const getPreferredTheme = () => {
15     const storedTheme = getStoredTheme()
16     if (storedTheme) {
17       return storedTheme
18     }
19
20     return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
21   }
22
23   const setTheme = theme => {
24     if (theme === 'auto') {
25       document.documentElement.setAttribute('data-bs-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'))
26     } else {
27       document.documentElement.setAttribute('data-bs-theme', theme)
28     }
29   }
30
31   setTheme(getPreferredTheme())
32
33   const showActiveTheme = (theme, focus = false) => {
34     const themeSwitcher = document.querySelector('#bd-theme')
35
36     if (!themeSwitcher) {
37       return
38     }
39
40     const themeSwitcherText = document.querySelector('#bd-theme-text')
41     // const activeThemeIcon = document.querySelector('.theme-icon-active use')
42     const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`)
43     // const svgOfActiveBtn = btnToActive.querySelector('svg use').getAttribute('href')
44
45     document.querySelectorAll('[data-bs-theme-value]').forEach(element => {
46       element.classList.remove('active')
47       element.setAttribute('aria-pressed', 'false')
48     })
49
50     btnToActive.classList.add('active')
51     btnToActive.setAttribute('aria-pressed', 'true')
52     // activeThemeIcon.setAttribute('href', svgOfActiveBtn)
53     const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`
54     themeSwitcher.setAttribute('aria-label', themeSwitcherLabel)
55
56     if (focus) {
57       themeSwitcher.focus()
58     }
59   }
60
61   window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
62     const storedTheme = getStoredTheme()
63     if (storedTheme !== 'light' && storedTheme !== 'dark') {
64       setTheme(getPreferredTheme())
65     }
66   })
67
68   showActiveTheme(getPreferredTheme())
69
70   document.querySelectorAll('[data-bs-theme-value]')
71     .forEach(toggle => {
72       toggle.addEventListener('click', () => {
73         const theme = toggle.getAttribute('data-bs-theme-value')
74         setStoredTheme(theme)
75         setTheme(theme)
76         showActiveTheme(theme, true)
77       })
78     })
79 }