Skip to content

feat: add Menu.setHighlightColors() for Windows - #55074

Merged
jkleinsc merged 4 commits into
electron:mainfrom
ashleyhendrata:menu-highlight-colors
Oct 29, 2026
Merged

jkleinsc merged 4 commits into
electron:mainfrom
ashleyhendrata:menu-highlight-colors

Conversation

@ashleyhendrata

@ashleyhendrata ashleyhendrata commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Description of Change

Closes #54953

Adds Menu.setHighlightColors(options) so apps can set the background and text color of the hovered or keyboard-focused item in menus on Windows. By default that highlight is about #f2f2f2 on white (roughly 1.12:1), below the 3:1 that WCAG 1.4.11 asks for, and apps had no way to change it.

The colors are applied by a color mixer registered after Chromium's in ElectronBrowserMainParts::PreEarlyInitialization(), which overrides kColorMenuItemBackgroundSelected and kColorMenuItemForegroundSelected. The mixer does nothing in high contrast or forced colors mode so the user's system colors win. Calling the method clears the color provider cache so menus opened afterwards pick up the change, and null restores the defaults.

The mixer is only registered on Windows, so the method has no effect on macOS (which uses NSMenu) or on Linux, where the GTK and Qt themes provide their own menu colors (ui/gtk/gtk_color_mixers.cc, ui/qt/qt_ui.cc).

const { Menu } = require('electron')

Menu.setHighlightColors({
  light: { background: '#0067c0', foreground: '#ffffff' }, // 5.7:1
  dark: { background: '#4cc2ff', foreground: '#000000' } // 10.5:1
})

Menu.setHighlightColors(null) // restore the defaults

Light and dark colors are set independently: any color left unset keeps Chromium's default for that mode, and each call replaces the colors from previous calls.

Tested on Windows 11 ARM64 with the CI build from this PR:

Highlight Contrast vs. menu background
Default #f2f2f2 on #ffffff 1.12:1
Menu.setHighlightColors({ light: { background: '#0067c0', foreground: '#ffffff' } }) #0067c0 on #ffffff 5.7:1

Checked context menus and menu bar dropdowns, light and dark mode, that a mode left unset keeps the default highlight (light colors only, viewed in dark mode), keyboard navigation with the arrow keys, resetting with null, and that a Windows contrast theme (Night sky) overrides the app's colors.

