JAVASCRIPT
Vue 3 Custom Composable for Dark Mode Toggling
Create a reusable Vue 3 composable to manage dark mode state, persist user preference in localStorage, and dynamically apply a 'dark' class to the document body.
// src/composables/useDarkTheme.js
import { ref, watch, onMounted } from 'vue';
export function useDarkTheme() {
const isDark = ref(false);
const STORAGE_KEY = 'vue-dark-theme';
// Watch for changes in isDark and update localStorage/body class
watch(isDark, (newValue) => {
if (newValue) {
document.documentElement.classList.add('dark');
localStorage.setItem(STORAGE_KEY, 'true');
} else {
document.documentElement.classList.remove('dark');
localStorage.setItem(STORAGE_KEY, 'false');
}
}, { immediate: true }); // Run immediately on component mount
// On mount, check localStorage for preferred theme
onMounted(() => {
const storedPreference = localStorage.getItem(STORAGE_KEY);
if (storedPreference === 'true') {
isDark.value = true;
} else if (storedPreference === 'false') {
isDark.value = false;
} else {
// No preference, check system preference
isDark.value = window.matchMedia('(prefers-color-scheme: dark)').matches;
}
});
const toggleDark = () => {
isDark.value = !isDark.value;
};
return { isDark, toggleDark };
}
// src/App.vue
<script setup>
import { useDarkTheme } from './composables/useDarkTheme';
const { isDark, toggleDark } = useDarkTheme();
</script>
<template>
<div :class="{ 'bg-gray-100 text-gray-900': !isDark, 'bg-gray-900 text-gray-100': isDark }" class="min-h-screen p-8 transition-colors duration-300">
<h1 class="text-3xl font-bold mb-4">My Awesome App</h1>
<p>Current theme: {{ isDark ? 'Dark' : 'Light' }}</p>
<button @click="toggleDark" class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors">
Toggle Dark Mode
</button>
<p class="mt-4">This is some content that adapts to the theme.</p>
</div>
</template>
<!-- In your main CSS (e.g., index.css or main.css) -->
<!-- You would typically define your dark mode styles based on the .dark class on html -->
<!-- Example with Tailwind CSS setup: -->
<!-- tailwind.config.js: { darkMode: 'class', ... } -->
<!-- css: -->
<!-- html.dark .your-element { background-color: #333; color: #eee; } -->
How it works: This Vue 3 composable provides a robust solution for managing dark mode. It utilizes `ref` for reactive state, `watch` to persist the user's preference in `localStorage` and toggle a 'dark' class on the `document.documentElement` (html tag), and `onMounted` to initialize the theme based on stored preference or system settings. This makes the dark mode logic reusable across any component, keeping your codebase clean and organized.