feat: dark theme applies to editor content area

Three changes make the editor respect the active theme:

1. useThemeManager now derives app-specific CSS variables (--bg-primary,
   --text-primary, --border-primary, etc.) from the theme's core colors,
   so the editor's EditorTheme.css variables resolve correctly for both
   light and dark themes.

2. BlockNoteView theme prop is now dynamic (isDark ? 'dark' : 'light')
   instead of hardcoded to 'light', so BlockNote's own UI chrome (menus,
   toolbars) matches the active theme.

3. Removed forced light-mode class removal from main.tsx that was
   preventing dark mode from being applied.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
lucaronin
2026-03-02 11:53:31 +01:00
parent 178efb6512
commit 13ee62ce67
8 changed files with 239 additions and 9 deletions

View File

@@ -60,6 +60,7 @@ interface EditorProps {
onGoBack?: () => void
onGoForward?: () => void
leftPanelsCollapsed?: boolean
isDarkTheme?: boolean
}
function EditorEmptyState() {
@@ -82,6 +83,7 @@ export const Editor = memo(function Editor({
onTrashNote, onRestoreNote, onArchiveNote, onUnarchiveNote,
onRenameTab, onContentChange, onTitleSync,
canGoBack, canGoForward, onGoBack, onGoForward, leftPanelsCollapsed,
isDarkTheme,
}: EditorProps) {
const vaultPathRef = useRef(vaultPath)
useEffect(() => { vaultPathRef.current = vaultPath }, [vaultPath])
@@ -161,6 +163,7 @@ export const Editor = memo(function Editor({
onArchiveNote={onArchiveNote}
onUnarchiveNote={onUnarchiveNote}
vaultPath={vaultPath}
isDarkTheme={isDarkTheme}
/>
}
{showRightPanel && <ResizeHandle onResize={onInspectorResize} />}

View File

@@ -32,6 +32,7 @@ interface EditorContentProps {
onArchiveNote?: (path: string) => void
onUnarchiveNote?: (path: string) => void
vaultPath?: string
isDarkTheme?: boolean
}
function EditorLoadingSkeleton() {
@@ -97,7 +98,7 @@ function ActiveTabBreadcrumb({ activeTab, props }: {
export function EditorContent({
activeTab, isLoadingNewTab, entries, editor,
diffMode, diffContent, onToggleDiff,
onNavigateWikilink, onEditorChange, vaultPath,
onNavigateWikilink, onEditorChange, vaultPath, isDarkTheme,
...breadcrumbProps
}: EditorContentProps) {
return (
@@ -106,7 +107,7 @@ export function EditorContent({
{diffMode && <DiffModeView diffContent={diffContent} onToggleDiff={onToggleDiff} />}
{!diffMode && activeTab && (
<div style={{ display: 'flex', flex: 1, flexDirection: 'column', minHeight: 0 }}>
<SingleEditorView editor={editor} entries={entries} onNavigateWikilink={onNavigateWikilink} onChange={onEditorChange} vaultPath={vaultPath} />
<SingleEditorView editor={editor} entries={entries} onNavigateWikilink={onNavigateWikilink} onChange={onEditorChange} vaultPath={vaultPath} isDarkTheme={isDarkTheme} />
</div>
)}
{isLoadingNewTab && !diffMode && <EditorLoadingSkeleton />}

View File

@@ -40,6 +40,7 @@ const mockThemeManager: ThemeManager = {
themes: [],
activeThemeId: null,
activeTheme: null,
isDark: false,
switchTheme: vi.fn(),
createTheme: vi.fn().mockResolvedValue('untitled'),
reloadThemes: vi.fn(),

View File

@@ -23,12 +23,13 @@ function useInsertImageCallback(editor: ReturnType<typeof useCreateBlockNote>) {
}
/** Single BlockNote editor view — content is swapped via replaceBlocks */
export function SingleEditorView({ editor, entries, onNavigateWikilink, onChange, vaultPath }: {
export function SingleEditorView({ editor, entries, onNavigateWikilink, onChange, vaultPath, isDarkTheme }: {
editor: ReturnType<typeof useCreateBlockNote>
entries: VaultEntry[]
onNavigateWikilink: (target: string) => void
onChange?: () => void
vaultPath?: string
isDarkTheme?: boolean
}) {
const navigateRef = useRef(onNavigateWikilink)
useEffect(() => { navigateRef.current = onNavigateWikilink }, [onNavigateWikilink])
@@ -100,7 +101,7 @@ export function SingleEditorView({ editor, entries, onNavigateWikilink, onChange
)}
<BlockNoteView
editor={editor}
theme="light"
theme={isDarkTheme ? 'dark' : 'light'}
onChange={onChange}
>
<SuggestionMenuController