From b29732a6535794fa4a68fb557eca045f33507b9b Mon Sep 17 00:00:00 2001 From: Lars Behrends Date: Fri, 10 Apr 2026 14:59:40 +0200 Subject: [PATCH] Introduce ThemeContext and apply theme tokens Add a ThemeContext and provider, wrap the app with ThemeProvider, and sync user settings' theme into the context. Replace hardcoded color classes with design token classes (background, muted, foreground, border, card, etc.) across multiple UI components to centralize theming and enable consistent light/dark styling. Files updated include App.tsx (useTheme, setTheme, ThemeProvider, footer/background tokens), several views and components (AddMediaView, BrowseView, CastDetailView, CastView, MediaCard, MediaListItem, SettingsView, ImporterView) to use tokenized classes, and add new src/contexts/ThemeContext.tsx. --- src/App.tsx | 25 ++++--- src/components/AddMediaView.tsx | 89 ++++++++++++------------ src/components/BrowseView.tsx | 38 +++++----- src/components/CastDetailView.tsx | 106 ++++++++++++++-------------- src/components/CastView.tsx | 70 +++++++++---------- src/components/DetailView.tsx | 88 +++++++++++------------ src/components/ImporterView.tsx | 112 +++++++++++++++--------------- src/components/MediaCard.tsx | 6 +- src/components/MediaListItem.tsx | 18 ++--- src/components/SettingsView.tsx | 70 ++++++++++--------- src/contexts/ThemeContext.tsx | 74 ++++++++++++++++++++ 11 files changed, 392 insertions(+), 304 deletions(-) create mode 100644 src/contexts/ThemeContext.tsx diff --git a/src/App.tsx b/src/App.tsx index 52b65c8..836ab45 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -17,11 +17,13 @@ import SettingsView from './components/SettingsView'; import { MOCK_MEDIA, DETAIL_MEDIA } from './data'; import { Media, Staff, MediaCategory, UserSettings } from './types'; import { fetchAllMedia, fetchMediaById, fetchCastById, convertApiCastToStaff, fetchSettings, updateSettings } from './api'; +import { ThemeProvider, useTheme } from './contexts/ThemeContext'; function AppContent() { const navigate = useNavigate(); const location = useLocation(); const [searchParams, setSearchParams] = useSearchParams(); + const { setTheme } = useTheme(); const [activeCategory, setActiveCategory] = useState( (searchParams.get('category') as MediaCategory) || 'Anime' ); @@ -43,6 +45,8 @@ function AppContent() { if (loadedSettings) { setSettings(loadedSettings); setEnabledCategories(loadedSettings.enabledCategories); + // Sync theme with theme context + setTheme(loadedSettings.theme); } } catch (error) { console.error('Failed to load settings from API:', error); @@ -50,7 +54,7 @@ function AppContent() { }; loadSettingsFromApi(); - }, []); + }, [setTheme]); const reloadSettings = async () => { try { @@ -58,6 +62,8 @@ function AppContent() { if (loadedSettings) { setSettings(loadedSettings); setEnabledCategories(loadedSettings.enabledCategories); + // Sync theme with theme context + setTheme(loadedSettings.theme); } } catch (error) { console.error('Failed to reload settings from API:', error); @@ -270,7 +276,7 @@ function AppContent() { }; return ( -
+
} /> @@ -329,18 +336,18 @@ function AppContent() { {/* Footer */} -