Wire guest branding theme

This commit is contained in:
Codex Agent
2026-01-15 08:06:21 +01:00
parent 53096fbf29
commit a1f37bb491
14 changed files with 478 additions and 123 deletions

View File

@@ -160,48 +160,32 @@ function applyThemeMode(mode: EventBranding['mode']) {
}
const root = document.documentElement;
const prefersDark = typeof window !== 'undefined'
const prefersDark = typeof window !== 'undefined' && typeof window.matchMedia === 'function'
? window.matchMedia('(prefers-color-scheme: dark)').matches
: false;
let storedTheme: 'light' | 'dark' | 'system' | null = null;
try {
const raw = localStorage.getItem('theme');
storedTheme = raw === 'light' || raw === 'dark' || raw === 'system' ? raw : null;
} catch {
storedTheme = null;
}
const applyDark = () => root.classList.add('dark');
const applyLight = () => root.classList.remove('dark');
if (mode === 'dark') {
applyDark();
root.style.colorScheme = 'dark';
return;
}
if (mode === 'light') {
applyLight();
return;
}
if (storedTheme === 'dark') {
applyDark();
return;
}
if (storedTheme === 'light') {
applyLight();
root.style.colorScheme = 'light';
return;
}
if (prefersDark) {
applyDark();
root.style.colorScheme = 'dark';
return;
}
applyLight();
root.style.colorScheme = 'light';
}
export function EventBrandingProvider({
@@ -214,6 +198,9 @@ export function EventBrandingProvider({
const resolved = useMemo(() => resolveBranding(branding), [branding]);
useEffect(() => {
if (typeof document !== 'undefined') {
document.documentElement.classList.add('guest-theme');
}
applyCssVariables(resolved);
const previousDark = typeof document !== 'undefined' ? document.documentElement.classList.contains('dark') : false;
applyThemeMode(resolved.mode ?? 'auto');
@@ -225,6 +212,7 @@ export function EventBrandingProvider({
} else {
document.documentElement.classList.remove('dark');
}
document.documentElement.classList.remove('guest-theme');
}
resetCssVariables();
applyCssVariables(DEFAULT_EVENT_BRANDING);

View File

@@ -0,0 +1,40 @@
import React from 'react';
import { render, waitFor } from '@testing-library/react';
import { EventBrandingProvider } from '../EventBrandingContext';
import type { EventBranding } from '../../types/event-branding';
const sampleBranding: EventBranding = {
primaryColor: '#ff3366',
secondaryColor: '#ff99aa',
backgroundColor: '#fef2f2',
fontFamily: 'Montserrat, sans-serif',
logoUrl: null,
mode: 'dark',
};
describe('EventBrandingProvider', () => {
afterEach(() => {
document.documentElement.classList.remove('guest-theme', 'dark');
document.documentElement.style.removeProperty('color-scheme');
document.documentElement.style.removeProperty('--guest-background');
});
it('applies guest theme classes and variables', async () => {
const { unmount } = render(
<EventBrandingProvider branding={sampleBranding}>
<div>Guest</div>
</EventBrandingProvider>
);
await waitFor(() => {
expect(document.documentElement.classList.contains('guest-theme')).toBe(true);
expect(document.documentElement.classList.contains('dark')).toBe(true);
expect(document.documentElement.style.colorScheme).toBe('dark');
expect(document.documentElement.style.getPropertyValue('--guest-background')).toBe(sampleBranding.backgroundColor);
});
unmount();
expect(document.documentElement.classList.contains('guest-theme')).toBe(false);
});
});