GenerAI / worldmonitor /src /utils /contrast.ts
amogaddy's picture
Integra World Monitor (AGPL-3.0, self-hosted) nello Space: pagina, menu, e arricchimento notizie per la AI (part 8)
dbb1bf9 verified
Raw
History Blame Contribute Delete
1.52 kB
/**
* WCAG relative luminance of a solid hex color (#rgb or #rrggbb, with or
* without the leading '#'). https://www.w3.org/TR/WCAG21/#dfn-relative-luminance
*/
export function relativeLuminance(hex: string): number {
const h = hex.replace('#', '');
const full = h.length === 3 ? h.split('').map((c) => c + c).join('') : h;
const channel = (offset: number): number => {
const c = parseInt(full.slice(offset, offset + 2), 16) / 255;
return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
};
return 0.2126 * channel(0) + 0.7152 * channel(2) + 0.0722 * channel(4);
}
/** WCAG contrast ratio between two solid hex colors (1–21). */
export function contrastRatio(a: string, b: string): number {
const la = relativeLuminance(a);
const lb = relativeLuminance(b);
const [hi, lo] = la >= lb ? [la, lb] : [lb, la];
return (hi + 0.05) / (lo + 0.05);
}
/**
* Pick the higher-contrast foreground text color (white or near-black) for a
* solid hex background. Returns whichever of `#ffffff` / `#1a1a1a` has the
* greater contrast ratio against `bgHex` — e.g. white on dark badges, dark on
* light/mid badges (yellow, orange). The four CorrelationPanel score-badge
* backgrounds clear WCAG AA with the chosen color; arbitrary mid-gray inputs
* may still need a different palette to reach 4.5:1.
*/
export function readableTextColor(bgHex: string): '#ffffff' | '#1a1a1a' {
return contrastRatio('#ffffff', bgHex) >= contrastRatio('#1a1a1a', bgHex)
? '#ffffff'
: '#1a1a1a';
}