Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: recalibrate getTextColor function #983

Merged
merged 1 commit into from
Jul 27, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 35 additions & 25 deletions packages/shared/styles/color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,38 +81,48 @@ export const getTextColor = (
darkTextColor,
lightTextColor
): string => {
// Convert color from hex to RGB.
const getRGB = (c: string | number): number => {
return parseInt(c as string, 16) || (c as number);
};

// Convert to sRGB and apply gamma correction.
const getsRGB = (c: string): number => {
const rgb = getRGB(c) / 255;
return rgb <= 0.03928 ? rgb / 12.92 : Math.pow((rgb + 0.055) / 1.055, 2.4);
};

// Calculate relative luminance.
const getLuminance = (hexColor: string): number => {
return (
0.2126 * getsRGB(hexColor.slice(1, 3)) +
0.7152 * getsRGB(hexColor.slice(3, 5)) +
0.0722 * getsRGB(hexColor.slice(5, 7))
);
};

// Use relative luminance to compare color contrast.
const getContrast = (f: string, b: string): number => {
// Use relative luminance to compare color contrast.
const getLuminance = (hexColor: string): number => {
// Convert to sRGB and apply gamma correction.
const getRGB = (c: string | number): number =>
parseInt(c as string, 16) || (c as number);
const getsRGB = (c: string): number => {
const rgb = getRGB(c) / 255;
return rgb <= 0.03928
? rgb / 12.92
: Math.pow((rgb + 0.055) / 1.055, 2.4);
};

return (
0.2126 * getsRGB(hexColor.slice(1, 3)) +
0.7152 * getsRGB(hexColor.slice(3, 5)) +
0.0722 * getsRGB(hexColor.slice(5, 7))
);
};

const L1 = getLuminance(f);
const L2 = getLuminance(b);
// Ratio formula is defined by WCAG guidelines
return (Math.max(L1, L2) + 0.05) / (Math.min(L1, L2) + 0.05);
};

const LIGHT_COLOR = getContrast(bgColor, lightTextColor);
const DARK_COLOR = getContrast(bgColor, darkTextColor);
// WCAG 2.2 color contrast standard for normal text.
const MIN_NORMAL_CONTRAST = 4.5;

const contrastWithDarkText = getContrast(bgColor, darkTextColor);
const contrastWithLightText = getContrast(bgColor, lightTextColor);

if (
contrastWithLightText >= MIN_NORMAL_CONTRAST &&
contrastWithDarkText < MIN_NORMAL_CONTRAST
) {
return lightTextColor;
}

// Determine which color has the highest contrast ratio and return that color.
return LIGHT_COLOR > DARK_COLOR ? lightTextColor : darkTextColor;
return contrastWithDarkText > MIN_NORMAL_CONTRAST
? darkTextColor
: lightTextColor;
};

// Assumes we always want our default hover colors to be lower
Expand Down