From f4411fdc7668bf4762a25dd520afbdc637c6ef6b Mon Sep 17 00:00:00 2001 From: Jon Seager Date: Mon, 9 Feb 2026 19:54:42 +0000 Subject: [PATCH] feat(a11y): add role=img and sr-only data to map and chart components Add ARIA role=img with descriptive labels to world-map SVG and donut-chart SVG. Include a screen-reader-only data table in world-map for country/count pairs. --- static/js/components/donut-chart.js | 2 +- static/js/components/world-map.js | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/static/js/components/donut-chart.js b/static/js/components/donut-chart.js index 1ab4c76..0e5ad14 100644 --- a/static/js/components/donut-chart.js +++ b/static/js/components/donut-chart.js @@ -103,7 +103,7 @@ class DonutChart extends HTMLElement { }); this.innerHTML = `
- + ${segments.join("")} ${(() => { const icon = DONUT_ICONS[this.dataset.icon]; diff --git a/static/js/components/world-map.js b/static/js/components/world-map.js index c4de3d8..084abed 100644 --- a/static/js/components/world-map.js +++ b/static/js/components/world-map.js @@ -71,6 +71,31 @@ customElements.define( svg.style.display = "block"; this.appendChild(svg); + svg.setAttribute("role", "img"); + svg.setAttribute( + "aria-label", + "World map showing coffee origins by country", + ); + + const srOnly = this.querySelector(".sr-only"); + if (srOnly) srOnly.remove(); + const raw = this.dataset.countries || ""; + if (raw) { + const entries = raw.split(",").map((e) => e.split(":")); + const sr = document.createElement("div"); + sr.className = "sr-only"; + sr.innerHTML = + "" + + entries + .map( + ([code, count]) => + ``, + ) + .join("") + + "
Coffee origins by country
CountryCount
${code.toUpperCase()}${count}
"; + this.appendChild(sr); + } + this._recolor(); }