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.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs