Skip to content

Add colorblind mode setting#1545

Open
TimCrooker wants to merge 4 commits intopingdotgg:mainfrom
TimCrooker:feat/colorblind-diff-colors
Open

Add colorblind mode setting#1545
TimCrooker wants to merge 4 commits intopingdotgg:mainfrom
TimCrooker:feat/colorblind-diff-colors

Conversation

@TimCrooker
Copy link
Copy Markdown

@TimCrooker TimCrooker commented Mar 29, 2026

What Changed

Added an opt-in Colorblind mode toggle in Settings > General. When enabled, all places where red and green appear side by side to distinguish additions from deletions switch to blue/orange instead.

This uses a CSS-first approach: toggling a colorblind-mode class on :root and defining scoped overrides in index.css. This is the same pattern as the high-contrast mode proposal in #1284, and both can coexist cleanly (:root.colorblind-mode.high-contrast just applies both rule sets).

What colorblind mode is NOT

It is not a global theme override. --success and --destructive are intentionally left untouched at the root level. Red is fine for error messages, delete buttons, and warnings because those don't appear next to green. The problem is specifically red next to green in comparative contexts (additions vs deletions), so the override is scoped only to those elements.

Areas covered

  • Diff panel -- line backgrounds, emphasis highlights, and -N/+N header stats (via @pierre/diffs CSS variable overrides)
  • DiffStatLabel -- the +additions / -deletions text in chat messages
  • GitActionsControl -- per-file and total +insertions / -deletions in the commit dialog

Color palette

From GitHub's Primer design system (@primer/primitives diffBlob tokens), the most widely deployed colorblind-friendly diff palette in production.

Addition (blue) Deletion (orange)
Light #0969da #bc4c00
Dark #388bfd #db6d28

References:

Why

I'm colorblind. Red and green look the same to me, which makes diffs and stats hard to read.

Closes #1537

Compatibility with #1284

This PR follows the exact same architecture as the high-contrast mode proposal:

  • Root CSS class toggle (colorblind-mode class on <html>)
  • All color overrides in index.css (single source of truth)
  • Early sync read in main.tsx to prevent FOUC
  • Runtime sync via useEffect in the root route
  • Both settings compose naturally as independent root classes

A future unified appearance system would just manage which root classes are active.

UI Changes

Settings toggle (off by default):

Screenshot 2026-03-29 at 12 49 17 PM Screenshot 2026-03-29 at 12 49 21 PM

Diff panel -- default (red/green) vs colorblind mode (blue/orange):

Screenshot 2026-03-29 at 12 50 06 PM Screenshot 2026-03-29 at 12 50 15 PM

Diff stats in chat -- default vs colorblind mode:

Screenshot 2026-03-29 at 12 50 26 PM Screenshot 2026-03-29 at 12 50 38 PM

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Low Risk
Low risk: UI-only setting that swaps diff/stat color tokens via CSS and a root class, with no data/auth logic changes. Main risk is visual regressions or missing overrides in some diff contexts.

Overview
Adds an opt-in Colorblind mode client setting (colorblindMode, default false) with a new toggle in Settings → General, tracked in the “restore defaults” dirty list.

When enabled, the app toggles a colorblind-mode class on :root (applied early in main.tsx to avoid FOUC and kept in sync from __root.tsx) and introduces CSS variables/classes in index.css to render addition/deletion comparisons as blue/orange.

Updates diff-related UI to use these overrides: DiffPanel now generates @pierre/diffs unsafeCSS based on the setting, and diff stat displays in GitActionsControl and chat DiffStatLabel switch from Tailwind success/destructive classes to new .diff-stat-addition/.diff-stat-deletion classes; tests cover the new default and ensure legacy settings migration does not attempt to migrate the new key.

Written by Cursor Bugbot for commit ed8e1e5. This will update automatically on new commits. Configure here.

Note

Add colorblind mode setting with blue/orange diff colors

  • Adds a colorblindMode boolean to ClientSettingsSchema (default false) and a toggle in the General settings panel.
  • Introduces .diff-stat-addition and .diff-stat-deletion CSS classes in index.css that swap to blue/orange under a colorblind-mode root class; diff panel colors are also dynamically generated via buildDiffPanelCss.
  • Applies the stored setting at startup in main.tsx and syncs the root class reactively via a ColorblindModeSync component in __root.tsx.
  • Updates diff stat labels in GitActionsControl and DiffStatLabel to use the new classes instead of text-success/text-destructive.

Macroscope summarized ed8e1e5.

Toggle a root CSS class to swap red/green with blue/orange in diff
contexts (panel backgrounds, header stats, inline stat labels). Colors
from GitHub Primer's @primer/primitives diffBlob tokens. Follows the
same root-class pattern as the high-contrast mode proposal (pingdotgg#1284).

Closes pingdotgg#1537
Copilot AI review requested due to automatic review settings March 29, 2026 17:19
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 29, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e9cf20a8-bd90-413b-8ef6-858047550a41

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Mar 29, 2026
Copy link
Copy Markdown
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

Adds an opt-in Colorblind mode client setting that swaps red/green comparative diff colors to a blue/orange palette by toggling a root CSS class and applying scoped CSS/variable overrides.

Changes:

  • Extend client settings schema with colorblindMode (default false) and add contract/unit coverage.
  • Apply colorblind-mode root class at startup and keep it in sync at runtime via the root route.
  • Update diff/stat UI to use new CSS hooks and update diff panel CSS variable overrides when enabled.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/contracts/src/settings.ts Adds colorblindMode to ClientSettingsSchema with a decoding default.
packages/contracts/src/settings.test.ts Verifies DEFAULT_CLIENT_SETTINGS.colorblindMode defaults to false.
apps/web/src/hooks/useSettings.ts Adds helpers to toggle the root class and read the persisted value early.
apps/web/src/hooks/useSettings.test.ts Ensures legacy migration patch does not attempt to migrate colorblindMode.
apps/web/src/main.tsx Applies colorblind mode before first React render to avoid a flash.
apps/web/src/routes/__root.tsx Keeps the root class synced with live settings via an effect.
apps/web/src/index.css Defines blue/orange variables under :root.colorblind-mode and stat color classes.
apps/web/src/components/settings/SettingsPanels.tsx Adds Settings > General toggle + restore-defaults detection for the new setting.
apps/web/src/components/chat/DiffStatLabel.tsx Uses new stat CSS classes so the palette can be overridden by colorblind mode.
apps/web/src/components/GitActionsControl.tsx Uses new stat CSS classes for per-file/total insertions/deletions.
apps/web/src/components/DiffPanel.tsx Dynamically switches @pierre/diffs override variables based on the setting.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Fix diff-stat default colors to use --color-success/--color-destructive
(matching text-success/text-destructive) instead of the -foreground
variants. Add try/catch around getStoredColorblindMode to prevent
malformed localStorage from crashing startup. Merge duplicate imports.
@TimCrooker
Copy link
Copy Markdown
Author

@juliusmarminge Rewrote this to follow the same root-class pattern as #1284. Toggles colorblind-mode on :root, all overrides in index.css, early sync read to prevent FOUC, runtime sync in the root route. Both compose cleanly as independent root classes.

The one intentional difference: colorblind mode only overrides diff-specific elements, not --success/--destructive globally. Red is fine for errors and delete buttons on their own. The problem is only when red and green appear side by side in comparative contexts like diffs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Add colorblind-friendly diff colors setting

2 participants