audiobookshelf/client/store/theme.js
Farhan ALVY af5ba658c3 Implement Dynamic Theme Switching (Dark/Light Mode)
This commit introduces a comprehensive theme system that allows users to seamlessly
switch between dark and light modes throughout the application.

🌟 Key Features:
• Toggle between dark and light themes with smooth transitions
• Automatic theme persistence using localStorage
• System preference detection for initial theme selection
• Comprehensive CSS variable system for consistent theming
• Theme-aware utility classes for easy component integration

🎨 What's Included:
• Theme Vuex store for state management and theme logic
• Complete CSS variable definitions for both light and dark modes
• Smooth 0.3s transitions for all theme-related properties
• Proper contrast ratios ensuring accessibility in both themes
• Support for all UI components including buttons, inputs, icons, and dropdowns

🚀 Developer Experience:
• Easy-to-use utility classes (.text-themed, .bg-primary, etc.)
• Centralized theme management through Vuex store
• Automatic document class updates (html.dark / html.light)
• No breaking changes to existing components

This enhancement significantly improves user experience by providing
visual comfort options and follows modern UI/UX best practices.
2025-10-08 08:19:21 +00:00

56 lines
1.7 KiB
JavaScript

export const state = () => ({
isDarkMode: true
})
export const mutations = {
setDarkMode(state, isDark) {
state.isDarkMode = isDark
},
toggleTheme(state) {
console.log('Is Dark Mode State', state.isDarkMode)
state.isDarkMode = !state.isDarkMode
}
}
export const actions = {
initializeTheme({ commit, dispatch }) {
// Check localStorage for saved theme preference
const savedTheme = localStorage.getItem('audiobookshelf_theme')
if (savedTheme) {
const isDark = savedTheme === 'dark'
commit('setDarkMode', isDark)
dispatch('applyTheme', isDark)
} else {
// Default to dark mode (matches your current app design)
// or check system preference: const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
commit('setDarkMode', true)
dispatch('applyTheme', true)
}
},
toggleTheme({ commit, state, dispatch }) {
const newTheme = !state.isDarkMode
commit('setDarkMode', newTheme)
localStorage.setItem('audiobookshelf_theme', newTheme ? 'dark' : 'light')
dispatch('applyTheme', newTheme)
},
applyTheme({}, isDark) {
// Apply theme class to document
if (isDark) {
document.documentElement.classList.add('dark')
document.documentElement.classList.remove('light')
} else {
document.documentElement.classList.add('light')
document.documentElement.classList.remove('dark')
}
// Update meta theme-color for mobile browsers
const metaThemeColor = document.querySelector('meta[name=theme-color]')
if (metaThemeColor) {
metaThemeColor.setAttribute('content', isDark ? '#232323' : '#ffffff')
}
}
}
export const getters = {
isDarkMode: (state) => state.isDarkMode
}