Repository: electron/electron
Pull request: feat: add accessibilityDisplayShouldDifferentiateWithoutColor on macOS

#### Description of Change

Adds `nativeTheme.shouldDifferentiateWithoutColor` on macOS that maps to the `accessibilityDisplayShouldDifferentiateWithoutColor` property on `NSWorkspace`. If `true`, the user has indicated that they prefer UI that differentiates items with something other than color alone. This is useful for users with color vision deficiency.

For example, an app like Linear might use this to automatically show diffs in a way that that deemphasizes usage of red and green to indicate removals and additions.

A somewhat equivalent media query has been discussed, fwiw: https://github.com/w3c/csswg-drafts/issues/10335

#### Checklist

- [x] PR description included
- [x] I have built and tested this PR
- [x] `npm test` passes
- [x] tests are [~changed~ or added](https://github.com/electron/electron/blob/main/docs/development/testing.md)
- [x] relevant API documentation, tutorials, and examples are updated and follow the [documentation style guide](https://github.com/electron/electron/blob/main/docs/development/style-guide.md)
- [x] [PR release notes](https://github.com/electron/clerk/blob/main/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/main/README.md#examples).

#### Release Notes

Notes: Added nativeTheme.shouldDifferentiateWithoutColor on macOS 

Changed files:
filename: docs/api/native-theme.md
patch: @@ -84,3 +84,7 @@ Currently, Windows high contrast is the only system setting that triggers forced
 ### `nativeTheme.prefersReducedTransparency` _Readonly_
 
 A `boolean` that indicates whether the user has chosen via system accessibility settings to reduce transparency at the OS level.
+
+### `nativeTheme.shouldDifferentiateWithoutColor` _macOS_ _Readonly_
+
+A `boolean` that indicates whether the user prefers UI that differentiates items using something other than color alone (e.g. shapes or labels). This maps to [NSWorkspace.accessibilityDisplayShouldDifferentiateWithoutColor](https://developer.apple.com/documentation/appkit/nsworkspace/accessibilitydisplayshoulddifferentiatewithoutcolor).

filename: shell/browser/api/electron_api_native_theme.cc
patch: @@ -147,7 +147,12 @@ gin::ObjectTemplateBuilder NativeTheme::GetObjectTemplateBuilder(
                    &NativeTheme::ShouldUseInvertedColorScheme)
       .SetProperty("inForcedColorsMode", &NativeTheme::InForcedColorsMode)
       .SetProperty("prefersReducedTransparency",
-                   &NativeTheme::GetPrefersReducedTransparency);
+                   &NativeTheme::GetPrefersReducedTransparency)
+#if BUILDFLAG(IS_MAC)
+      .SetProperty("shouldDifferentiateWithoutColor",
+                   &NativeTheme::ShouldDifferentiateWithoutColor)
+#endif
+      ;
 }
 
 const char* NativeTheme::GetTypeName() {

filename: shell/browser/api/electron_api_native_theme.h
patch: @@ -56,6 +56,9 @@ class NativeTheme final : public gin_helper::DeprecatedWrappable<NativeTheme>,
   bool ShouldUseInvertedColorScheme();
   bool InForcedColorsMode();
   bool GetPrefersReducedTransparency();
+#if BUILDFLAG(IS_MAC)
+  bool ShouldDifferentiateWithoutColor();
+#endif
 
   // ui::NativeThemeObserver:
   void OnNativeThemeUpdated(ui::NativeTheme* theme) override;

filename: shell/browser/api/electron_api_native_theme_mac.mm
patch: @@ -26,4 +26,9 @@
   [[NSApplication sharedApplication] setAppearance:new_appearance];
 }
 
+bool NativeTheme::ShouldDifferentiateWithoutColor() {
+  return [[NSWorkspace sharedWorkspace]
+      accessibilityDisplayShouldDifferentiateWithoutColor];
+}
+
 }  // namespace electron::api

filename: spec/api-native-theme-spec.ts
patch: @@ -6,6 +6,7 @@ import { once } from 'node:events';
 import * as path from 'node:path';
 import { setTimeout } from 'node:timers/promises';
 
+import { ifdescribe } from './lib/spec-helpers';
 import { closeAllWindows } from './lib/window-helpers';
 
 describe('nativeTheme module', () => {
@@ -119,4 +120,10 @@ describe('nativeTheme module', () => {
       expect(nativeTheme.prefersReducedTransparency).to.be.a('boolean');
     });
   });
+
+  ifdescribe(process.platform === 'darwin')('nativeTheme.shouldDifferentiateWithoutColor', () => {
+    it('returns a boolean', () => {
+      expect(nativeTheme.shouldDifferentiateWithoutColor).to.be.a('boolean');
+    });
+  });
 });