You've already forked wp-bootstrap
75 lines
2.7 KiB
JavaScript
75 lines
2.7 KiB
JavaScript
|
|
/**
|
||
|
|
* WP Bootstrap Dark Mode Toggle
|
||
|
|
*
|
||
|
|
* Handles dark mode switching using Bootstrap 5.3's data-bs-theme attribute.
|
||
|
|
* Respects prefers-color-scheme media query and persists choice in localStorage.
|
||
|
|
*
|
||
|
|
* @package WPBootstrap
|
||
|
|
* @since 0.1.0
|
||
|
|
*/
|
||
|
|
(function () {
|
||
|
|
'use strict';
|
||
|
|
|
||
|
|
var STORAGE_KEY = 'wp-bootstrap-theme';
|
||
|
|
var ATTR = 'data-bs-theme';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get the user's stored preference, or fall back to system preference.
|
||
|
|
*
|
||
|
|
* @return {string} 'dark' or 'light'
|
||
|
|
*/
|
||
|
|
function getPreferredTheme() {
|
||
|
|
var stored = localStorage.getItem(STORAGE_KEY);
|
||
|
|
if (stored) {
|
||
|
|
return stored;
|
||
|
|
}
|
||
|
|
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Apply the theme to the document and update all toggle buttons.
|
||
|
|
*
|
||
|
|
* @param {string} theme - 'dark' or 'light'
|
||
|
|
*/
|
||
|
|
function setTheme(theme) {
|
||
|
|
document.documentElement.setAttribute(ATTR, theme);
|
||
|
|
|
||
|
|
document.querySelectorAll('[data-bs-theme-toggle]').forEach(function (toggle) {
|
||
|
|
var isDark = theme === 'dark';
|
||
|
|
toggle.setAttribute('aria-label', isDark
|
||
|
|
? (toggle.dataset.labelLight || 'Switch to light mode')
|
||
|
|
: (toggle.dataset.labelDark || 'Switch to dark mode'));
|
||
|
|
toggle.setAttribute('aria-pressed', String(isDark));
|
||
|
|
|
||
|
|
var sunIcon = toggle.querySelector('.wp-bootstrap-sun-icon');
|
||
|
|
var moonIcon = toggle.querySelector('.wp-bootstrap-moon-icon');
|
||
|
|
if (sunIcon) sunIcon.style.display = isDark ? 'inline-block' : 'none';
|
||
|
|
if (moonIcon) moonIcon.style.display = isDark ? 'none' : 'inline-block';
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// Apply theme immediately to prevent flash.
|
||
|
|
setTheme(getPreferredTheme());
|
||
|
|
|
||
|
|
// When DOM is ready, re-apply for toggle buttons and attach event listeners.
|
||
|
|
document.addEventListener('DOMContentLoaded', function () {
|
||
|
|
setTheme(getPreferredTheme());
|
||
|
|
|
||
|
|
document.querySelectorAll('[data-bs-theme-toggle]').forEach(function (toggle) {
|
||
|
|
toggle.addEventListener('click', function () {
|
||
|
|
var currentTheme = document.documentElement.getAttribute(ATTR);
|
||
|
|
var newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
||
|
|
localStorage.setItem(STORAGE_KEY, newTheme);
|
||
|
|
setTheme(newTheme);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
// Listen for system preference changes when no stored preference exists.
|
||
|
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function (e) {
|
||
|
|
if (!localStorage.getItem(STORAGE_KEY)) {
|
||
|
|
setTheme(e.matches ? 'dark' : 'light');
|
||
|
|
}
|
||
|
|
});
|
||
|
|
})();
|