feat(i18n): Complete localization of marketing frontend with react-i18next, prefixed URLs, JSON migrations, and automation
This commit is contained in:
68
resources/js/hooks/use-appearance.ts
Normal file
68
resources/js/hooks/use-appearance.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
type Appearance = 'light' | 'dark' | 'system';
|
||||
|
||||
export function useAppearance(): { appearance: Appearance; updateAppearance: (mode: Appearance) => void } {
|
||||
const [appearance, setAppearance] = useState<Appearance>('system');
|
||||
|
||||
useEffect(() => {
|
||||
const stored = localStorage.getItem('theme') as Appearance | null;
|
||||
if (stored) {
|
||||
setAppearance(stored);
|
||||
} else {
|
||||
setAppearance('system');
|
||||
}
|
||||
}, []);
|
||||
|
||||
const updateAppearance = (mode: Appearance) => {
|
||||
setAppearance(mode);
|
||||
localStorage.setItem('theme', mode);
|
||||
if (mode === 'dark') {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (appearance === 'system') {
|
||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
if (mediaQuery.matches) {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
const listener = (e: MediaQueryListEvent) => {
|
||||
if (e.matches) {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
};
|
||||
mediaQuery.addEventListener('change', listener);
|
||||
return () => mediaQuery.removeEventListener('change', listener);
|
||||
} else if (appearance === 'dark') {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
}, [appearance]);
|
||||
|
||||
return { appearance, updateAppearance };
|
||||
}
|
||||
|
||||
export function initializeTheme() {
|
||||
const stored = localStorage.getItem('theme') as Appearance | null;
|
||||
if (stored) {
|
||||
if (stored === 'dark') {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
} else {
|
||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
if (mediaQuery.matches) {
|
||||
document.documentElement.classList.add('dark');
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user