From 621649b0b55207a5142cd11bf5c3d427d1ae2ac9 Mon Sep 17 00:00:00 2001 From: Alex Netsch Date: Fri, 5 Sep 2025 11:02:30 +0200 Subject: [PATCH] Fix dark mode for system setting (#630) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Perfect! ✅ I've successfully fixed the diff theme detection issue by: ## What I Did: ### 1. **Created a shared theme utility** (`frontend/src/utils/theme.ts`): - Properly handles all theme modes including SYSTEM - When theme is SYSTEM, it checks `window.matchMedia('(prefers-color-scheme: dark)')` - Treats all colored themes (PURPLE, GREEN, BLUE, ORANGE, RED) as dark themes ### 2. **Updated all diff-related components** to use the utility: - **DiffCard.tsx** ✅ - **EditDiffRenderer.tsx** ✅ - **FileChangeRenderer.tsx** ✅ ### 3. **Replaced the broken pattern**: ```tsx // OLD - only worked for explicit DARK theme let theme = 'light'; if (config?.theme === ThemeMode.DARK) theme = 'dark'; // NEW - works for all themes including SYSTEM const theme = getActualTheme(config?.theme); ``` ## Result: Now when you have **VK theme set to SYSTEM** and your **OS is in dark mode**, the diff viewers will correctly show dark theme colors instead of the incorrect light theme colors. The fix ensures consistency with how other components (Logo, JSONEditor) handle theme detection and follows the same pattern that the ThemeProvider uses internally. * fmt * Lint --- frontend/src/components/DiffCard.tsx | 5 ++-- .../EditDiffRenderer.tsx | 7 ++---- .../FileChangeRenderer.tsx | 6 ++--- frontend/src/utils/theme.ts | 23 +++++++++++++++++++ 4 files changed, 31 insertions(+), 10 deletions(-) create mode 100644 frontend/src/utils/theme.ts diff --git a/frontend/src/components/DiffCard.tsx b/frontend/src/components/DiffCard.tsx index a7c2e837..4ec9e0c7 100644 --- a/frontend/src/components/DiffCard.tsx +++ b/frontend/src/components/DiffCard.tsx @@ -1,9 +1,10 @@ -import { Diff as Diff, ThemeMode } from 'shared/types'; +import { Diff } from 'shared/types'; import { DiffModeEnum, DiffView } from '@git-diff-view/react'; import { generateDiffFile } from '@git-diff-view/file'; import { useMemo } from 'react'; import { useConfig } from '@/components/config-provider'; import { getHighLightLanguageFromPath } from '@/utils/extToLanguage'; +import { getActualTheme } from '@/utils/theme'; import { Button } from '@/components/ui/button'; import { ChevronRight, @@ -46,7 +47,7 @@ export default function DiffCard({ selectedAttempt, }: Props) { const { config } = useConfig(); - const theme = config?.theme === ThemeMode.DARK ? 'dark' : 'light'; + const theme = getActualTheme(config?.theme); const oldName = diff.oldPath || undefined; const newName = diff.newPath || oldName || 'unknown'; diff --git a/frontend/src/components/NormalizedConversation/EditDiffRenderer.tsx b/frontend/src/components/NormalizedConversation/EditDiffRenderer.tsx index 7d440a9f..0b4948bf 100644 --- a/frontend/src/components/NormalizedConversation/EditDiffRenderer.tsx +++ b/frontend/src/components/NormalizedConversation/EditDiffRenderer.tsx @@ -5,11 +5,11 @@ import { DiffLineType, parseInstance, } from '@git-diff-view/react'; -import { ThemeMode } from 'shared/types'; import { ChevronRight, ChevronUp } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { useConfig } from '@/components/config-provider'; import { getHighLightLanguageFromPath } from '@/utils/extToLanguage'; +import { getActualTheme } from '@/utils/theme'; import '@/styles/diff-style-overrides.css'; import '@/styles/edit-diff-overrides.css'; @@ -67,10 +67,7 @@ function EditDiffRenderer({ const { config } = useConfig(); const [expanded, setExpanded] = useExpandable(expansionKey, false); - let theme: 'light' | 'dark' | undefined = 'light'; - if (config?.theme === ThemeMode.DARK) { - theme = 'dark'; - } + const theme = getActualTheme(config?.theme); const { hunks, hideLineNumbers, additions, deletions, isValidDiff } = useMemo( () => processUnifiedDiff(unifiedDiff, hasLineNumbers), diff --git a/frontend/src/components/NormalizedConversation/FileChangeRenderer.tsx b/frontend/src/components/NormalizedConversation/FileChangeRenderer.tsx index f04048b4..180ab8a0 100644 --- a/frontend/src/components/NormalizedConversation/FileChangeRenderer.tsx +++ b/frontend/src/components/NormalizedConversation/FileChangeRenderer.tsx @@ -1,4 +1,4 @@ -import { ThemeMode, type FileChange } from 'shared/types'; +import { type FileChange } from 'shared/types'; import { useConfig } from '@/components/config-provider'; import { Button } from '@/components/ui/button'; import { @@ -9,6 +9,7 @@ import { ArrowRight, } from 'lucide-react'; import { getHighLightLanguageFromPath } from '@/utils/extToLanguage'; +import { getActualTheme } from '@/utils/theme'; import EditDiffRenderer from './EditDiffRenderer'; import FileContentView from './FileContentView'; import '@/styles/diff-style-overrides.css'; @@ -45,8 +46,7 @@ const FileChangeRenderer = ({ path, change, expansionKey }: Props) => { const { config } = useConfig(); const [expanded, setExpanded] = useExpandable(expansionKey, false); - let theme: 'light' | 'dark' | undefined = 'light'; - if (config?.theme === ThemeMode.DARK) theme = 'dark'; + const theme = getActualTheme(config?.theme); // Edit: delegate to EditDiffRenderer for identical styling and behavior if (isEdit(change)) { diff --git a/frontend/src/utils/theme.ts b/frontend/src/utils/theme.ts new file mode 100644 index 00000000..5dbf8414 --- /dev/null +++ b/frontend/src/utils/theme.ts @@ -0,0 +1,23 @@ +import { ThemeMode } from 'shared/types'; + +/** + * Resolves the actual theme (light/dark) based on the theme mode setting. + * Handles system theme detection properly. + */ +export function getActualTheme( + themeMode: ThemeMode | undefined +): 'light' | 'dark' { + if (!themeMode || themeMode === ThemeMode.LIGHT) { + return 'light'; + } + + if (themeMode === ThemeMode.SYSTEM) { + // Check system preference + return window.matchMedia('(prefers-color-scheme: dark)').matches + ? 'dark' + : 'light'; + } + + // All other themes (DARK, PURPLE, GREEN, BLUE, ORANGE, RED) have dark backgrounds + return 'dark'; +}