diff --git a/react/src/utils/getTokenBackgroundColor.ts b/react/src/utils/getTokenBackgroundColor.ts index 8d0480be..d0280e14 100644 --- a/react/src/utils/getTokenBackgroundColor.ts +++ b/react/src/utils/getTokenBackgroundColor.ts @@ -16,6 +16,14 @@ export function getTokenBackgroundColor( negativeColor: AnyColor = "red", positiveColor: AnyColor = "blue" ): Colord { + // Zero is the neutral point and must stay white even when an observed + // range has no positive values. Dividing 0 by a zero maximum produces NaN, + // which colord represents as transparent black and makes token text + // unreadable on a white page. + if (value === 0) { + return colord("white"); + } + // original_color.mix("white", x) interpolates between original_color and // white, with x being the ratio of white. So x=0 is original_color, x=1 is // white. Clamp at 0 to avoid negative values. diff --git a/react/src/utils/tests/getTokenBackgroundColor.test.ts b/react/src/utils/tests/getTokenBackgroundColor.test.ts index 3d3e64c6..6fb8795e 100644 --- a/react/src/utils/tests/getTokenBackgroundColor.test.ts +++ b/react/src/utils/tests/getTokenBackgroundColor.test.ts @@ -28,4 +28,10 @@ describe("getBackgroundColor", () => { const res = getTokenBackgroundColor(0, 0, 1); expect(res.brightness()).toBeCloseTo(1); }); + + it("keeps zero white when the observed maximum is zero", () => { + const res = getTokenBackgroundColor(0, 0, 0); + expect(res.toRgbString()).toBe("rgb(255, 255, 255)"); + expect(res.brightness()).toBeCloseTo(1); + }); });