/
colors.js
92 lines (80 loc) · 2.76 KB
/
colors.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import colorConverter from 'css-color-converter';
import { suggestColors } from 'a11y-color';
const axe = require('axe-core');
const BLACK_HEX = '#000000';
const WHITE_HEX = '#ffffff';
export const getAllColorTypes = value => {
const color = colorConverter(value);
return {
hex: color.toHexString(),
rgba: color.toRgbaArray()
};
};
/**
* Gets color combinations for current palette
* @param {Array} colors an array of color palette objects
* @param {Object} results object containing current results configuration (fontSize, fontWeight, etc..)
* @return {Array} an array of color combinations, each containing:
* @property {Object} fg a color palette object
* @property {Object} bg a color palette object
* @property {Number} contrast the contrast between the fg and bg (calculated by axe)
* @property {Array} rgba an array of rgba values
* @property {String} hex a suggested hex for combos that do not meet contast requirements
* @property {Object} suggestion a suggestion color object returned by a11y-color
* @property {Boolean} pass whether or not the combo passes color contrast requirements
*/
export const getCombos = (colors, results) => {
// map colors with it's original index position
const palette = colors.map((c, i) => ({
...c,
originalIndex: i
}));
if (results.includeBlackAndWhite) {
const hasBlackText = colors.find(c => c.hex === BLACK_HEX);
const hasWhiteText = colors.find(c => c.hex === WHITE_HEX);
const data = { background: false, text: true };
if (!hasBlackText) {
palette.push({
...getAllColorTypes(BLACK_HEX),
...data,
forced: 'black'
});
}
if (!hasWhiteText) {
palette.push({
...getAllColorTypes(WHITE_HEX),
...data,
forced: 'white'
});
}
}
const backgrounds = palette.filter(c => c.background);
const texts = palette.filter(c => c.text);
return backgrounds.reduce((acc, bg) => {
const bgColor = new axe.commons.color.Color(...bg.rgba);
texts.filter(fg => fg.hex !== bg.hex).forEach(fg => {
const fgColor = new axe.commons.color.Color(...fg.rgba);
const contrast = axe.commons.color.getContrast(bgColor, fgColor);
// TODO: Account for bold text here
const cutoff = results.fontSize < 18 ? 4.5 : 3;
const pass = contrast >= cutoff;
const suggestedColor =
!pass &&
suggestColors(bgColor, fgColor, {
AA: cutoff
});
const suggestion = suggestedColor && suggestedColor['AA'];
const { rgba, hex } = suggestion && getAllColorTypes(suggestion.fg);
acc.push({
fg,
bg,
contrast,
rgba,
hex,
suggestion,
pass
});
});
return acc;
}, []);
};