Skip to content

Use theme-aware window background color#21729

Merged
sergiou87 merged 5 commits intodevelopmentfrom
pr/21564
Mar 5, 2026
Merged

Use theme-aware window background color#21729
sergiou87 merged 5 commits intodevelopmentfrom
pr/21564

Conversation

@sergiou87
Copy link
Member

Closes #21548

Description

Add light/dark background colors instead of hardcoded #fff and a getWindowBackgroundColor helper to choose the appropriate color based on nativeTheme.shouldUseDarkColors. Use this helper when creating the main window and when the native theme updates so the window background matches the current light/dark theme.

Recordings

Before After
Before.mov
After.mov

Release notes

Notes: [Fixed] Fix window background color when resizing - Thanks @BaldrianSector

BaldrianSector and others added 2 commits February 4, 2026 21:56
Add light/dark background color constants and a getWindowBackgroundColor helper to choose the appropriate color based on nativeTheme.shouldUseDarkColors. Use this helper when creating BrowserWindow and when the native theme updates so the window background matches the current light/dark theme.
Keep the native window background in sync with the app's CSS theme color. Add a new IPC channel type and a main-process handler that calls BrowserWindow.setBackgroundColor, and send the computed --background-color from the renderer after applying a theme so the window chrome matches the UI.

Co-Authored-By: Baldrian Sector <53869869+baldriansector@users.noreply.github.com>
niik
niik previously approved these changes Mar 4, 2026
Copy link
Member

@niik niik left a comment

Choose a reason for hiding this comment

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

I love this so much, I didn't know how bad this problem was before I got to resize with this change. Thanks @BaldrianSector, @sergiou87!

Co-Authored-By: Baldrian Sector <53869869+baldriansector@users.noreply.github.com>
sergiou87 and others added 2 commits March 4, 2026 11:01
Co-Authored-By: Baldrian Sector <53869869+baldriansector@users.noreply.github.com>
@BaldrianSector
Copy link
Contributor

This should also fix quick white flash, that would sometimes momentarily be shown when opening the app in full screen on darkmode 👌🏻

When the app loads it sometimes needs a frame before content is displayed and the #fff would take up the whole screen

@sergiou87
Copy link
Member Author

Hmmm @BaldrianSector not sure if that flash will be fixed in this case, since I left that initial '#fff', but we can revisit later. I'd just prefer not having any hardcoded/duplicated colors in the code if possible 😓

@BaldrianSector
Copy link
Contributor

BaldrianSector commented Mar 4, 2026

Ahh, you're right. Well, I guess that's something to revisit for later then 😉

@sergiou87 sergiou87 enabled auto-merge March 4, 2026 10:14
@sergiou87
Copy link
Member Author

I think something like this would solve both issues (flash when the app starts and hardcoding colors twice), but not sure if it's worth the effort, feels a bit overkill…

