fix(desktop): eliminate white flash on window resize in dark mode

Set native window backgroundColor to match the app's surface0 color so
the backing layer is dark during resize repaints. Extend the existing
updateWindowControls IPC to also call setBackgroundColor on all platforms
(including macOS), keeping the renderer as the single source of truth
for theme resolution. Add a prefers-color-scheme CSS rule in index.html
to cover the HTML-to-React mount gap.
This commit is contained in:
Mohamed Boudra
2026-04-01 18:33:17 +07:00
parent ade1e338ea
commit 963c79265a
3 changed files with 22 additions and 2 deletions

View File

@@ -19,6 +19,12 @@
body {
overflow: hidden;
}
/* Prevent white flash before React mounts */
@media (prefers-color-scheme: dark) {
html, body {
background-color: #181B1A;
}
}
/* These styles make the root element full-height */
#root {
display: flex;

View File

@@ -14,6 +14,7 @@ import { closeAllTransportSessions } from "./daemon/local-transport.js";
import {
registerWindowManager,
getMainWindowChromeOptions,
getWindowBackgroundColor,
resolveSystemWindowTheme,
setupWindowResizeEvents,
setupDragDropPrevention,
@@ -93,6 +94,7 @@ async function createMainWindow(): Promise<void> {
width: 1200,
height: 800,
show: false,
backgroundColor: getWindowBackgroundColor(systemTheme),
...(iconPath ? { icon: iconPath } : {}),
...getMainWindowChromeOptions({
platform: process.platform,

View File

@@ -33,6 +33,10 @@ export function resolveSystemWindowTheme(): WindowTheme {
return nativeTheme.shouldUseDarkColors ? "dark" : "light";
}
export function getWindowBackgroundColor(theme: WindowTheme): string {
return theme === "dark" ? "#181B1A" : "#ffffff";
}
export function createWindowControlsOverlayState(theme: WindowTheme): WindowControlsOverlayState {
const overlay = getTitleBarOverlayOptions(theme);
return {
@@ -44,7 +48,7 @@ export function createWindowControlsOverlayState(theme: WindowTheme): WindowCont
export function getTitleBarOverlayOptions(theme: WindowTheme): Electron.TitleBarOverlayOptions {
if (theme === "dark") {
return { color: "#18181c", symbolColor: "#e4e4e7", height: 29 };
return { color: "#181B1A", symbolColor: "#e4e4e7", height: 29 };
}
return { color: "#ffffff", symbolColor: "#09090b", height: 29 };
@@ -171,7 +175,7 @@ export function registerWindowManager(): void {
ipcMain.handle("paseo:window:updateWindowControls", (event, update?: unknown) => {
const win = BrowserWindow.fromWebContents(event.sender);
if (!win || process.platform === "darwin") {
if (!win) {
return;
}
@@ -180,6 +184,14 @@ export function registerWindowManager(): void {
return;
}
if (nextUpdate.backgroundColor) {
win.setBackgroundColor(nextUpdate.backgroundColor);
}
if (process.platform === "darwin") {
return;
}
const current =
overlayStateByWindow.get(win) ?? createWindowControlsOverlayState(resolveSystemWindowTheme());
const nextState = applyWindowControlsOverlayUpdate({