MM-52280: Generate higher contrast for some usernames (#25073)

* MM-52280: Generate higher contrast for some usernames

Keep 3 tries but return the best value instead of the last one

Signed-off-by: Nicolas Le Cam <niko.lecam@gmail.com>

* Try ten times to find the best contrast before giving up

---------

Signed-off-by: Nicolas Le Cam <niko.lecam@gmail.com>
Этот коммит содержится в:
Nicolas Le Cam
2023-10-26 21:48:35 +02:00
коммит произвёл GitHub
родитель 375404c12e
Коммит 573e45691f
2 изменённых файлов: 54 добавлений и 7 удалений

Просмотреть файл

@@ -0,0 +1,30 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import ColorContrastChecker from 'color-contrast-checker';
import {cachedUserNameColors, generateColor} from './utils';
const CONSTRAST_CHECKER = new ColorContrastChecker();
const BACKGROUND_COLOR = '#ACC8E5';
describe('components/user_profile/utils', () => {
test.each([
['Ross_Bednar', '#432dd2', 4.5],
['Geovany95', '#2d3086', 4.5],
['Madisen25', '#52783a', 2.9],
['Gerard17', '#783a54', 4.5],
['Alia30', '#392d86', 4.5],
['Darien.Prosacco97', '#862d6d', 4.5],
['Alf48', '#4053bf', 3.7],
['Darron_Orn-Walsh49', '#742d86', 4.5],
])('should generate best color contrast', (userName, expected, ratio) => {
cachedUserNameColors.clear();
const actual = generateColor(userName, BACKGROUND_COLOR);
expect(actual).toBe(expected);
expect(
CONSTRAST_CHECKER.isLevelCustom(actual, BACKGROUND_COLOR, ratio),
).toBeTruthy();
});
});

Просмотреть файл

@@ -4,27 +4,44 @@
import ColorContrastChecker from 'color-contrast-checker';
import ColorHash from 'color-hash';
const cachedColors = new Map<string, string>();
const REQUIRED_COLOR_RATIO = 4.5;
export const cachedUserNameColors = new Map<string, string>();
export function generateColor(username: string, background: string): string {
const cacheKey = `${username}-${background}`;
const cachedColor = cachedColors.get(cacheKey);
const cachedColor = cachedUserNameColors.get(cacheKey);
if (cachedColor) {
return cachedColor;
}
let userColor = background;
let contrastRatio = 1;
let userAndSalt = username;
const checker = new ColorContrastChecker();
const colorHash = new ColorHash();
let tries = 3;
while (!checker.isLevelCustom(userColor, background, 4.5) && tries > 0) {
userColor = colorHash.hex(userAndSalt);
const backgroundLuminance = checker.hexToLuminance(background);
for (let tries = 10; tries > 0; tries--) {
const textColor = colorHash.hex(userAndSalt);
const cr = checker.getContrastRatio(
checker.hexToLuminance(textColor),
backgroundLuminance,
);
if (cr > contrastRatio) {
userColor = textColor;
contrastRatio = cr;
}
if (cr >= REQUIRED_COLOR_RATIO) {
break;
}
userAndSalt += 'salt';
tries--;
}
cachedColors.set(cacheKey, userColor);
cachedUserNameColors.set(cacheKey, userColor);
return userColor;
}