diff --git a/app/src/main-process/app-window.ts b/app/src/main-process/app-window.ts
index 485a9fb1ea..a7710fdff0 100644
--- a/app/src/main-process/app-window.ts
+++ b/app/src/main-process/app-window.ts
@@ -29,6 +29,7 @@ import {
 import { addTrustedIPCSender } from './trusted-ipc-sender'
 import { getUpdaterGUID } from '../lib/get-updater-guid'
 import { CLIAction } from '../lib/cli-action'
+import themeColors from '../lib/default-theme-colors.json'
 
 export class AppWindow {
   private window: Electron.BrowserWindow
@@ -61,7 +62,9 @@ export class AppWindow {
       show: false,
       // This fixes subpixel aliasing on Windows
       // See https://github.com/atom/atom/commit/683bef5b9d133cb194b476938c77cc07fd05b972
-      backgroundColor: '#fff',
+      backgroundColor: nativeTheme.shouldUseDarkColors
+        ? themeColors.darkBackgroundColor
+        : themeColors.lightBackgroundColor,
       webPreferences: {
         // Disable auxclick event
         // See https://developers.google.com/web/updates/2016/10/auxclick
diff --git a/app/styles/_variables.scss b/app/styles/_variables.scss
index d48b4c14b5..9d2738150c 100644
--- a/app/styles/_variables.scss
+++ b/app/styles/_variables.scss
@@ -21,7 +21,7 @@ $overlay-background-color: rgba(0, 0, 0, 0.4);
   --text-color: #{$gray-900};
   --text-secondary-color: #{$gray-500};
   --text-secondary-color-muted: #{lighten($gray-500, 30%)};
-  --background-color: #{$white};
+  --background-color: #{$default-light-background-color};
 
   --button-height: 25px;
 
diff --git a/app/styles/themes/_dark.scss b/app/styles/themes/_dark.scss
index f3fbfd8e18..1b3f99510c 100644
--- a/app/styles/themes/_dark.scss
+++ b/app/styles/themes/_dark.scss
@@ -23,7 +23,7 @@ body.theme-dark {
   --text-color: #{$gray-100};
   --text-secondary-color: #{$gray-400};
   --text-secondary-color-muted: #{darken($gray-500, 10%)};
-  --background-color: #{$gray-900};
+  --background-color: #{$default-dark-background-color};
 
   --button-background: #{$blue};
   --button-hover-background: #{lighten($blue, 5%)};
diff --git a/app/webpack.common.ts b/app/webpack.common.ts
index 32310f597a..cd5225de6f 100644
--- a/app/webpack.common.ts
+++ b/app/webpack.common.ts
@@ -3,6 +3,11 @@ import HtmlWebpackPlugin from 'html-webpack-plugin'
 import webpack from 'webpack'
 import merge from 'webpack-merge'
 import { getReplacements } from './app-info'
+import * as themeColors from './src/lib/default-theme-colors.json'
+
+export const sassLoaderOptions = {
+  additionalData: `$default-light-background-color: ${themeColors.lightBackgroundColor};\n$default-dark-background-color: ${themeColors.darkBackgroundColor};\n`,
+}
 
 export const externals = ['7zip']
 
diff --git a/app/webpack.development.ts b/app/webpack.development.ts
index a87b602d40..53dda52286 100644
--- a/app/webpack.development.ts
+++ b/app/webpack.development.ts
@@ -1,4 +1,5 @@
 import * as common from './webpack.common'
+import { sassLoaderOptions } from './webpack.common'
 
 import * as webpack from 'webpack'
 import merge from 'webpack-merge'
@@ -57,7 +58,10 @@ const rendererConfig = merge({}, common.renderer, config, {
         use: [
           'style-loader',
           { loader: 'css-loader', options: { sourceMap: true } },
-          { loader: 'sass-loader', options: { sourceMap: true } },
+          {
+            loader: 'sass-loader',
+            options: { sourceMap: true, ...sassLoaderOptions },
+          },
         ],
       },
     ],
@@ -79,7 +83,10 @@ const crashConfig = merge({}, common.crash, config, {
         use: [
           'style-loader',
           { loader: 'css-loader', options: { sourceMap: true } },
-          { loader: 'sass-loader', options: { sourceMap: true } },
+          {
+            loader: 'sass-loader',
+            options: { sourceMap: true, ...sassLoaderOptions },
+          },
         ],
       },
     ],
diff --git a/app/webpack.production.ts b/app/webpack.production.ts
index 8e0687adaf..621a9bb5fd 100644
--- a/app/webpack.production.ts
+++ b/app/webpack.production.ts
@@ -1,4 +1,5 @@
 import * as common from './webpack.common'
+import { sassLoaderOptions } from './webpack.common'
 
 import * as webpack from 'webpack'
 import merge from 'webpack-merge'
@@ -22,7 +23,11 @@ const rendererConfig = merge({}, common.renderer, config, {
       // appended to the index.html HEAD at compile time
       {
         test: /\.(scss|css)$/,
-        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
+        use: [
+          MiniCssExtractPlugin.loader,
+          'css-loader',
+          { loader: 'sass-loader', options: sassLoaderOptions },
+        ],
       },
     ],
   },
@@ -50,7 +55,11 @@ const crashConfig = merge({}, common.crash, config, {
       // appended to the index.html HEAD at compile time
       {
         test: /\.(scss|css)$/,
-        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
+        use: [
+          MiniCssExtractPlugin.loader,
+          'css-loader',
+          { loader: 'sass-loader', options: sassLoaderOptions },
+        ],
       },
     ],
   },

Basically extracts the colors to a JSON and uses that both in code and in scss. For ts code it just imports the json, but for scss it needs to tweak the scss loading options via webpack…

@niik
Copy link
Member

niik commented Mar 5, 2026

I think we should take this one step at a time. Getting the right background color when resizing is a great first step. I'm not too fussed about the initial flash, we can review a PR to address that separately

@sergiou87 sergiou87 merged commit e0bb31b into development Mar 5, 2026
7 checks passed
@sergiou87 sergiou87 deleted the pr/21564 branch March 5, 2026 08:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

When resizing on the main window on macOS it leaves trailing white bars

3 participants