-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add color blind accessibility command suite #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
HeyItsGilbert
merged 3 commits into
main
from
claude/terminal-color-accessibility-gC1q2
Mar 13, 2026
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| # Okabe-Ito palette: peer-reviewed, safe across all common colorblindness types. | ||
| # Source: https://jfly.uni-koeln.de/color/ | ||
| $script:OKABE_ITO = @{ | ||
| Black = @{ R = 0; G = 0; B = 0 } | ||
| Orange = @{ R = 230; G = 159; B = 0 } | ||
| SkyBlue = @{ R = 86; G = 180; B = 233 } | ||
| BluishGreen = @{ R = 0; G = 158; B = 115 } | ||
| Yellow = @{ R = 240; G = 228; B = 66 } | ||
| Blue = @{ R = 0; G = 114; B = 178 } | ||
| Vermillion = @{ R = 213; G = 94; B = 0 } | ||
| ReddishPurple = @{ R = 204; G = 121; B = 167 } | ||
| } | ||
|
|
||
| function Get-ColorBlindPaletteData { | ||
| <# | ||
| .SYNOPSIS | ||
| Returns the RGB color table for a named color blind profile. | ||
|
|
||
| .DESCRIPTION | ||
| Returns a hashtable of named color entries (each with R, G, B keys) for the specified | ||
| color blindness profile. All profiles are derived from the Okabe-Ito palette, adjusted | ||
| per the specific perceptual needs of each condition. | ||
|
|
||
| .PARAMETER ProfileType | ||
| The color blindness profile to retrieve. Valid values: Deuteranopia, Protanopia, | ||
| Tritanopia, Achromatopsia, AccessibleDefault. | ||
|
|
||
| .EXAMPLE | ||
| Get-ColorBlindPaletteData -ProfileType Deuteranopia | ||
| #> | ||
| param ( | ||
| [Parameter(Mandatory = $true)] | ||
| [ValidateSet('Deuteranopia', 'Protanopia', 'Tritanopia', 'Achromatopsia', 'AccessibleDefault')] | ||
| [string]$ProfileType | ||
| ) | ||
|
|
||
| switch ($ProfileType) { | ||
| 'Deuteranopia' { | ||
| # Red-green deficiency (most common). Maximize blue/orange/yellow contrast. | ||
| # Red and green are shifted to orange and blue respectively. | ||
| @{ | ||
| Error = $script:OKABE_ITO.Vermillion # Vermillion (not red) | ||
|
Check warning on line 42 in Accessibility/Private/Get-ColorBlindPaletteData.ps1
|
||
| Warning = $script:OKABE_ITO.Orange # Orange | ||
| Success = $script:OKABE_ITO.Blue # Blue (not green) | ||
| Info = $script:OKABE_ITO.SkyBlue # Sky Blue | ||
| Highlight = $script:OKABE_ITO.Yellow # Yellow | ||
| Accent = $script:OKABE_ITO.ReddishPurple # Reddish Purple | ||
| Text = $script:OKABE_ITO.Black # Black | ||
| Muted = @{ R = 120; G = 120; B = 120 } # Mid-gray (not part of Okabe-Ito) | ||
| } | ||
| } | ||
| 'Protanopia' { | ||
| # Red-weak (cannot perceive red). Red-range hues shifted further toward orange/yellow. | ||
| @{ | ||
| Error = @{ R = 230; G = 159; B = 0 } # Orange (red is invisible) | ||
| Warning = @{ R = 240; G = 228; B = 66 } # Yellow | ||
| Success = @{ R = 0; G = 114; B = 178 } # Blue | ||
| Info = @{ R = 86; G = 180; B = 233 } # Sky Blue | ||
| Highlight = @{ R = 204; G = 121; B = 167 } # Reddish Purple | ||
| Accent = @{ R = 0; G = 158; B = 115 } # Bluish Green | ||
| Text = @{ R = 0; G = 0; B = 0 } # Black | ||
| Muted = @{ R = 120; G = 120; B = 120 } # Mid-gray | ||
| } | ||
| } | ||
| 'Tritanopia' { | ||
| # Blue-yellow deficiency. Shift to red/green contrast; replace blue with high-contrast cyan. | ||
| @{ | ||
| Error = @{ R = 213; G = 94; B = 0 } # Vermillion | ||
| Warning = @{ R = 204; G = 121; B = 167 } # Reddish Purple (not yellow) | ||
| Success = @{ R = 0; G = 158; B = 115 } # Bluish Green | ||
| Info = @{ R = 0; G = 200; B = 200 } # Cyan (high contrast, not pure blue) | ||
| Highlight = @{ R = 255; G = 100; B = 100 } # Light Red (visible to tritanopes) | ||
| Accent = @{ R = 180; G = 60; B = 60 } # Dark Red | ||
| Text = @{ R = 0; G = 0; B = 0 } # Black | ||
| Muted = @{ R = 120; G = 120; B = 120 } # Mid-gray | ||
| } | ||
| } | ||
| 'Achromatopsia' { | ||
| # Full colorblindness. High-contrast grayscale ladder designed for strong separation between steps. | ||
| @{ | ||
| Error = @{ R = 30; G = 30; B = 30 } # Near-black (on white bg) | ||
| Warning = @{ R = 80; G = 80; B = 80 } # Dark gray | ||
| Success = @{ R = 50; G = 50; B = 50 } # Dark gray variant | ||
| Info = @{ R = 110; G = 110; B = 110 } # Medium gray | ||
| Highlight = @{ R = 230; G = 230; B = 230 } # Near-white | ||
| Accent = @{ R = 0; G = 0; B = 0 } # Black | ||
| Text = @{ R = 0; G = 0; B = 0 } # Black | ||
| Muted = @{ R = 160; G = 160; B = 160 } # Light gray | ||
| } | ||
| } | ||
| 'AccessibleDefault' { | ||
| # Okabe-Ito as-is: a safe general baseline for users unsure of their type. | ||
| @{ | ||
| Error = @{ R = 213; G = 94; B = 0 } # Vermillion | ||
| Warning = @{ R = 230; G = 159; B = 0 } # Orange | ||
| Success = @{ R = 0; G = 158; B = 115 } # Bluish Green | ||
| Info = @{ R = 86; G = 180; B = 233 } # Sky Blue | ||
| Highlight = @{ R = 240; G = 228; B = 66 } # Yellow | ||
| Accent = @{ R = 0; G = 114; B = 178 } # Blue | ||
| Text = @{ R = 0; G = 0; B = 0 } # Black | ||
| Muted = @{ R = 120; G = 120; B = 120 } # Mid-gray | ||
| } | ||
| } | ||
| } | ||
| } | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| function Get-ContrastRatio { | ||
| <# | ||
| .SYNOPSIS | ||
| Calculates the WCAG contrast ratio between two relative luminance values. | ||
|
|
||
| .DESCRIPTION | ||
| Implements the W3C WCAG 2.1 contrast ratio formula. Returns a ratio between 1:1 | ||
| (no contrast) and 21:1 (maximum contrast, black on white). | ||
|
|
||
| .PARAMETER Luminance1 | ||
| Relative luminance of the first color (0.0 to 1.0). | ||
|
|
||
| .PARAMETER Luminance2 | ||
| Relative luminance of the second color (0.0 to 1.0). | ||
|
|
||
| .EXAMPLE | ||
| Get-ContrastRatio -Luminance1 1.0 -Luminance2 0.0 | ||
| # Returns 21.0 (white on black) | ||
|
|
||
| .NOTES | ||
| https://www.w3.org/TR/WCAG21/#dfn-contrast-ratio | ||
| #> | ||
| param ( | ||
| [Parameter(Mandatory = $true)] | ||
| [double]$Luminance1, | ||
| [Parameter(Mandatory = $true)] | ||
| [double]$Luminance2 | ||
| ) | ||
|
|
||
| $lighter = [Math]::Max($Luminance1, $Luminance2) | ||
| $darker = [Math]::Min($Luminance1, $Luminance2) | ||
|
|
||
| return ($lighter + 0.05) / ($darker + 0.05) | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| function Get-RelativeLuminance { | ||
| <# | ||
| .SYNOPSIS | ||
| Calculates the relative luminance of an RGB color per the W3C WCAG 2.1 formula. | ||
|
|
||
| .DESCRIPTION | ||
| Implements the W3C relative luminance formula required for WCAG contrast ratio | ||
| calculations. Returns a value between 0 (black) and 1 (white). | ||
|
|
||
| .PARAMETER R | ||
| Red channel value (0-255). | ||
|
|
||
| .PARAMETER G | ||
| Green channel value (0-255). | ||
|
|
||
| .PARAMETER B | ||
| Blue channel value (0-255). | ||
|
|
||
| .EXAMPLE | ||
| Get-RelativeLuminance -R 0 -G 0 -B 0 | ||
| # Returns 0 (black) | ||
|
|
||
| .EXAMPLE | ||
| Get-RelativeLuminance -R 255 -G 255 -B 255 | ||
| # Returns 1 (white) | ||
|
|
||
| .NOTES | ||
| https://www.w3.org/TR/WCAG21/#dfn-relative-luminance | ||
| #> | ||
| param ( | ||
| [Parameter(Mandatory = $true)] | ||
| [ValidateRange(0, 255)] | ||
| [int]$R, | ||
| [Parameter(Mandatory = $true)] | ||
| [ValidateRange(0, 255)] | ||
| [int]$G, | ||
| [Parameter(Mandatory = $true)] | ||
| [ValidateRange(0, 255)] | ||
| [int]$B | ||
| ) | ||
|
|
||
| $channels = @($R / 255.0, $G / 255.0, $B / 255.0) | ||
| $linearized = $channels | ForEach-Object { | ||
| if ($_ -le 0.04045) { | ||
| $_ / 12.92 | ||
| } else { | ||
| [Math]::Pow(($_ + 0.055) / 1.055, 2.4) | ||
| } | ||
| } | ||
|
|
||
| return (0.2126 * $linearized[0]) + (0.7152 * $linearized[1]) + (0.0722 * $linearized[2]) | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| function ConvertTo-PlainText { | ||
| <# | ||
| .SYNOPSIS | ||
| Strips common ANSI color/style escape codes and PSStyle formatting from a string. | ||
|
|
||
| .DESCRIPTION | ||
| Removes common ANSI/VT100 SGR-style escape sequences (colors, bold, italic, etc.) | ||
| from text, returning clean plain text without those decorations. Useful for | ||
| preparing terminal output for screen readers, plain-text logging, or piping to | ||
| tools that do not handle such escape codes. | ||
|
|
||
| Supports pipeline input. | ||
|
|
||
| .PARAMETER InputText | ||
| The text string to strip of ANSI color/style escape codes. | ||
|
|
||
| .EXAMPLE | ||
| ConvertTo-PlainText -InputText "$($PSStyle.Bold)Hello$($PSStyle.BoldOff) World" | ||
|
|
||
| Returns 'Hello World' with no formatting. | ||
|
|
||
| .EXAMPLE | ||
| ConvertTo-Bionic "The quick brown fox" | ConvertTo-PlainText | ||
|
|
||
| Converts text to bionic format then strips common ANSI color/style escape sequences | ||
| for screen reader use. | ||
|
|
||
| .EXAMPLE | ||
| Get-Content .\log.txt -Raw | ConvertTo-PlainText | ||
|
|
||
| Strips common ANSI color/style escape codes from a log file that may contain | ||
| colored output. | ||
|
|
||
| .NOTES | ||
| https://www.w3.org/WAI/WCAG21/Techniques/general/G166 | ||
| #> | ||
| [CmdletBinding()] | ||
| param ( | ||
| [Parameter( | ||
| Mandatory = $true, | ||
| ValueFromPipeline = $true, | ||
| Position = 0 | ||
| )] | ||
| [string]$InputText | ||
| ) | ||
|
|
||
| process { | ||
| # Matches ESC (0x1B) followed by [ and any sequence of parameter/intermediate bytes and a final byte | ||
| $InputText -replace '\x1B\[[0-9;]*[mABCDEFGHJKSTfhilmnprsu]', '' | ||
| } | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| function Disable-ScreenReaderMode { | ||
| <# | ||
| .SYNOPSIS | ||
| Restores normal ANSI-formatted terminal output after screen reader mode. | ||
|
|
||
| .DESCRIPTION | ||
| Clears the screen reader mode flag set by Enable-ScreenReaderMode, allowing | ||
| Accessibility module commands to resume producing colored and styled terminal | ||
| output using ANSI escape sequences. | ||
|
|
||
| .EXAMPLE | ||
| Disable-ScreenReaderMode | ||
|
|
||
| Deactivates screen reader mode and restores ANSI-formatted output. | ||
|
|
||
| .EXAMPLE | ||
| Enable-ScreenReaderMode | ||
| ConvertTo-Bionic "Example text" | ||
| Disable-ScreenReaderMode | ||
|
|
||
| Temporarily uses screen reader mode for one operation, then restores normal output. | ||
|
|
||
| .NOTES | ||
| https://www.w3.org/WAI/WCAG21/Understanding/non-text-contrast | ||
| #> | ||
| [CmdletBinding()] | ||
| param () | ||
|
|
||
| $script:ScreenReaderMode = $false | ||
|
|
||
| if ($script:PreviousOutputRendering) { | ||
| $PSStyle.OutputRendering = $script:PreviousOutputRendering | ||
| Write-Verbose "Screen reader mode disabled. Previous output rendering restored." | ||
| } | ||
| else { | ||
| # Fallback if no previous output rendering mode was saved. | ||
| $PSStyle.OutputRendering = [System.Management.Automation.OutputRendering]::Host | ||
| Write-Verbose "Screen reader mode disabled. Output rendering set to Host." | ||
| } | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| function Enable-ScreenReaderMode { | ||
| <# | ||
| .SYNOPSIS | ||
| Optimizes terminal output for screen reader assistive technology. | ||
|
|
||
| .DESCRIPTION | ||
| Sets a module-wide flag that signals all Accessibility module commands to produce | ||
| output that is compatible with screen readers: no ANSI color codes, no box-drawing | ||
| characters, simplified structure, and plain descriptive text only. | ||
|
|
||
| Use Disable-ScreenReaderMode to return to normal output mode. | ||
|
|
||
| .EXAMPLE | ||
| Enable-ScreenReaderMode | ||
|
|
||
| Activates screen reader-friendly output mode for all Accessibility module commands. | ||
|
|
||
| .EXAMPLE | ||
| Enable-ScreenReaderMode | ||
| ConvertTo-Bionic "The quick brown fox jumped over the lazy dog." | ||
|
|
||
| Enables screen reader mode then runs a bionic conversion. Output will contain no | ||
| ANSI bold codes, just the plain text result. | ||
|
|
||
| .NOTES | ||
| https://www.w3.org/WAI/WCAG21/Understanding/non-text-contrast | ||
| #> | ||
| [CmdletBinding()] | ||
| param () | ||
|
|
||
| $script:ScreenReaderMode = $true | ||
HeyItsGilbert marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| if (-not (Get-Variable -Name PreviousOutputRendering -Scope Script -ErrorAction SilentlyContinue)) { | ||
| $script:PreviousOutputRendering = $PSStyle.OutputRendering | ||
| } | ||
|
|
||
| $PSStyle.OutputRendering = [System.Management.Automation.OutputRendering]::PlainText | ||
|
|
||
| Write-Verbose "Screen reader mode enabled. ANSI output suppressed." | ||
| } | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| function Export-AccessibilityProfile { | ||
| <# | ||
| .SYNOPSIS | ||
| Exports the current accessibility settings to a JSON file. | ||
|
|
||
| .DESCRIPTION | ||
| Serializes all active accessibility settings (color blind profile, screen reader mode, | ||
| output rendering) to a JSON file at the specified path. The file can later be restored | ||
| using Import-AccessibilityProfile, making it easy to share configurations or persist | ||
| them outside of $PROFILE. | ||
|
|
||
| .PARAMETER Path | ||
| The file path where the JSON settings file should be written. | ||
|
|
||
| .EXAMPLE | ||
| Export-AccessibilityProfile -Path "$HOME\accessibility-settings.json" | ||
|
|
||
| Exports the current settings to a JSON file in the user's home directory. | ||
|
|
||
| .EXAMPLE | ||
| Set-ColorBlindProfile -ProfileType Deuteranopia | ||
| Export-AccessibilityProfile -Path ".\my-profile.json" | ||
|
|
||
| Applies a color profile then exports it to a local file. | ||
|
|
||
| .NOTES | ||
| https://www.w3.org/WAI/WCAG21/Understanding/ | ||
| #> | ||
| [CmdletBinding(SupportsShouldProcess)] | ||
| param ( | ||
| [Parameter(Mandatory = $true, Position = 0)] | ||
| [string]$Path | ||
| ) | ||
|
|
||
| $profile = Get-AccessibilityProfile | ||
|
|
||
| if ($PSCmdlet.ShouldProcess($Path, "Export accessibility settings")) { | ||
| $profile | ConvertTo-Json -Depth 5 | Set-Content -Path $Path -Encoding UTF8 | ||
| Write-Verbose "Accessibility settings exported to: $Path" | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.