All files / js/composables useAppearance.ts

71.05% Statements 27/38
42.85% Branches 9/21
88.88% Functions 8/9
71.05% Lines 27/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100          4x       4x                     4x       1x 1x       1x   1x     1x 1x       1x     1x 1x       1x     1x             1x         1x 1x     1x     1x     1x 1x       1x           1x     1x     1x   1x     1x          
import { onMounted, ref } from 'vue';
 
type Appearance = 'light' | 'dark' | 'system';
 
export function updateTheme(value: Appearance) {
    Iif (typeof window === 'undefined') {
        return;
    }
 
    Iif (value === 'system') {
        const mediaQueryList = window.matchMedia(
            '(prefers-color-scheme: dark)',
        );
        const systemTheme = mediaQueryList.matches ? 'dark' : 'light';
 
        document.documentElement.classList.toggle(
            'dark',
            systemTheme === 'dark',
        );
    } else {
        document.documentElement.classList.toggle('dark', value === 'dark');
    }
}
 
const setCookie = (name: string, value: string, days = 365) => {
    Iif (typeof document === 'undefined') {
        return;
    }
 
    const maxAge = days * 24 * 60 * 60;
 
    document.cookie = `${name}=${value};path=/;max-age=${maxAge};SameSite=Lax`;
};
 
const mediaQuery = () => {
    Iif (typeof window === 'undefined') {
        return null;
    }
 
    return window.matchMedia('(prefers-color-scheme: dark)');
};
 
const getStoredAppearance = () => {
    Iif (typeof window === 'undefined') {
        return null;
    }
 
    return localStorage.getItem('appearance') as Appearance | null;
};
 
const handleSystemThemeChange = () => {
    const currentAppearance = getStoredAppearance();
 
    updateTheme(currentAppearance || 'system');
};
 
export function initializeTheme() {
    Iif (typeof window === 'undefined') {
        return;
    }
 
    // Initialize theme from saved preference or default to system...
    const savedAppearance = getStoredAppearance();
    updateTheme(savedAppearance || 'system');
 
    // Set up system theme change listener...
    mediaQuery()?.addEventListener('change', handleSystemThemeChange);
}
 
const appearance = ref<Appearance>('system');
 
export function useAppearance() {
    onMounted(() => {
        const savedAppearance = localStorage.getItem(
            'appearance',
        ) as Appearance | null;
 
        Iif (savedAppearance) {
            appearance.value = savedAppearance;
        }
    });
 
    function updateAppearance(value: Appearance) {
        appearance.value = value;
 
        // Store in localStorage for client-side persistence...
        localStorage.setItem('appearance', value);
 
        // Store in cookie for SSR...
        setCookie('appearance', value);
 
        updateTheme(value);
    }
 
    return {
        appearance,
        updateAppearance,
    };
}