feat(linter): add opt-in color-blind contrast lint rule#133
Open
mvanhorn wants to merge 1 commit into
Open
Conversation
Adds a color-blind-contrast rule that simulates protanopia, deuteranopia, and tritanopia, re-runs the component backgroundColor/textColor contrast check on the simulated colors, and warns below a 3:1 floor. Off by default; activated via a new --cvd flag on the lint command. Fixes google-labs-code#48
rajpratham1
approved these changes
Jun 27, 2026
rajpratham1
left a comment
There was a problem hiding this comment.
This is a thoughtful accessibility enhancement that introduces an opt-in color-blind contrast lint rule without changing the default linting behavior. The implementation is modular, integrates cleanly with the existing rule system, exposes the feature through a CLI flag, and includes good test coverage to verify both the rule itself and that it remains disabled by default.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
design.md lintchecks componentbackgroundColor/textColorpairs against WCAG AA as perceived by full-color vision. This adds an opt-incolor-blind-contrastrule, enabled with a new--cvdflag, that re-runs the contrast check under simulated protanopia, deuteranopia, and tritanopia and warns when a simulated pair drops below 3:1. It is off by default, so existinglintoutput is unchanged.Why this matters
A pair that clears AA for full-color vision can still collapse for the roughly 5-10% of users with congenital color-vision deficiency, because the only cue is a hue shift those users do not see. The worked example from #48: brand orange
#E44001on white is 4.17:1, an AA near-miss the baseline rule already reports, but 2.92:1 under protanopia and 2.31:1 under deuteranopia. The opt-in rule surfaces exactly those two failures the default check never sees.Demo
Simulated Demo (HyperFrames):
Changes
color-blind-contrastrule mirrors the existingcontrast-ratiorule and reusesparseColor/contrastRatiofor the simulated colors, so there is no duplicated color math. Simulation applies the Brettel-Vienot-Mollon matrices to eachResolvedColor, then re-parses the result to recover WCAG luminance.--cvdcomposes the rule ontoDEFAULT_RULE_DESCRIPTORSfor that run. The rule is exported for selective composition but deliberately kept out of the default set, so defaultlintoutput is byte-identical.Testing
bun test: 285 pass, 1 skip, 0 fail. New tests cover the Feature: color-blind contrast lint rule (opt-in, Brettel-Viénot-Mollon simulation) #48 worked example, a CVD-safe pair, and the rule's absence from the default rule set.bun run lintandbun run buildpass clean.design.md lint --cvdon a#E44001-on-white button reproduces the issue's exact figures (protanopia 2.92:1 on#9d9c10, deuteranopia 2.31:1 on#a7b314); without--cvdthe output is unchanged.Fixes #48