Files
fheroes2/docs/assets/js/theme-toggle.js
T

122 lines
5.3 KiB
JavaScript

/***************************************************************************
* fheroes2: https://github.com/ihhub/fheroes2 *
* Copyright (C) 2025 *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
// Theme toggle functionality
class ThemeManager
{
constructor()
{
this.themeToggle = document.getElementById( "theme-toggle" );
this.themeKey = "theme";
this.darkTheme = "dark";
this.lightTheme = "light";
this.accessibility = window.AccessibilityManager ? new window.AccessibilityManager() : null;
this.init();
}
init()
{
this.applySavedTheme();
this.setupEventListeners();
this.setupAccessibility();
}
setTheme( theme, saveToStorage = true )
{
document.documentElement.setAttribute( "data-theme", theme );
document.body.setAttribute( "data-theme", theme );
// Only save to localStorage if explicitly requested
if ( saveToStorage ) {
localStorage.setItem( this.themeKey, theme );
}
// Update button text and ARIA attributes
if ( this.themeToggle ) {
this.themeToggle.textContent = theme === this.darkTheme ? "☀️ Light Mode" : "🌙 Dark Mode";
// Update ARIA attributes
this.themeToggle.setAttribute( "aria-label", `Switch to ${theme === this.darkTheme ? this.lightTheme : this.darkTheme} mode` );
this.themeToggle.setAttribute( "aria-pressed", theme === this.darkTheme ? "true" : "false" );
// Announce theme change if accessibility manager is available
if ( this.accessibility ) {
this.accessibility.announce( `${theme === this.darkTheme ? 'Dark' : 'Light'} mode activated` );
}
}
}
applySavedTheme()
{
const savedTheme = localStorage.getItem( this.themeKey );
if ( savedTheme ) {
this.setTheme( savedTheme );
}
else {
// Check system preference but don't save it to localStorage
const prefersDark = window.matchMedia( "(prefers-color-scheme: dark)" ).matches;
this.setTheme( prefersDark ? this.darkTheme : this.lightTheme, false );
}
}
setupEventListeners()
{
// Add event listener to the toggle button
if ( this.themeToggle ) {
this.themeToggle.addEventListener( "click", () => {
const currentTheme = document.documentElement.getAttribute( "data-theme" );
this.setTheme( currentTheme === this.darkTheme ? this.lightTheme : this.darkTheme );
} );
}
// Listen for system theme changes
window.matchMedia( "(prefers-color-scheme: dark)" ).addEventListener( "change", ( e ) => {
// Only apply system preference if user hasn't manually set a preference
if ( !localStorage.getItem( this.themeKey ) ) {
this.setTheme( e.matches ? this.darkTheme : this.lightTheme, false );
}
} );
}
setupAccessibility()
{
if ( this.themeToggle ) {
// Set initial ARIA attributes
const currentTheme = document.documentElement.getAttribute( "data-theme" );
this.themeToggle.setAttribute( "aria-label", `Switch to ${currentTheme === this.darkTheme ? this.lightTheme : this.darkTheme} mode` );
this.themeToggle.setAttribute( "aria-pressed", currentTheme === this.darkTheme ? "true" : "false" );
// Add keyboard event handling
this.themeToggle.addEventListener( "keydown", ( event ) => {
if ( event.key === "Enter" || event.key === " " ) {
event.preventDefault();
const currentTheme = document.documentElement.getAttribute( "data-theme" );
this.setTheme( currentTheme === this.darkTheme ? this.lightTheme : this.darkTheme );
}
} );
}
}
}
// Initialize the theme manager when the DOM is loaded
document.addEventListener( "DOMContentLoaded", () => { new ThemeManager(); } );