Files
fotospiel-app/resources/js/guest/lib/guestTheme.ts
2026-01-15 08:06:21 +01:00

104 lines
2.9 KiB
TypeScript

export type GuestThemePayload = {
primary: string;
secondary: string;
background: string;
surface: string;
mode?: 'light' | 'dark' | 'auto';
};
type GuestThemeCleanup = () => void;
const prefersDarkScheme = (): boolean => {
if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {
return false;
}
return window.matchMedia('(prefers-color-scheme: dark)').matches;
};
const applyColorScheme = (root: HTMLElement, theme: 'light' | 'dark') => {
if (theme === 'dark') {
root.classList.add('dark');
root.style.colorScheme = 'dark';
} else {
root.classList.remove('dark');
root.style.colorScheme = 'light';
}
};
export function applyGuestTheme(payload: GuestThemePayload): GuestThemeCleanup {
if (typeof document === 'undefined') {
return () => {};
}
const root = document.documentElement;
const hadGuestTheme = root.classList.contains('guest-theme');
const wasDark = root.classList.contains('dark');
const previousColorScheme = root.style.colorScheme;
const previousVars = {
primary: root.style.getPropertyValue('--guest-primary'),
secondary: root.style.getPropertyValue('--guest-secondary'),
background: root.style.getPropertyValue('--guest-background'),
surface: root.style.getPropertyValue('--guest-surface'),
};
root.classList.add('guest-theme');
root.style.setProperty('--guest-primary', payload.primary);
root.style.setProperty('--guest-secondary', payload.secondary);
root.style.setProperty('--guest-background', payload.background);
root.style.setProperty('--guest-surface', payload.surface);
const mode = payload.mode ?? 'auto';
if (mode === 'dark') {
applyColorScheme(root, 'dark');
} else if (mode === 'light') {
applyColorScheme(root, 'light');
} else {
applyColorScheme(root, prefersDarkScheme() ? 'dark' : 'light');
}
return () => {
if (hadGuestTheme) {
root.classList.add('guest-theme');
} else {
root.classList.remove('guest-theme');
}
if (wasDark) {
root.classList.add('dark');
} else {
root.classList.remove('dark');
}
if (previousColorScheme) {
root.style.colorScheme = previousColorScheme;
} else {
root.style.removeProperty('color-scheme');
}
if (previousVars.primary) {
root.style.setProperty('--guest-primary', previousVars.primary);
} else {
root.style.removeProperty('--guest-primary');
}
if (previousVars.secondary) {
root.style.setProperty('--guest-secondary', previousVars.secondary);
} else {
root.style.removeProperty('--guest-secondary');
}
if (previousVars.background) {
root.style.setProperty('--guest-background', previousVars.background);
} else {
root.style.removeProperty('--guest-background');
}
if (previousVars.surface) {
root.style.setProperty('--guest-surface', previousVars.surface);
} else {
root.style.removeProperty('--guest-surface');
}
};
}