fix(ui): improve financial text contrast

TD-010: use readable semantic text colors on financial surfaces while preserving signs and state meanings.
This commit is contained in:
2026-09-21 21:10:10 +03:00
parent 60f9538886
commit 5b2c6bb7cb
4 changed files with 53 additions and 8 deletions
+2 -2
View File
@@ -63,11 +63,11 @@
} }
.positive { .positive {
color: var(--mantine-color-green-6); color: var(--wl-color-positive);
} }
.negative { .negative {
color: var(--mantine-color-red-6); color: var(--wl-color-negative);
} }
.expandedCard { .expandedCard {
+45
View File
@@ -0,0 +1,45 @@
import { describe, expect, it } from "vitest";
import tokens from "./tokens.json";
function luminance(color: string) {
const channels = [1, 3, 5]
.map((index) => Number.parseInt(color.slice(index, index + 2), 16) / 255)
.map((value) =>
value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4,
);
return channels[0] * 0.2126 + channels[1] * 0.7152 + channels[2] * 0.0722;
}
describe("financial text contrast", () => {
it.each(["positive", "negative"] as const)(
"keeps %s readable on journal, position and tinted card surfaces",
(tone) => {
const role = tokens.color.roles[tone];
const palettes = tokens.color.palettes;
const foreground =
palettes[role.color as keyof typeof palettes][role.shade];
const surfaces = [
palettes.gray[0],
...Object.entries(palettes)
.filter(([name]) => name !== "dark")
.map(
([, palette]) =>
`#${[1, 3, 5]
.map((index) =>
Math.round(
Number.parseInt(palette[0].slice(index, index + 2), 16) *
0.45 +
255 * 0.55,
)
.toString(16)
.padStart(2, "0"),
)
.join("")}`,
),
];
for (const background of surfaces)
expect(
(luminance(background) + 0.05) / (luminance(foreground) + 0.05),
).toBeGreaterThanOrEqual(4.5);
},
);
});
+3 -3
View File
@@ -53,7 +53,7 @@
"#40c057", "#40c057",
"#37b24d", "#37b24d",
"#2f9e44", "#2f9e44",
"#2b8a3e" "#237032"
], ],
"red": [ "red": [
"#fff5f5", "#fff5f5",
@@ -151,12 +151,12 @@
}, },
"positive": { "positive": {
"color": "green", "color": "green",
"shade": 6, "shade": 9,
"description": "Положительный результат; дополните знаком и текстом" "description": "Положительный результат; дополните знаком и текстом"
}, },
"negative": { "negative": {
"color": "red", "color": "red",
"shade": 6, "shade": 9,
"description": "Ошибка / отрицательный результат; дополните текстом" "description": "Ошибка / отрицательный результат; дополните текстом"
}, },
"warning": { "warning": {
+3 -3
View File
@@ -19,15 +19,15 @@
} }
.positive { .positive {
color: var(--mantine-color-green-6); color: var(--wl-color-positive);
} }
.negative { .negative {
color: var(--mantine-color-red-6); color: var(--wl-color-negative);
} }
.neutral { .neutral {
color: var(--mantine-color-dimmed); color: var(--mantine-color-gray-7);
} }
@media (max-width: 36em) { @media (max-width: 36em) {