From 91f6266b2b7ac582940ca43c2aafb5652c2a37f0 Mon Sep 17 00:00:00 2001 From: silverwind Date: Tue, 2 Apr 2024 01:52:38 +0200 Subject: [PATCH] Fix and rewrite contrast color calculation --- modules/templates/util_render.go | 9 ++---- modules/util/color.go | 31 +++++++++----------- web_src/js/components/ContextPopup.vue | 18 ++++-------- web_src/js/utils/color.js | 16 ++++------- web_src/js/utils/color.test.js | 39 +++++++++++++------------- 5 files changed, 48 insertions(+), 65 deletions(-) diff --git a/modules/templates/util_render.go b/modules/templates/util_render.go index d1c9b082fab00..ef5a7545b1746 100644 --- a/modules/templates/util_render.go +++ b/modules/templates/util_render.go @@ -123,16 +123,10 @@ func RenderIssueTitle(ctx context.Context, text string, metas map[string]string) func RenderLabel(ctx context.Context, locale translation.Locale, label *issues_model.Label) template.HTML { var ( archivedCSSClass string - textColor = "#111" + textColor = util.ContrastColor(label.Color) labelScope = label.ExclusiveScope() ) - r, g, b := util.HexToRBGColor(label.Color) - // Determine if label text should be light or dark to be readable on background color - if util.UseLightTextOnBackground(r, g, b) { - textColor = "#eee" - } - description := emoji.ReplaceAliases(template.HTMLEscapeString(label.Description)) if label.IsArchived() { @@ -153,6 +147,7 @@ func RenderLabel(ctx context.Context, locale translation.Locale, label *issues_m // Make scope and item background colors slightly darker and lighter respectively. // More contrast needed with higher luminance, empirically tweaked. + r, g, b := util.HexToRBGColor(label.Color); luminance := util.GetLuminance(r, g, b) contrast := 0.01 + luminance*0.03 // Ensure we add the same amount of contrast also near 0 and 1. diff --git a/modules/util/color.go b/modules/util/color.go index 240b045c287a9..052ab3d380f22 100644 --- a/modules/util/color.go +++ b/modules/util/color.go @@ -4,22 +4,12 @@ package util import ( "fmt" - "math" "strconv" "strings" ) // Check similar implementation in web_src/js/utils/color.js and keep synchronization -// Return R, G, B values defined in reletive luminance -func getLuminanceRGB(channel float64) float64 { - sRGB := channel / 255 - if sRGB <= 0.03928 { - return sRGB / 12.92 - } - return math.Pow((sRGB+0.055)/1.055, 2.4) -} - // Get color as RGB values in 0..255 range from the hex color string (with or without #) func HexToRBGColor(colorString string) (float64, float64, float64) { hexString := colorString @@ -50,16 +40,23 @@ func HexToRBGColor(colorString string) (float64, float64, float64) { // return luminance given RGB channels // Reference from: https://www.w3.org/WAI/GL/wiki/Relative_luminance func GetLuminance(r, g, b float64) float64 { - R := getLuminanceRGB(r) - G := getLuminanceRGB(g) - B := getLuminanceRGB(b) - luminance := 0.2126*R + 0.7152*G + 0.0722*B - return luminance + return (0.2126*r + 0.7152*g + 0.0722*b) / 255 } +// calc( ((132 * 0.2126) + (182 * 0.7152) + (235 * 0.0722)) / 255 ) +// = .68704 + +// color: hsl(0, 0%, calc(var(--lightness-switch) * 100%)) !important; +// --lightness-switch: max(0, min(calc((1/(var(--lightness-threshold) - var(--perceived-lightness)))), 1)); + // Reference from: https://firsching.ch/github_labels.html // In the future WCAG 3 APCA may be a better solution. // Check if text should use light color based on RGB of background -func UseLightTextOnBackground(r, g, b float64) bool { - return GetLuminance(r, g, b) < 0.453 +func ContrastColor(color string) string { + r, g, b := HexToRBGColor(color); + if GetLuminance(r, g, b) < 0.453 { + return "#fff" + } else { + return "#000" + } } diff --git a/web_src/js/components/ContextPopup.vue b/web_src/js/components/ContextPopup.vue index d87eb1a180ea7..5a932045b1b03 100644 --- a/web_src/js/components/ContextPopup.vue +++ b/web_src/js/components/ContextPopup.vue @@ -1,7 +1,6 @@