├── CHANGELOG.md ├── README.md ├── UNLICENSE ├── USERS.md ├── colors ├── alacritty.sh ├── ansi.sh ├── cmd.ps1 ├── colors.sh ├── contrast.sh ├── demo.sh ├── foot.sh ├── ghostty.sh ├── iterm2.sh ├── konsole.sh └── xresources.sh └── data ├── HISTORY.md ├── starlight.png ├── v1.png ├── v2.png └── v3.png /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | Documentation on how the colors were determined in every version, along with the changes. 3 | For how they all look, you can see the [history file](data/HISTORY.md) 4 | 5 | ## V4 6 | V4 is a reimagining of starlight using the LCH color space. 7 | The comments in particular were regarding the accessibility (lack of contrast) of red and magenta. 8 | After some testing, WCAG AAA is not a particularly big deal, but a contrast ratio of at least 4 is highly recommendable. 9 | With some math and focus group testing, 10 | I determined that highly variable lightness values are somewhat inevitable when catering to color blindnesses: 11 | in part because they're what permit colorblind people to differentiate the colors, 12 | and in part because of the need to fit into sRGB. 13 | 14 | The new colors aim for an LCH L of 65 for the basic version and 75 for the bright version. 15 | Additionally, bright versions are hue-shifted right by 10. 16 | Chroma values are either 40, 60, or 80, depending on sRGB and colorblindness constraints. 17 | 18 | That said, the new colors are (L, C, H): 19 | * Red: 55, 80, 20 and 60, 80, 30. 20 | The lightness needed to be reduced to fit into sRGB, but be high enough to remain legible. 21 | For bright red, it looked different enough at 60, so it was kept to remain mostly within sRGB. 22 | * Green: 65, 80, 130 and 75, 80, 140. 23 | * Yellow: 80, 80, 90 and 90, 80, 100. 24 | * Blue: 65, 40, 230 and 75, 40, 240. 25 | The chromacity had to be reduced to fit into sRGB. 26 | * Magenta: 80, 45, 320 and 80, 45, 330. 27 | Unfortuately, magenta is right between two problem colors (blue and red). 28 | In the end, I got out of it by going the pastel route, making them soft 29 | and differentiable via luminosity. 30 | * Cyan: 70, 50, 170 and 80, 50, 180. 31 | The chromacity had to be reduced to fit into sRGB. 32 | The hue and lightness had to be further played around with to accomodate color blindness. 33 | 34 | The white and black values were left alone, as no one had issues with them. 35 | They may be changed in a patch. 36 | 37 | ## V3 38 | We use black as the background, and move old brblack into black. 39 | We then make brblack more of a gray. 40 | Since old brblack is 14% L, we double that to a 38% for the new brblack. 41 | This gives us a black of `#242424` and a brblack of `#616161`, 42 | with background being equivalent to `black`. 43 | 44 | ## V2 45 | Tweak green to be more easily differentiable from yellow using HSV. 46 | First, make it complimentary to yellow (hue of 132). 47 | Regular version is set to a saturation of 60 and value of 80. 48 | Bright version is set to a saturation and value of 90. 49 | 50 | ## V1 51 | Non black/white colors are picked mathematically using a six-tone model, then tweaked individually by HSL. 52 | On the baseline, the hue used to generate the six tones is 180, the saturation 80-100 (regular/bright) and lightness +/-5% (45-55, regular/bright). 53 | 54 | * Red is tweaked away from blue, to a hue of 195. 55 | * Green is too vibrant, so the regular saturation is pushed down to 70. 56 | * Yellow is not as easily differentiable, so the bright version is tweaked towards green (185). 57 | * Blue is illegible, so it's tweaked towards green, to 165. 58 | * Regular blue is also bumped up to 90 saturation, to compensate for the extra effect lightness has. 59 | * Magenta is tweaked away from blue, to 195, lower saturation (70-90) and higher in lightness to compensate (0-10). 60 | * Cyan is tweaked similar to blue hue-wise (to 165), but is otherwise normal. 61 | 62 | Black and white are then hand-picked just to be mostly pleasant on the eyes. 63 | We use bright black and bright white for background/foreground. 64 | Both black and white are defined by hsl L % (with H and S both being 0). 65 | 66 | Black: 5% and 14%. 67 | White: 90% and 100%. 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Starlight 2 | Starlight is an ansi color theme focused on usability. 3 | 4 | It was made after I made the discovery[^1] that I have a color perception deficiency: I have trouble differentiating between hues of blue (a greater one than the average person, making it impossible for me to read typical default blue text on black backgrounds). 5 | I also have a mild deficiency along the same lines for red, but not nearly as bad. 6 | I set out to make a high contrast theme that would work for me (a non-normative survey helped discover that some others have no issues with this content, while a few others do still struggle, but due to not struggling as much as I do, they simply live with it). 7 | [^1]: I now have an actual diagnosis: tritanomaly. It's sufficiently rare that health professionals where I live do not screen for it when checking for colorblindness. 8 | 9 | This repository is me sharing it. 10 | 11 | You can find the exact rgb data in `colors/colors.sh`. 12 | Other files inside of `colors/*.sh` are generators for various applications I use. 13 | The goal is for me to only need to modify `colors/colors.sh` and the explanation/implementation section whenever I make adjustments. 14 | 15 | ## Screenshots 16 | ![Starlight](data/starlight.png) 17 | 18 | ## Users 19 | You can find a list of things using starlight in the [USERS](USERS.md) file. 20 | 21 | ## Goals 22 | * All base colors (black, red, green, yellow, blue, magenta, cyan, white) should be easily uniquely identifiable. 23 | * Bright variants should be identifiable side by side, but do not need to be uniquely identifiable. 24 | * Text in any color (except black) should be legible on the black, even when not bold. 25 | 26 | See the [CHANGELOG](CHANGELOG.md) to see implementation details. 27 | 28 | ## As Template 29 | A lot of the tooling present is usable as a template for other ansi color schemes. 30 | To use it this way, modify `colors.sh` and set your own colors, re-using all of the other scripts as-is. 31 | Don't forget to add a screenshot to `data/` and modify the README! 32 | -------------------------------------------------------------------------------- /UNLICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /USERS.md: -------------------------------------------------------------------------------- 1 | # Users 2 | The following projects use starlight, grouped by use type, in alphabetical order. 3 | 4 | ## As an ANSI theme 5 | A star (*) indicates that a version of starlight is the default theme. 6 | 7 | * the [foot](https://codeberg.org/dnkl/foot) terminal emulator* 8 | 9 | ## As a palette base for a theme 10 | 11 | * the [helix](https://helix-editor.com) editor ([starlight.toml](https://github.com/helix-editor/helix/blob/master/runtime/themes/starlight.toml)) 12 | -------------------------------------------------------------------------------- /colors/alacritty.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./colors.sh 3 | 4 | cat < b) { 29 | return (a + 0.05) / (b + 0.05) 30 | } else { 31 | return (b + 0.05) / (a + 0.05) 32 | } 33 | } 34 | contrast($(lightness $(coldec $1)), $(lightness $(coldec $2))) 35 | EOF 36 | } 37 | 38 | [ $# -lt 0 ] || set -- \ 39 | red green yellow blue magenta cyan white \ 40 | brred brgreen bryellow brblue brmagenta brcyan brwhite 41 | 42 | # lower: error if below this 43 | lower=4 44 | # higher: warn if below this 45 | higher=7 46 | 47 | reprint() { 48 | printf '%s%s' "$@" "$(reset)" 49 | } 50 | 51 | demo() { 52 | reprint "$(fgc $1)$(bgc $2) demo text " 53 | } 54 | 55 | gt() { 56 | test -n "$(printf 'if (%s > %s) 1' "$1" "$2" | bc)" 57 | } 58 | 59 | for i; do 60 | color=$(eval echo '$'$i) 61 | value=$(contrast $background $color) 62 | if gt "$lower" "$value"; then 63 | # fail 64 | reprint "$(acol 31)fail" 65 | elif gt "$higher" "$value"; then 66 | # warn 67 | reprint "$(acol 33)warn" 68 | else 69 | # pass 70 | reprint "$(acol 32)pass" 71 | fi 72 | printf ': #%s at %s\t%s (%s)\n' \ 73 | "$color" "$value" "$(demo $color $background)" "$i" 74 | done 75 | -------------------------------------------------------------------------------- /colors/demo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./ansi.sh 3 | # demo as in starlight.png 4 | # requires truecolor 5 | 6 | # for every color: 7 | # color, bright color | bold color, bright bold color 8 | 9 | # loop 10 | demopart() { 11 | eval fgc '$'"$1" 12 | if [ $# -gt 1 ]; then 13 | bold 14 | printf 'bold ' 15 | fi 16 | # 9 is the length of brmagenta 17 | printf '%-9s' "$1" 18 | reset 19 | bgc $background 20 | } 21 | 22 | demo() { 23 | for col in black red green yellow blue magenta cyan white; do 24 | printf '%b %b | %b %b\n' "$(demopart $col)" "$(demopart br$col)" \ 25 | "$(demopart $col bold)" "$(demopart br$col bold)" 26 | done 27 | } 28 | 29 | . ./colors.sh 30 | bgc $background 31 | demo 32 | reset 33 | -------------------------------------------------------------------------------- /colors/foot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./colors.sh 3 | 4 | cat < 29 | dict() { 30 | _dict_r=$(d2r $(h2d $(extract $1 R))) 31 | _dict_g=$(d2r $(h2d $(extract $1 G))) 32 | _dict_b=$(d2r $(h2d $(extract $1 B))) 33 | 34 | cat < 36 | Color Space 37 | sRGB 38 | 39 | Alpha Component 40 | 1 41 | 42 | Red Component 43 | $_dict_r 44 | 45 | Green Component 46 | $_dict_g 47 | 48 | Blue Component 49 | $_dict_b 50 | 51 | HEREDOC 52 | } 53 | 54 | cat < 56 | 57 | 58 | 59 | Theme Name 60 | $theme 61 | 62 | Ansi 0 Color 63 | $(dict $black) 64 | 65 | Ansi 1 Color 66 | $(dict $red) 67 | 68 | Ansi 2 Color 69 | $(dict $green) 70 | 71 | Ansi 3 Color 72 | $(dict $yellow) 73 | 74 | Ansi 4 Color 75 | $(dict $blue) 76 | 77 | Ansi 5 Color 78 | $(dict $magenta) 79 | 80 | Ansi 6 Color 81 | $(dict $cyan) 82 | 83 | Ansi 7 Color 84 | $(dict $white) 85 | 86 | Ansi 8 Color 87 | $(dict $brblack) 88 | 89 | Ansi 9 Color 90 | $(dict $brred) 91 | 92 | Ansi 10 Color 93 | $(dict $brgreen) 94 | 95 | Ansi 11 Color 96 | $(dict $bryellow) 97 | 98 | Ansi 12 Color 99 | $(dict $brblue) 100 | 101 | Ansi 13 Color 102 | $(dict $brmagenta) 103 | 104 | Ansi 14 Color 105 | $(dict $brcyan) 106 | 107 | Ansi 15 Color 108 | $(dict $brwhite) 109 | 110 | Background Color 111 | $(dict $background) 112 | 113 | Foreground Color 114 | $(dict $foreground) 115 | 116 | Selected Text Color 117 | $(dict $background) 118 | 119 | Selection Color 120 | $(dict $foreground) 121 | 122 | Cursor Color 123 | $(dict $foreground) 124 | 125 | Cursor Text Color 126 | $(dict $background) 127 | 128 | Link Color 129 | $(dict $brblue) 130 | 131 | 132 | HEREDOC 133 | -------------------------------------------------------------------------------- /colors/konsole.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . ./colors.sh 3 | 4 | # $1 is the combined value 5 | # $2 is R, G or B 6 | extract() { 7 | case "$2" in 8 | R) awk "BEGIN{print substr(\"$1\", 1, 2)}" ;; 9 | G) awk "BEGIN{print substr(\"$1\", 3, 2)}" ;; 10 | B) awk "BEGIN{print substr(\"$1\", 5, 2)}" ;; 11 | *) return 1 ;; 12 | esac 13 | } 14 | 15 | # hex 2 decimal 16 | # $1 is a number in hex 17 | h2d() { 18 | printf '%d' 0x"$1" 19 | } 20 | 21 | # $1: color value 22 | # prints r,g,b 23 | rgb() { 24 | _rgb_r=$(h2d $(extract $1 R)) 25 | _rgb_g=$(h2d $(extract $1 G)) 26 | _rgb_b=$(h2d $(extract $1 B)) 27 | echo $_rgb_r,$_rgb_g,$_rgb_b 28 | } 29 | 30 | cat <