ui-copilot / backend /rules /chart_rules.py
ksri77's picture
feat: Module 8 β€” Learning Mode (why + references on every issue)
66f3a37
Raw
History Blame Contribute Delete
3.23 kB
from __future__ import annotations
from itertools import combinations
from backend.models.issue import Category, Issue, Severity
from backend.utils.color_utils import colour_distance
def analyze(parsed_page: dict, thresholds: dict) -> list[Issue]:
issues: list[Issue] = []
t = thresholds["charts"]
charts = parsed_page.get("charts", [])
for i, chart in enumerate(charts):
label = f"Chart #{i + 1}"
# CH1 β€” no axis labels
if not chart.get("has_axis_labels", True):
issues.append(Issue(
rule_id="CH1_missing_axis_labels",
category=Category.COMPONENT_QUALITY,
severity=Severity.MEDIUM,
confidence=0.8,
message=f"{label} has no axis labels β€” users can't tell what the data represents.",
recommendation="Add descriptive axis labels with units (e.g. 'Revenue ($)' on Y, 'Month' on X).",
evidence="No axis labels detected.",
estimated_time="10 minutes",
why=(
"Without axis labels, users cannot determine the unit of measurement, "
"whether the Y-axis starts at zero, or what time period the X-axis covers. "
"The chart becomes decorative rather than informative. Every chart needs "
"at minimum a title and labelled axes to pass a basic data literacy check."
),
references=["Edward Tufte", "Datawrapper", "Stripe"],
))
# CH2 β€” chart colours too similar (hard to distinguish series)
colors = chart.get("colors", [])
if len(colors) >= 2:
too_close = [
(a, b)
for a, b in combinations(colors, 2)
if colour_distance(a, b) < t["min_color_distance"]
]
if too_close:
issues.append(Issue(
rule_id="CH2_similar_chart_colors",
category=Category.ACCESSIBILITY,
severity=Severity.MEDIUM,
confidence=0.85,
message=(
f"{label} has {len(too_close)} colour pair(s) that are too similar "
"to distinguish β€” problematic for colour-blind users."
),
recommendation=(
"Use a perceptually distinct colour palette for chart series. "
"Test with a colour-blindness simulator."
),
evidence=f"Similar pairs: {too_close[:3]}",
estimated_time="15 minutes",
why=(
"Colour-blindness affects ~8% of men and ~0.5% of women. When chart "
"series are distinguished only by hue, a large portion of your audience "
"cannot read the chart. WCAG 1.4.1 requires that colour is not the "
"sole means of conveying information β€” add patterns, shapes, or labels."
),
references=["WCAG 2.1 SC 1.4.1", "Datawrapper", "Coblis"],
))
return issues