// SPDX-License-Identifier: MIT /** Doxygen Awesome https://github.com/jothepro/doxygen-awesome-css Copyright (c) 2021 - 2025 jothepro */ class DoxygenAwesomeDarkModeToggle extends HTMLElement { // SVG icons from https://fonts.google.com/icons // Licensed under the Apache 2.0 license: // https://www.apache.org/licenses/LICENSE-2.0.html static lightModeIcon = `` static darkModeIcon = `` static title = "Toggle Light/Dark Mode" static prefersLightModeInDarkModeKey = "prefers-light-mode-in-dark-mode" static prefersDarkModeInLightModeKey = "prefers-dark-mode-in-light-mode" static _staticConstructor = function() { DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.userPreference) // Update the color scheme when the browsers preference changes // without user interaction on the website. window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged() }) // Update the color scheme when the tab is made visible again. // It is possible that the appearance was changed in another tab // while this tab was in the background. document.addEventListener("visibilitychange", visibilityState => { if (document.visibilityState === 'visible') { DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged() } }); }() static init() { const toggleSelector = 'doxygen-awesome-dark-mode-toggle' const existingToggle = document.querySelector(toggleSelector) const toggleButton = existingToggle || document.createElement(toggleSelector) if (!existingToggle) { toggleButton.title = DoxygenAwesomeDarkModeToggle.title toggleButton.updateIcon() window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { toggleButton.updateIcon() }) document.addEventListener("visibilitychange", () => { if (document.visibilityState === 'visible') { toggleButton.updateIcon() } }); } const moveToggle = () => { const searchBox = document.getElementById("MSearchBox") const toggle = document.querySelector(toggleSelector) || toggleButton if (searchBox && searchBox.parentNode !== toggle.parentNode) { searchBox.parentNode.appendChild(toggle) } } const containsSearchBox = node => { return node.nodeType === Node.ELEMENT_NODE && (node.id === "MSearchBox" || node.querySelector("#MSearchBox") !== null) } const observer = new MutationObserver(mutations => { const searchBoxChanged = mutations.some(mutation => [...mutation.addedNodes, ...mutation.removedNodes] .some(containsSearchBox) ) if (searchBoxChanged) { moveToggle() } }) observer.observe(document.documentElement, { childList: true, subtree: true }) moveToggle() } constructor() { super(); this.onclick=this.toggleDarkMode } /** * @returns `true` for dark-mode, `false` for light-mode system preference */ static get systemPreference() { return window.matchMedia('(prefers-color-scheme: dark)').matches } /** * @returns `true` for dark-mode, `false` for light-mode user preference */ static get userPreference() { return (!DoxygenAwesomeDarkModeToggle.systemPreference && localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)) || (DoxygenAwesomeDarkModeToggle.systemPreference && !localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey)) } static set userPreference(userPreference) { DoxygenAwesomeDarkModeToggle.darkModeEnabled = userPreference if(!userPreference) { if(DoxygenAwesomeDarkModeToggle.systemPreference) { localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey, true) } else { localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey) } } else { if(!DoxygenAwesomeDarkModeToggle.systemPreference) { localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey, true) } else { localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey) } } DoxygenAwesomeDarkModeToggle.onUserPreferenceChanged() } static enableDarkMode(enable) { if(enable) { DoxygenAwesomeDarkModeToggle.darkModeEnabled = true document.documentElement.classList.add("dark-mode") document.documentElement.classList.remove("light-mode") } else { DoxygenAwesomeDarkModeToggle.darkModeEnabled = false document.documentElement.classList.remove("dark-mode") document.documentElement.classList.add("light-mode") } } static onSystemPreferenceChanged() { DoxygenAwesomeDarkModeToggle.darkModeEnabled = DoxygenAwesomeDarkModeToggle.userPreference DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled) } static onUserPreferenceChanged() { DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled) } toggleDarkMode() { DoxygenAwesomeDarkModeToggle.userPreference = !DoxygenAwesomeDarkModeToggle.userPreference this.updateIcon() } updateIcon() { if(DoxygenAwesomeDarkModeToggle.darkModeEnabled) { this.innerHTML = DoxygenAwesomeDarkModeToggle.darkModeIcon } else { this.innerHTML = DoxygenAwesomeDarkModeToggle.lightModeIcon } } } customElements.define("doxygen-awesome-dark-mode-toggle", DoxygenAwesomeDarkModeToggle);