KEMBAR78
A11y: Disable forced color adjustment for Monaco editor by hawkticehurst · Pull Request #265373 · microsoft/vscode · GitHub
Skip to content

Conversation

@hawkticehurst
Copy link
Member

@hawkticehurst hawkticehurst commented Sep 5, 2025

Resolves microsoft/monaco-editor#4942
Resolves microsoft/monaco-editor#4945
Resolves microsoft/monaco-editor#4985

This PR disables forced color adjustment for the Monaco editor. This change matches what we do in VS Code desktop and now the editor will rely on the custom built-in high contrast themes that we ship instead.

meganrogge
meganrogge previously approved these changes Sep 5, 2025
Copy link
Contributor

@meganrogge meganrogge left a comment

Choose a reason for hiding this comment

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

👏🏼

@hawkticehurst hawkticehurst marked this pull request as ready for review September 8, 2025 12:08
@vs-code-engineering
Copy link

⚠️ This PR originates from a fork. Due to security restrictions, pipelines from forks are no longer triggered automatically. Learn more.

If the changes appear safe, you can manually trigger the pipeline by commenting /AzurePipelines run.

@vs-code-engineering vs-code-engineering bot added this to the September 2025 milestone Sep 8, 2025
Copy link
Member

@bpasero bpasero left a comment

Choose a reason for hiding this comment

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

🤔 this seems like a very isolated change in one area, does this impact all actions that show disabled?

Tyriar
Tyriar previously approved these changes Sep 8, 2025
@hawkticehurst
Copy link
Member Author

🤔 this seems like a very isolated change in one area, does this impact all actions that show disabled?

Oh great question. Based on the ticket, I was assuming the audit checked in other areas of the product for similar issues but perhaps that's wrong to assume. Do you know if there's an easy to way to audit the entire product to find where else this may be showing up?

@bpasero
Copy link
Member

bpasero commented Sep 8, 2025

So just in search alone, there are more disabled buttons:

image

I am just generally wondering what the accessibility issue is here: is it the low contrast of disabled actions in high contrast themes?

@hawkticehurst
Copy link
Member Author

hawkticehurst commented Sep 8, 2025

So just in search alone, there are more disabled buttons:

Nice I can start there.

I am just generally wondering what the accessibility issue is here: is it the low contrast of disabled actions in high contrast themes?

No, this is for Windows OS high contrast themes (not VS Code HC themes). When those themes are applied the OS switches to the system colors palette and the ticket reports that our disabled find widget buttons are using a color that makes them look enabled when they are not.

This comment explains/shows an example (from Edge) of what it should look like.

@bpasero
Copy link
Member

bpasero commented Sep 8, 2025

For reference, the disabled color is defined here:

export const disabledForeground = registerColor('disabledForeground',
{ dark: '#CCCCCC80', light: '#61616180', hcDark: '#A5A5A5', hcLight: '#7F7F7F' },
nls.localize('disabledForeground', "Overall foreground for disabled elements. This color is only used if not overridden by a component."));

One thing I do not fully understand: if Windows is turned into high contrast theme, VS Code should also change to high contrast automatically (@aeschli could comment on that). If there is an issue with our colors in high contrast themes, we need to fix the color in our high contrast theme. Anything else is just patches that will be hard to maintain...

@hawkticehurst
Copy link
Member Author

hawkticehurst commented Sep 8, 2025

If there is an issue with our colors in high contrast themes, we need to fix the color in our high contrast theme. Anything else is just patches that will be hard to maintain...

Ahh yeah that makes a ton of sense to me. I can get behind this.

If so, I wonder if we would want / need to add something along these lines that makes explicit use of the forced colors palette??

export const disabledForeground = registerColor('disabledForeground', 
 	{ dark: '#CCCCCC80', light: '#61616180', hcDark: '#A5A5A5', hcLight: '#7F7F7F', forcedColors: 'GrayText' }, 
 	nls.localize('disabledForeground', "Overall foreground for disabled elements. This color is only used if not overridden by a component."));

Basically adding support for a "forced colors theme"?

@aeschli
Copy link
Contributor

aeschli commented Sep 9, 2025

Ah, interesting, I'm also learning about the forced-color mode.
In VS Code we don't support the forced-colors mode by setting forced-color-adjust: none; but the Monaco editor can run in it.

In that mode, the colors set in CSS are ignored and replaced by a limited set of system colors based on the 'role' of the elements. Unfortunately it looks like our disabled element (marked with 'aria-disabled=true') are not recognized as disabled and rendered with the regular (button?) color instead of the recommended 'GrayText` color, and CSS adjustment would be necessary.

May I suggest a change limited to Monaco?
Monaco has fixed set of color themes and they are defined here:

