VUE

useDarkMode Composable

Reactive dark mode toggle with system preference detection and localStorage persistence

Vue3ComposablesDarkModeThemeReactive

Code

import { ref, watch, onMounted, onUnmounted } from 'vue';

type ThemeMode = 'light' | 'dark' | 'system';

export function useDarkMode(): {
  isDark: Ref<boolean>;
  themeMode: Ref<ThemeMode>;
  toggleDarkMode: () => void;
  setThemeMode: (mode: ThemeMode) => void;
} {
  // Get stored theme mode or default to system
  const themeMode = ref<ThemeMode>(
    (localStorage.getItem('theme-mode') as ThemeMode) || 'system'
  );
  const isDark = ref(false);
  let mediaQuery: MediaQueryList | null = null;

  // Update dark mode based on theme mode and system preference
  const updateDarkMode = () => {
    __TOKEN_37__ (themeMode.value === 'system') {
      isDark.value = window.matchMedia('(prefers-color-scheme: dark)').matches;
    } else {
      isDark.value = themeMode.value === 'dark';
    }
    
    // Apply to document
    document.documentElement.classList.toggle('dark', isDark.value);
  };

  // Toggle dark/light mode
  const toggleDarkMode = () => {
    setThemeMode(isDark.value ? 'light' : 'dark');
  };

  // Set specific theme mode
  const setThemeMode = (mode: ThemeMode) => {
    themeMode.value = mode;
    localStorage.setItem('theme-mode', mode);
    updateDarkMode();
  };

  // Listen to system preference changes
  const handleSystemChange = () => {
    __TOKEN_42__ (themeMode.value === 'system') updateDarkMode();
  };

  onMounted(() => {
    mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
    mediaQuery.addEventListener('change', handleSystemChange);
    updateDarkMode();
  });

  onUnmounted(() => {
    __TOKEN_43__ (mediaQuery) {
      mediaQuery.removeEventListener('change', handleSystemChange);
    }
  });

  // Watch for theme mode changes
  watch(themeMode, updateDarkMode);

  return {
    isDark,
    themeMode,
    toggleDarkMode,
    setThemeMode
  };
}

// Usage example
// const { isDark, toggleDarkMode, setThemeMode } = useDarkMode();
// toggleDarkMode(); // Switch between light/dark
// setThemeMode('system'); // Use system preference