Before (default) After (#0067c0 / #ffffff)
Default highlight, context menu
Default highlight, menu bar
Custom highlight, context menu
Custom highlight, menu bar

Checklist

Release Notes

Notes: Added Menu.setHighlightColors() to set menu highlight colors on Windows.

@ashleyhendrata
ashleyhendrata marked this pull request as ready for review October 22, 2026 21:37
@ashleyhendrata
ashleyhendrata marked this pull request as draft October 22, 2026 21:37
@georgexu99 georgexu99 added target/44-x-y PR should also be added to the "44-x-y" branch. target/45-x-y PR should also be added to the "45-x-y" branch. labels Oct 26, 2026
@github-actions github-actions Bot added the target/46-x-y PR should also be added to the "46-x-y" branch. label Oct 26, 2026
@erickzhao erickzhao added the semver/minor backwards-compatible functionality label Oct 27, 2026
ashleyhendrata and others added 3 commits October 27, 2026 14:24
Lets apps set the background and text color of the hovered or
keyboard-focused item in Views menus on Windows. The colors are
skipped in high contrast and forced colors modes.

Closes electron#54953

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Comment thread docs/api/menu.md
```
-->

- `options` Object | null

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Having the dark mode options be an optional override feels strange, since we're then making the simplest usage result in no differentiation between light/dark mode (which is likely not what people want most of the time).

I wonder if a more symmetrical API would be better:

  - `light` (optional)
    - `background` string (optional)
    - `foreground` string (optional)
  - `dark` (optional)
    - `background` string (optional)
    - `foreground` string (optional)

Or alternatively:

  - `lightBackground` string (optional)
  - `lightForeground` string (optional)
  - `darkBackground` string (optional)
  - `darkForeground` string (optional)

If someone specifically wants to use the same colors for light/dark mode, then it would force them to be more verbose, but otherwise these API shapes would make calls to setHighlightColors much more explanatory without someone having to look up the docs to understand the override/fallback behaviors.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That makes sense, thanks for pointing that out! I've switched to the nested version, and each mode only uses its own colors (no fallback).

Comment thread shell/browser/api/electron_api_menu.cc Outdated
if (gin::ConvertFromV8(isolate, value, &str))
*out = ParseCSSColor(str);
if (!*out) {
thrower.ThrowTypeError(base::StrCat({"Invalid color for '", key, "'"}));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this comment might become outdated if you take my other suggestion to change the API shape, but I think this will produce an error like Invalid color for 'background' which won't be enough for someone to know if it was the light or dark "background" key.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Error now includes the mode, thank you!

Light and dark colors are now set independently, with no fallback
between modes, and validation errors name the mode (for example
'dark.background').

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>

@itsananderson itsananderson left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

API LGTM

@georgexu99

Copy link
Copy Markdown
Contributor

@claude get us a review please

@jkleinsc jkleinsc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

API LGTM

@jkleinsc
jkleinsc merged commit 77a943b into electron:main Oct 29, 2026
95 checks passed
@welcome

welcome Bot commented Oct 29, 2026

Copy link
Copy Markdown

Congrats on merging your first pull request! 🎉🎉🎉

@release-clerk

release-clerk Bot commented Oct 29, 2026

Copy link
Copy Markdown

Release Notes Persisted

Added Menu.setHighlightColors() to set menu highlight colors on Windows.

@trop

trop Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

I was unable to backport this PR to "44-x-y" cleanly;
you will need to perform this backport manually.

@trop trop Bot added needs-manual-bp/44-x-y and removed target/44-x-y PR should also be added to the "44-x-y" branch. labels Oct 29, 2026
@trop

trop Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

I have automatically backported this PR to "45-x-y", please check out #55493

@trop

trop Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

I have automatically backported this PR to "46-x-y", please check out #55494

@trop trop Bot added in-flight/46-x-y and removed target/45-x-y PR should also be added to the "45-x-y" branch. target/46-x-y PR should also be added to the "46-x-y" branch. labels Oct 29, 2026
@trop

trop Bot commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

@ashleyhendrata has manually backported this PR to "44-x-y", please check out #55500

@trop trop Bot added in-flight/44-x-y merged/46-x-y PR was merged to the "46-x-y" branch. merged/45-x-y PR was merged to the "45-x-y" branch. and removed needs-manual-bp/44-x-y in-flight/46-x-y in-flight/45-x-y labels Oct 30, 2026
jkleinsc pushed a commit that referenced this pull request Nov 3, 2026
feat: add Menu.setHighlightColors() for Windows (#55074)

* feat: add Menu.setHighlightColors() for Windows

Lets apps set the background and text color of the hovered or
keyboard-focused item in Views menus on Windows. The colors are
skipped in high contrast and forced colors modes.

Closes #54953



* docs: add API history for Menu.setHighlightColors



* style: apply clang-format to menu_highlight_colors.cc



* refactor: use symmetric light/dark options for Menu.setHighlightColors

Light and dark colors are now set independently, with no fallback
between modes, and validation errors name the mode (for example
'dark.background').



---------


(cherry picked from commit 77a943b)

Co-authored-by: Claude <svc-devxp-claude@slack-corp.com>
@trop trop Bot added merged/44-x-y PR was merged to the "44-x-y" branch. and removed in-flight/44-x-y labels Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

47-x-y api-review/requested 🗳 merged/44-x-y PR was merged to the "44-x-y" branch. merged/45-x-y PR was merged to the "45-x-y" branch. merged/46-x-y PR was merged to the "46-x-y" branch. semver/minor backwards-compatible functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request]: Allow apps to set the hover/focus highlight colors of Views-based menus on Windows

5 participants