summaryrefslogtreecommitdiffstats
path: root/modules/util
diff options
context:
space:
mode:
authorsilverwind <me@silverwind.io>2024-04-07 18:19:25 +0200
committerGusted <postmaster@gusted.xyz>2024-04-15 16:11:34 +0200
commitf6c0c39f1aef167bb14375a009cf463c6bf031fb (patch)
tree6785b479f0f47fbe360311391af0e8ab53dc8bc5 /modules/util
parentMerge pull request '[CHORE] Exclude git repository testdate from watching' (#... (diff)
downloadforgejo-f6c0c39f1aef167bb14375a009cf463c6bf031fb.tar.xz
forgejo-f6c0c39f1aef167bb14375a009cf463c6bf031fb.zip
[PORT] gitea##30237: Fix and rewrite contrast color calculation, fix project-related bugs
1. The previous color contrast calculation function was incorrect at least for the `#84b6eb` where it output low-contrast white instead of black. I've rewritten these functions now to accept hex colors and to match GitHub's calculation and to output pure white/black for maximum contrast. Before and after: <img width="94" alt="Screenshot 2024-04-02 at 01 53 46" src="https://github.com/go-gitea/gitea/assets/115237/00b39e15-a377-4458-95cf-ceec74b78228"><img width="90" alt="Screenshot 2024-04-02 at 01 51 30" src="https://github.com/go-gitea/gitea/assets/115237/1677067a-8d8f-47eb-82c0-76330deeb775"> 2. Fix project-related issues: - Expose the new `ContrastColor` function as template helper and use it for project cards, replacing the previous JS solution which eliminates a flash of wrong color on page load. - Fix a bug where if editing a project title, the counter would get lost. - Move `rgbToHex` function to color utils. Co-authored-by: delvh <dev.lh@web.de> Co-authored-by: Giteabot <teabot@gitea.io> --- Conflict resolution: Trivial. (cherry picked from commit 36887ed3921d03f1864360c95bd2ecf853bfbe72)
Diffstat (limited to 'modules/util')
-rw-r--r--modules/util/color.go42
-rw-r--r--modules/util/color_test.go46
2 files changed, 39 insertions, 49 deletions
diff --git a/modules/util/color.go b/modules/util/color.go
index 240b045c28..9c520dce78 100644
--- a/modules/util/color.go
+++ b/modules/util/color.go
@@ -4,22 +4,10 @@ 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
@@ -47,19 +35,23 @@ func HexToRBGColor(colorString string) (float64, float64, float64) {
return r, g, b
}
-// 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
+// Returns relative luminance for a SRGB color - https://en.wikipedia.org/wiki/Relative_luminance
+// Keep this in sync with web_src/js/utils/color.js
+func GetRelativeLuminance(color string) float64 {
+ r, g, b := HexToRBGColor(color)
+ return (0.2126729*r + 0.7151522*g + 0.0721750*b) / 255
}
-// 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 UseLightText(backgroundColor string) bool {
+ return GetRelativeLuminance(backgroundColor) < 0.453
+}
+
+// Given a background color, returns a black or white foreground color that the highest
+// contrast ratio. In the future, the APCA contrast function, or CSS `contrast-color` will be better.
+// https://github.com/color-js/color.js/blob/eb7b53f7a13bb716ec8b28c7a56f052cd599acd9/src/contrast/APCA.js#L42
+func ContrastColor(backgroundColor string) string {
+ if UseLightText(backgroundColor) {
+ return "#fff"
+ }
+ return "#000"
}
diff --git a/modules/util/color_test.go b/modules/util/color_test.go
index d96ac36730..be6e6b122a 100644
--- a/modules/util/color_test.go
+++ b/modules/util/color_test.go
@@ -33,33 +33,31 @@ func Test_HexToRBGColor(t *testing.T) {
}
}
-func Test_UseLightTextOnBackground(t *testing.T) {
+func Test_UseLightText(t *testing.T) {
cases := []struct {
- r float64
- g float64
- b float64
- expected bool
+ color string
+ expected string
}{
- {215, 58, 74, true},
- {0, 117, 202, true},
- {207, 211, 215, false},
- {162, 238, 239, false},
- {112, 87, 255, true},
- {0, 134, 114, true},
- {228, 230, 105, false},
- {216, 118, 227, true},
- {255, 255, 255, false},
- {43, 134, 133, true},
- {43, 135, 134, true},
- {44, 135, 134, true},
- {59, 182, 179, true},
- {124, 114, 104, true},
- {126, 113, 108, true},
- {129, 112, 109, true},
- {128, 112, 112, true},
+ {"#d73a4a", "#fff"},
+ {"#0075ca", "#fff"},
+ {"#cfd3d7", "#000"},
+ {"#a2eeef", "#000"},
+ {"#7057ff", "#fff"},
+ {"#008672", "#fff"},
+ {"#e4e669", "#000"},
+ {"#d876e3", "#000"},
+ {"#ffffff", "#000"},
+ {"#2b8684", "#fff"},
+ {"#2b8786", "#fff"},
+ {"#2c8786", "#000"},
+ {"#3bb6b3", "#000"},
+ {"#7c7268", "#fff"},
+ {"#7e716c", "#fff"},
+ {"#81706d", "#fff"},
+ {"#807070", "#fff"},
+ {"#84b6eb", "#000"},
}
for n, c := range cases {
- result := UseLightTextOnBackground(c.r, c.g, c.b)
- assert.Equal(t, c.expected, result, "case %d: error should match", n)
+ assert.Equal(t, c.expected, ContrastColor(c.color), "case %d: error should match", n)
}
}