export const hc_black: IStandaloneThemeData = {

I think this addition is good enough for the hc themes:

	colors: {
                ...
		[disabledForeground]: 'GrayText'
	}

the Monaco editor can run with a high contrast theme without being in forced-color mode. So maybe best if make that change only if mainWindow.matchMedia((forced-colors: active)).matches; is true

@hawkticehurst
Copy link
Member Author

hawkticehurst commented Sep 9, 2025

I can get behind that and am happy to update this PR (or start a new one if that's preferred?). @bpasero does that sound good to you?

*Would also do the same for #265430 which tackles a similar issue but for ::selection colors.

@vs-code-engineering
Copy link

⚠️ This PR originates from a fork. Due to security restrictions, pipelines from forks are no longer triggered automatically. Learn more.

If the changes appear safe, you can manually trigger the pipeline by commenting /AzurePipelines run.

mjbvz
mjbvz previously approved these changes Sep 9, 2025
@vs-code-engineering
Copy link

⚠️ This PR originates from a fork. Due to security restrictions, pipelines from forks are no longer triggered automatically. Learn more.

If the changes appear safe, you can manually trigger the pipeline by commenting /AzurePipelines run.

@hawkticehurst
Copy link
Member Author

@aeschli @bpasero reverted the old CSS change and made some updates. Not quite sure if this was the direction you were thinking, but was my attempt at still having declarative color tokens inside the theme file and making sure that the color changes only get applied when forced colors is active.

Bonus: Since system colors are finite, I also added typing so that autocomplete / intellisense kicks in nicely when adding new tokens in the future.

Let me know what you think and if you'd like me to go a different direction instead.

@hawkticehurst
Copy link
Member Author

Oh two more things:

  1. I included the changes to fix A11y: Fix code selection high contrast color mappings #265430 as well –– if you're happy with this PR, I'll close the other one, rename this one, and let it resolve both issues.
  2. I'm not actually sure how to test / validate these changes beyond your reviews. As @aeschli mentioned VS Code does support forced colors mode, but I also learned recently from @hediet that the Monaco Editor Playground debug task has been broken for awhile and will probably get removed. Any thoughts or do we just release this to Insiders and test in the browser-based playground via the latest release dropdown?

bhavyaus
bhavyaus previously approved these changes Sep 9, 2025
@vs-code-engineering
Copy link

⚠️ This PR originates from a fork. Due to security restrictions, pipelines from forks are no longer triggered automatically. Learn more.

If the changes appear safe, you can manually trigger the pipeline by commenting /AzurePipelines run.

@hawkticehurst hawkticehurst marked this pull request as draft September 10, 2025 00:14
@hawkticehurst hawkticehurst marked this pull request as ready for review September 10, 2025 12:59
@vs-code-engineering
Copy link

⚠️ This PR originates from a fork. Due to security restrictions, pipelines from forks are no longer triggered automatically. Learn more.

If the changes appear safe, you can manually trigger the pipeline by commenting /AzurePipelines run.

@aeschli
Copy link
Contributor

aeschli commented Sep 11, 2025

I talked to @hediet about whether we should do the same as in VS Code and define
.monaco-editor { forced-color-adjust: none; }
That means we rely on the colors that we have in our own high contrast theme.
If there are users that want system colors, we should plan more time to define a new theme that just uses the system colors.

@meganrogge
Copy link
Contributor

@aeschli can that work be deferred so we can fix this bug by the deadline?

We could also wait until or if users ask for what you're suggesting to implement that.

@aeschli
Copy link
Contributor

aeschli commented Sep 14, 2025

adding .monaco-editor { forced-color-adjust: none; } is the simplest fix. It brings Monaco en par with we do in VS Code. Properly supporting (and maintaining) a forced color theme is not trivial. Needs more work and testing (and maintenance)

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes high contrast color mapping issues in the find widget by adding forced colors media query handling. It ensures that when Windows high contrast themes are active, VS Code's built-in high contrast themes are used instead of the OS forcing system colors on Monaco editor components.

  • Adds forced-colors media query detection to disable OS color forcing
  • Applies forced-color-adjust: none to Monaco editor components when high contrast is active

@hawkticehurst hawkticehurst changed the title A11y: Fix find widget high contrast color mappings A11y: Disable forced color adjustment for Monaco editor Sep 22, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

@meganrogge meganrogge enabled auto-merge (squash) September 22, 2025 17:21
@meganrogge meganrogge merged commit 65d6a4d into microsoft:main Sep 22, 2025
17 checks passed
@hawkticehurst hawkticehurst deleted the find-widget-hc-fix branch September 22, 2025 17:25
this._onOSSchemeChanged();
// Always rebuild the generated CSS so that the `forced-color-adjust: none`
// rule is added/removed reactively when the OS forced colors state changes.
this._updateThemeOrColorMap();
Copy link
Contributor

Choose a reason for hiding this comment

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

Is that necessary? I think that's already triggered from_onOSSchemeChanged when needed

// If the OS has forced-colors active, disable forced color adjustment for
// Monaco editor elements so that VS Code's built-in high contrast themes
// (hc-black / hc-light) are used instead of the OS forcing system colors.
if (mainWindow.matchMedia(`(forced-colors: active)`).matches) {
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to check that, 'forced-color-adjust: none;' can be added also when forced colors are off, it has no effect then.
See how it is done for VS Code:

ruleCollector.addRule(`.monaco-workbench { forced-color-adjust: none; }`);

aeschli added a commit that referenced this pull request Sep 24, 2025
aeschli added a commit that referenced this pull request Sep 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment