diff --git a/packages/jaeger-ui-components/src/utils/color-generator.test.js b/packages/jaeger-ui-components/src/utils/color-generator.test.js index b71eed2644c..8da84c832bd 100644 --- a/packages/jaeger-ui-components/src/utils/color-generator.test.js +++ b/packages/jaeger-ui-components/src/utils/color-generator.test.js @@ -26,7 +26,7 @@ it('gives the same color for the same key', () => { expect(colorOne).toBe(colorTwo); }); -it('gives different colors for each for each key', () => { +it('gives different colors for each key', () => { clear(); const colorOne = getColorByKey('serviceA', createTheme()); const colorTwo = getColorByKey('serviceB', createTheme()); @@ -35,8 +35,10 @@ it('gives different colors for each for each key', () => { it('should not allow red', () => { expect(colorsToFilter.indexOf('#E24D42')).toBe(4); + expect(colorsToFilter.indexOf('#BF1B00')).toBe(28); const filteredColors = getFilteredColors(colorsToFilter, createTheme()); expect(filteredColors.indexOf('#E24D42')).toBe(-1); + expect(filteredColors.indexOf('#BF1B00')).toBe(-1); }); it('should not allow colors with a contrast ratio < 3 in light mode', () => { @@ -54,3 +56,23 @@ it('should not allow colors with a contrast ratio < 3 in dark mode', () => { expect(filteredColors.indexOf('#890F02')).toBe(-1); expect(filteredColors.indexOf('#0A437C')).toBe(-1); }); + +it('should not allow a color that is the same as the previous color', () => { + clear(); + const theme = createTheme(); + const colorOne = getColorByKey('random4', theme); // #447EBC + const colorTwo = getColorByKey('random17', theme); // #447EBC + expect(colorOne).not.toBe(colorTwo); + expect(colorOne).toBe('#447EBC'); + expect(colorTwo).toBe('#B7DBAB'); +}); + +it('should not allow a color that looks similar to the previous color', () => { + clear(); + const theme = createTheme({ colors: { mode: 'light' } }); + const colorOne = getColorByKey('random9', theme); // #58140C + const colorTwo = getColorByKey('random18', theme); // #511749 + expect(colorOne).toBe('#58140C'); + // #1F78C1 is the next color that has a contrast ratio >= 3 for the current theme + expect(colorTwo).toBe('#1F78C1'); +}); diff --git a/packages/jaeger-ui-components/src/utils/color-generator.tsx b/packages/jaeger-ui-components/src/utils/color-generator.tsx index 2f12451d940..cc108cb038d 100644 --- a/packages/jaeger-ui-components/src/utils/color-generator.tsx +++ b/packages/jaeger-ui-components/src/utils/color-generator.tsx @@ -45,13 +45,40 @@ class ColorGenerator { let i = this.cache.get(key); if (i == null) { const hash = this.hashCode(key.toLowerCase()); - const hashIndex = Math.abs(hash % this.colorsHex.length); - i = hashIndex === 4 ? hashIndex + 1 : hashIndex; + i = Math.abs(hash % this.colorsHex.length); + + const prevCacheItem = Array.from(this.cache).pop(); + if (prevCacheItem && prevCacheItem[1]) { + // disallow a color that is the same as the previous color + if (prevCacheItem[1] === i) { + i = this.getNextIndex(i); + } + + // disallow a color that looks very similar to the previous color + const prevColor = this.colorsHex[prevCacheItem[1]]; + if (tinycolor.readability(prevColor, this.colorsHex[i]) < 1.5) { + let newIndex = i; + for (let j = 0; j < this.colorsHex.length; j++) { + newIndex = this.getNextIndex(newIndex); + + if (tinycolor.readability(prevColor, this.colorsHex[newIndex]) > 1.5) { + i = newIndex; + break; + } + } + } + } + this.cache.set(key, i); } return i; } + getNextIndex(i: number) { + // get next index or go back to 0 + return i + 1 < this.colorsHex.length ? i + 1 : 0; + } + hashCode(key: string) { let hash = 0, i, @@ -110,6 +137,10 @@ export function getFilteredColors(colorsHex: string[], theme: GrafanaTheme2) { if (redIndex > -1) { colorsHex.splice(redIndex, 1); } + const redIndex2 = colorsHex.indexOf('#BF1B00'); + if (redIndex2 > -1) { + colorsHex.splice(redIndex2, 1); + } // Only add colors that have a contrast ratio >= 3 for the current theme let filteredColors = [];