46 lines
2.1 KiB
Python
46 lines
2.1 KiB
Python
"""Custom palette: one brand hex in, light + dark accent tokens out, readable in both modes."""
|
|
import importlib.util
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
PALETTE = Path(__file__).resolve().parents[1] / "skills" / "rpa-dashboard-no-ai" / "templates" / "palette.py"
|
|
spec = importlib.util.spec_from_file_location("palette", PALETTE)
|
|
palette = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(palette)
|
|
|
|
# Fixed Tebra Sky base colours the derived accents sit on (from dashboard.html).
|
|
LIGHT_BG, DARK_BG = "#eaf6fb", "#182a38"
|
|
LIGHT_INK, DARK_INK = "#1c2b33", "#e6eef4"
|
|
LOG_ERROR = "#f68c82" # dimmest log text colour
|
|
|
|
|
|
def contrast(a, b):
|
|
def lum(h):
|
|
c = [int(h[i:i + 2], 16) / 255 for i in (1, 3, 5)]
|
|
c = [x / 12.92 if x <= 0.03928 else ((x + 0.055) / 1.055) ** 2.4 for x in c]
|
|
return 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2]
|
|
hi, lo = sorted([lum(a), lum(b)], reverse=True)
|
|
return (hi + 0.05) / (lo + 0.05)
|
|
|
|
|
|
def test_derived_palette_is_readable_in_light_and_dark():
|
|
for brand in ["#3d9bd0", "#ffd400", "#0b1f4d", "#7a3cff", "#e4002b", "#00a651", "#ffffff", "#000000"]:
|
|
t = palette.derive(brand)
|
|
for mode, bg, ink in [("light", LIGHT_BG, LIGHT_INK), ("dark", DARK_BG, DARK_INK)]:
|
|
m = t[mode]
|
|
assert contrast("#ffffff", m["--accent"]) >= 3, (brand, mode, "button text")
|
|
assert contrast("#ffffff", m["--accent-2"]) >= 3, (brand, mode, "button text, light end")
|
|
assert contrast(m["--accent"], bg) >= 3, (brand, mode, "accent text")
|
|
assert contrast(ink, m["--accent-soft"]) >= 4.5, (brand, mode, "secondary button text")
|
|
assert contrast(LOG_ERROR, m["--accent-dark"]) >= 4.5, (brand, mode, "log text")
|
|
|
|
|
|
def test_brand_kept_when_it_already_passes():
|
|
assert palette.derive("#1f6fb2")["light"]["--accent"] == "#1f6fb2"
|
|
|
|
|
|
def test_cli_prints_both_token_blocks_and_contrast_table():
|
|
out = subprocess.run([sys.executable, str(PALETTE), "#7a3cff"], capture_output=True, text=True, check=True).stdout
|
|
assert "body{" in out and "body.dark{" in out and "PASS" in out and "FAIL" not in out
|