Files
Webklar/.kiro/specs/system-theme-detection/tasks.md
2026-05-10 12:19:58 +02:00

6.4 KiB

Implementation Plan: System-Theme-Erkennung (Light/Dark Mode)

Overview

Integrate next-themes into the existing React + Vite + Tailwind + shadcn/ui app to enable automatic OS theme detection, manual theme switching (light/dark/system), and persistent user preference. The CSS variables in src/index.css will be restructured so :root defines the light theme and .dark defines the dark theme. A ThemeToggle component will be added to the Header, and an inline script in index.html will prevent FOUC.

Tasks

  • 1. Restructure CSS variables and set up testing dependencies

    • 1.1 Restructure CSS custom properties in src/index.css

      • Move the current :root dark color values into the .dark block
      • Define new light theme values in :root (white backgrounds, dark text, matching design spec)
      • Ensure all design tokens are covered: background, foreground, card, primary, secondary, muted, accent, border, input, ring, destructive, popover, sidebar, chart-1 through chart-5
      • Update hardcoded color values in component styles (.glass-nav, .card-minimal, .project-card, .btn, .text-gradient, etc.) to use CSS variables where possible
      • Add dark-mode-aware variants for component styles that use hardcoded HSL values
      • Requirements: 4.1, 4.2, 4.3, 4.4
    • 1.2 Install fast-check as a dev dependency

      • Run npm install --save-dev fast-check
      • Requirements: (testing infrastructure)
  • 2. Create ThemeProvider wrapper and integrate into App

    • 2.1 Create src/components/ThemeProvider.tsx

      • Export a thin wrapper around ThemeProvider from next-themes
      • Configure with attribute="class", defaultTheme="system", enableSystem={true}, storageKey="theme"
      • Accept children and optional override props
      • Requirements: 1.1, 1.2, 1.3, 3.1, 3.2
    • 2.2 Wrap the App component tree with ThemeProvider in src/App.tsx

      • Import ThemeProvider and wrap it as the outermost provider around the existing component tree
      • Requirements: 1.1, 2.3, 2.4, 2.5
    • * 2.3 Write property test: System-Theme-Auflösung (Property 1)

      • Property 1: System-Theme-Auflösung
      • Generate arbitrary system theme values (light/dark), set preference to "system", verify resolvedTheme === systemTheme
      • Use fast-check with minimum 100 iterations
      • Validates: Requirements 1.1, 1.2, 1.3, 2.5
    • * 2.4 Write property test: Explizite Theme-Wahl überschreibt System (Property 2)

      • Property 2: Explizite Theme-Wahl überschreibt System
      • Generate arbitrary combinations of system theme and explicit choice ("light"/"dark"), verify resolvedTheme === expliziteWahl
      • Use fast-check with minimum 100 iterations
      • Validates: Requirements 2.3, 2.4
    • * 2.5 Write property test: Persistenz-Round-Trip (Property 3)

      • Property 3: Persistenz-Round-Trip
      • Generate arbitrary valid theme values ("light", "dark", "system"), set via setTheme(), read from localStorage, verify equality and correct restoration on simulated reload
      • Use fast-check with minimum 100 iterations
      • Validates: Requirements 3.1, 3.2
  • 3. Checkpoint

    • Ensure all tests pass, ask the user if questions arise.
  • 4. Create ThemeToggle component

    • 4.1 Create src/components/ThemeToggle.tsx

      • Build a button component using shadcn/ui DropdownMenu and Button
      • Use useTheme() hook from next-themes for theme, setTheme, resolvedTheme
      • Display Sun icon (lucide-react) for light, Moon for dark, Monitor for system
      • Implement mounted-state check to prevent hydration mismatch on icon rendering
      • Dropdown offers three options: "Hell" (light), "Dunkel" (dark), "System" (system)
      • Add aria-label describing current state (e.g., "Theme wechseln, aktuell: Dunkel")
      • Ensure keyboard navigability (Tab, Enter/Space)
      • Accept optional className prop for positioning flexibility
      • Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 6.1, 6.2, 6.3
    • * 4.2 Write unit tests for ThemeToggle

      • Test that the toggle button renders in the DOM
      • Test that dropdown shows three options (Hell, Dunkel, System)
      • Test correct icon rendering per theme state
      • Test aria-label contains current theme state
      • Test keyboard interaction (focus, Enter/Space opens dropdown)
      • Requirements: 2.1, 2.2, 2.6, 6.1, 6.2, 6.3
  • 5. Integrate ThemeToggle into Header

    • 5.1 Add ThemeToggle to desktop navigation in src/components/Header.tsx

      • Import ThemeToggle and place it in the NavBody actions area, before the "Kontakt" button
      • Requirements: 2.1
    • 5.2 Add ThemeToggle to mobile navigation in src/components/Header.tsx

      • Place ThemeToggle in the MobileNavHeader, positioned next to the hamburger toggle icon
      • Requirements: 2.1
    • * 5.3 Write unit tests for Header ThemeToggle integration

      • Test that ThemeToggle is present in the rendered Header component
      • Requirements: 2.1
  • 6. Add FOUC-prevention inline script to index.html

    • 6.1 Add inline <script> block in the <head> of index.html

      • Read localStorage.getItem("theme")
      • If value is "dark", add class="dark" to <html>
      • If value is "system" or absent, check window.matchMedia("(prefers-color-scheme: dark)") and set class accordingly
      • If value is "light", ensure no dark class is present
      • Script must execute synchronously before any rendering
      • Requirements: 5.1, 5.2, 3.2
    • * 6.2 Write unit test for FOUC-prevention logic

      • Extract the inline script logic into a testable function
      • Test that correct class is applied for each localStorage value and system preference combination
      • Requirements: 5.1
  • 7. Final checkpoint

    • Ensure all tests pass, ask the user if questions arise.

Notes

  • Tasks marked with * are optional and can be skipped for faster MVP
  • Each task references specific requirements for traceability
  • Checkpoints ensure incremental validation
  • Property tests validate universal correctness properties from the design document
  • Unit tests validate specific examples and edge cases
  • The project uses TypeScript throughout — all new files should be .tsx/.ts
  • next-themes is already installed (^0.3.0), fast-check needs to be added as a dev dependency
  • lucide-react is already available for Sun/Moon/Monitor icons
  • shadcn/ui DropdownMenu and Button components already exist in src/components/ui/