import tokens from "@wealthledger/tokens/tokens.json"; import { describe, expect, it } from "vitest"; 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("semantic text contrast", () => { it.each(["positive", "negative", "muted"] as const)( "keeps %s readable on canvas, white, subtle and tinted 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 = [ "#ffffff", palettes.gray[0], palettes.gray[2], ...Object.entries(palettes) .filter(([name]) => name !== "dark") .map(([, palette]) => palette[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); }, ); });