# Design-Dokument – System-Theme-Erkennung (Light/Dark Mode) ## Übersicht Dieses Feature integriert die bereits installierte Bibliothek `next-themes` (v0.3.0) in die bestehende React + Vite + Tailwind + shadcn/ui-Webseite, um eine automatische Erkennung des Betriebssystem-Themes (hell/dunkel) sowie manuelles Umschalten zu ermöglichen. Aktuell definiert `:root` in `src/index.css` das dunkle Farbschema. Es existiert zwar ein `.dark`-Block, dieser wird aber nicht aktiv genutzt. Die Tailwind-Konfiguration verwendet bereits `darkMode: ["class"]`, was perfekt mit `next-themes` zusammenarbeitet. Kernentscheidungen: - `next-themes` wird als ThemeProvider eingesetzt (bereits als Dependency vorhanden, `attribute: "class"` für Tailwind-Kompatibilität) - Das aktuelle `:root`-Farbschema wird zum Light Theme umstrukturiert, ein neues Dark Theme wird unter `.dark` definiert - Ein Theme-Toggle-Button wird im Header platziert (Desktop und Mobile) - Ein Inline-Script in `index.html` verhindert Theme-Flackern beim Laden (FOUC-Prevention) ## Architektur ```mermaid graph TD A[index.html – Inline-Script] -->|Setzt class auf html| B[html-Element] B --> C[ThemeProvider – next-themes] C --> D[App.tsx] D --> E[Header mit ThemeToggle] D --> F[Alle Seiten & Komponenten] G[localStorage – theme] <-->|Lesen/Schreiben| C H[prefers-color-scheme] -->|System-Erkennung| C I[index.css – :root Light] --> F J[index.css – .dark Dark] --> F ``` ### Datenfluss 1. Beim Laden der Seite liest ein Inline-Script in `index.html` den `localStorage`-Wert (`theme`) aus. Falls keiner vorhanden ist, wird `prefers-color-scheme` geprüft. Die entsprechende CSS-Klasse (`dark` oder keine) wird auf `` gesetzt – noch bevor React rendert. 2. `ThemeProvider` aus `next-themes` übernimmt die Verwaltung im React-Baum. Er synchronisiert den Zustand mit `localStorage` und reagiert auf Änderungen der System-Einstellung via `matchMedia`-Listener. 3. Der `ThemeToggle`-Button im Header nutzt den `useTheme()`-Hook, um zwischen `light`, `dark` und `system` zu wechseln. 4. Alle Komponenten nutzen weiterhin `hsl(var(--...))` CSS-Variablen – der Wechsel erfolgt rein über CSS-Klassen. ## Komponenten und Schnittstellen ### 1. ThemeProvider-Wrapper (`src/components/ThemeProvider.tsx`) Dünner Wrapper um `ThemeProvider` aus `next-themes`: ```typescript interface ThemeProviderProps { children: React.ReactNode; defaultTheme?: string; // Standard: "system" storageKey?: string; // Standard: "theme" enableSystem?: boolean; // Standard: true disableTransitionOnChange?: boolean; // Standard: false } ``` Konfiguration: - `attribute="class"` – Tailwind-kompatibel - `defaultTheme="system"` – Erstbesucher erhalten System-Theme - `enableSystem={true}` – Automatische Erkennung aktiv - `storageKey="theme"` – localStorage-Schlüssel Wird in `App.tsx` als äußerster Wrapper um den gesamten Komponentenbaum eingebunden. ### 2. ThemeToggle-Komponente (`src/components/ThemeToggle.tsx`) Button-Komponente mit Dropdown-Menü (shadcn/ui `DropdownMenu`): ```typescript interface ThemeToggleProps { className?: string; } ``` Funktionalität: - Zeigt ein Icon basierend auf dem aktuellen Theme (Sun, Moon, Monitor aus `lucide-react`) - Dropdown mit drei Optionen: „Hell", „Dunkel", „System" - Nutzt `useTheme()` Hook für `theme`, `setTheme`, `resolvedTheme` - `aria-label` beschreibt den aktuellen Zustand - Tastatur-bedienbar (Tab, Enter/Space) - Mounted-Check verhindert Hydration-Mismatch (Icon wird erst nach Mount gerendert) ### 3. Anpassungen am Header (`src/components/Header.tsx`) - ThemeToggle wird im Desktop-NavBody neben dem „Kontakt"-Button eingefügt - ThemeToggle wird im Mobile-Nav-Header neben dem Hamburger-Menü eingefügt - Positionierung: rechts, vor dem Kontakt-Button (Desktop) bzw. links vom Toggle-Icon (Mobile) ### 4. Inline-Script in `index.html` Ein `