Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions apps/desktop/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { autoUpdater } from "electron-updater";
import type { ContextMenuItem } from "@t3tools/contracts";
import { NetService } from "@t3tools/shared/Net";
import { RotatingFileSink } from "@t3tools/shared/logging";
import { THEME_BG_DARK, THEME_BG_LIGHT } from "@t3tools/shared/theme";
import { showDesktopConfirmDialog } from "./confirmDialog";
import { syncShellEnvironment } from "./syncShellEnvironment";
import { getAutoUpdateDisabledReason, shouldBroadcastDownloadProgress } from "./updateState";
Expand Down Expand Up @@ -1104,6 +1105,13 @@ function registerIpcHandlers(): void {
}

nativeTheme.themeSource = theme;

// Keep the native window background in sync so resize does not flash
// a stale color while the renderer catches up.
const bg = themeBackgroundColor();
for (const win of BrowserWindow.getAllWindows()) {
win.setBackgroundColor(bg);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale background color when OS theme changes

Medium Severity

When the app is set to "system" theme, OS-level dark/light mode changes update the renderer (via prefers-color-scheme media query) but never call setBackgroundColor on the BrowserWindow. The SET_THEME_CHANNEL handler only fires when the user explicitly changes the theme in the UI. Without a nativeTheme.on('updated') listener, the window background becomes stale after an OS theme change, causing the same wrong-color flash on resize that this PR aims to fix.

Additional Locations (1)
Fix in Cursor Fix in Web

});

ipcMain.removeHandler(CONTEXT_MENU_CHANNEL);
Expand Down Expand Up @@ -1220,6 +1228,10 @@ function getIconOption(): { icon: string } | Record<string, never> {
return iconPath ? { icon: iconPath } : {};
}

function themeBackgroundColor(): string {
return nativeTheme.shouldUseDarkColors ? THEME_BG_DARK : THEME_BG_LIGHT;
}

function createWindow(): BrowserWindow {
const window = new BrowserWindow({
width: 1100,
Expand All @@ -1228,6 +1240,7 @@ function createWindow(): BrowserWindow {
minHeight: 620,
show: false,
autoHideMenuBar: true,
backgroundColor: themeBackgroundColor(),
...getIconOption(),
title: APP_DISPLAY_NAME,
titleBarStyle: "hiddenInset",
Expand Down
14 changes: 14 additions & 0 deletions apps/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@
rel="stylesheet"
/>
<title>T3 Code (Alpha)</title>
<script>
// Apply dark class before first paint so CSS variables resolve correctly.
// Must run synchronously in <head> — no color literals needed here
// because the CSS custom properties handle the actual values.
(function () {
var t = localStorage.getItem("t3code:theme") || "system";
if (
t === "dark" ||
(t === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches)
) {
document.documentElement.classList.add("dark");
}
})();
</script>
</head>
<body>
<div id="root"></div>
Expand Down
4 changes: 4 additions & 0 deletions packages/shared/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
"./schemaJson": {
"types": "./src/schemaJson.ts",
"import": "./src/schemaJson.ts"
},
"./theme": {
"types": "./src/theme.ts",
"import": "./src/theme.ts"
}
},
"scripts": {
Expand Down
11 changes: 11 additions & 0 deletions packages/shared/src/theme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Native-window background colors that match the app's CSS theme tokens.
*
* Dark → `color-mix(in srgb, neutral-950 95%, white)` ≈ #161616
* Light → white
*
* Used by the Electron main process to set `BrowserWindow.backgroundColor`
* so resizing never flashes a mismatched color.
*/
export const THEME_BG_DARK = "#161616";
export const THEME_BG_LIGHT = "#ffffff";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded colors duplicate CSS tokens risking drift

Low Severity

THEME_BG_DARK (#161616) is a manually computed approximation of the CSS color-mix(in srgb, neutral-950 95%, white) token in index.css. There is no single source of truth — if the CSS value changes (different base color, different percentage, different color space), this constant silently becomes wrong and the BrowserWindow background will flash a mismatched color during resize. This was also flagged by a reviewer.

Fix in Cursor Fix in Web