Les boutons suivent la couleur d’apparence, les libellés trop petits ou trop techniques sont clarifiés, et le catalogue des fournisseurs se met à jour tout seul. Co-authored-by: Cursor <cursoragent@cursor.com>
81 lines
2.8 KiB
TypeScript
81 lines
2.8 KiB
TypeScript
'use client'
|
|
|
|
import { useLayoutEffect } from 'react'
|
|
import { applyDocumentTheme, normalizeThemeId, persistThemePreference } from '@/lib/apply-document-theme'
|
|
|
|
interface ThemeInitializerProps {
|
|
theme?: string
|
|
fontSize?: string
|
|
fontFamily?: string
|
|
accentColor?: string
|
|
}
|
|
|
|
export function ThemeInitializer({ theme, fontSize, fontFamily, accentColor }: ThemeInitializerProps) {
|
|
// useLayoutEffect : avant le paint (useEffect = trop tard = flash clair)
|
|
useLayoutEffect(() => {
|
|
const root = document.documentElement
|
|
|
|
const applyFontSize = (s?: string) => {
|
|
const size = s || 'medium'
|
|
|
|
const fontSizeMap: Record<string, string> = {
|
|
small: '14px',
|
|
medium: '16px',
|
|
large: '18px',
|
|
'extra-large': '20px',
|
|
}
|
|
|
|
const fontSizeFactorMap: Record<string, number> = {
|
|
small: 0.95,
|
|
medium: 1.0,
|
|
large: 1.1,
|
|
'extra-large': 1.25,
|
|
}
|
|
|
|
root.style.setProperty('--user-font-size', fontSizeMap[size] || '16px')
|
|
root.style.setProperty('--user-font-size-factor', (fontSizeFactorMap[size] || 1).toString())
|
|
}
|
|
|
|
// Préférence locale prioritaire (jamais écrasée par un rendu serveur « light »)
|
|
const localTheme = localStorage.getItem('theme-preference')
|
|
const effectiveTheme = normalizeThemeId(localTheme || theme || 'light')
|
|
|
|
// Appliquer le thème AVANT paint (cookie + class dark atomique)
|
|
applyDocumentTheme(effectiveTheme)
|
|
persistThemePreference(effectiveTheme)
|
|
|
|
// color-scheme navigateur (inputs, scrollbars) — évite flash chrome clair
|
|
try {
|
|
const dark =
|
|
effectiveTheme === 'dark' ||
|
|
effectiveTheme === 'midnight' ||
|
|
(effectiveTheme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
|
root.style.colorScheme = dark ? 'dark' : 'light'
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
|
|
applyFontSize(fontSize)
|
|
|
|
const localFontFamily = localStorage.getItem('font-family')
|
|
const effectiveFontFamily = localFontFamily || fontFamily || 'inter'
|
|
root.classList.remove('font-system', 'font-playfair', 'font-jetbrains')
|
|
if (effectiveFontFamily === 'system') root.classList.add('font-system')
|
|
if (effectiveFontFamily === 'playfair') root.classList.add('font-playfair')
|
|
if (effectiveFontFamily === 'jetbrains') root.classList.add('font-jetbrains')
|
|
if (!localFontFamily && fontFamily) {
|
|
localStorage.setItem('font-family', fontFamily)
|
|
}
|
|
|
|
const localAccent = localStorage.getItem('accent-color')
|
|
const serverAccent = accentColor || null
|
|
const effectiveAccent = serverAccent || localAccent || '#A47148'
|
|
root.style.setProperty('--color-brand-accent', effectiveAccent)
|
|
if (serverAccent && localAccent !== serverAccent) {
|
|
localStorage.setItem('accent-color', serverAccent)
|
|
}
|
|
}, [theme, fontSize, fontFamily, accentColor])
|
|
|
|
return null
|
|
}
|