From 3f80a7706796b39851dcd2d7ede3aa7b086126e5 Mon Sep 17 00:00:00 2001 From: Nicky Gerritsen Date: Sat, 1 Mar 2025 13:47:40 +0000 Subject: [PATCH] Use new APCA standard for colors --- webapp/src/Twig/TwigExtension.php | 47 ++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/webapp/src/Twig/TwigExtension.php b/webapp/src/Twig/TwigExtension.php index a27cb234cf..b571434af1 100644 --- a/webapp/src/Twig/TwigExtension.php +++ b/webapp/src/Twig/TwigExtension.php @@ -1148,6 +1148,35 @@ public function fileTypeIcon(string $type): string return 'fas fa-file-' . $iconName; } + private function relativeLuminance(string $rgb): float + { + // See https://en.wikipedia.org/wiki/Relative_luminance + + [$r, $g, $b] = Utils::parseHexColor($rgb); + + [$lr, $lg, $lb] = [ + pow($r / 255, 2.4), + pow($g / 255, 2.4), + pow($b / 255, 2.4), + ]; + + return 0.2126 * $lr + 0.7152 * $lg + 0.0722 * $lb; + } + + private function apcaContrast(string $fgColor, string $bgColor): float + { + // Based on WCAG 3.x (https://www.w3.org/TR/wcag-3.0/) + + $luminanceForeground = $this->relativeLuminance($fgColor); + $luminanceBackground = $this->relativeLuminance($bgColor); + + $contrast = ($luminanceBackground > $luminanceForeground) + ? (pow($luminanceBackground, 0.56) - pow($luminanceForeground, 0.57)) * 1.14 + : (pow($luminanceBackground, 0.65) - pow($luminanceForeground, 0.62)) * 1.14; + + return round($contrast * 100, 2); + } + /** * @return array{string, string} */ @@ -1162,17 +1191,15 @@ private function hexToForegroundAndBorder(string $rgb): array $darker[2] = max($darker[2] - 64, 0); $border = Utils::rgbToHex($darker); - [$r, $g, $b] = $background; + // Pick the text color with the biggest absolute contrast. + $contrastWithWhite = $this->apcaContrast('#ffffff', $rgb); + $contrastWithBlack = $this->apcaContrast('#000000', $rgb); - // Calculate relative luminance - // Source: https://www.w3.org/WAI/GL/wiki/Relative_luminance - $r = ($r / 255 <= 0.03928) ? ($r / 255) / 12.92 : pow(($r / 255 + 0.055) / 1.055, 2.4); - $g = ($g / 255 <= 0.03928) ? ($g / 255) / 12.92 : pow(($g / 255 + 0.055) / 1.055, 2.4); - $b = ($b / 255 <= 0.03928) ? ($b / 255) / 12.92 : pow(($b / 255 + 0.055) / 1.055, 2.4); - - $luminance = 0.2126 * $r + 0.7152 * $g + 0.0722 * $b; - - $foreground = ($luminance > 0.179) ? '#000000' : '#FFFFFF'; + if (abs($contrastWithBlack) > abs($contrastWithWhite)) { + $foreground = '#000000'; + } else { + $foreground = '#ffffff'; + } return [$foreground, $border]; }