From 68f59c49a2514d5e4c37fcae44faa070af4340a0 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Sun, 10 May 2026 23:34:16 -0400 Subject: [PATCH] a11y: aria-pressed for all pill groups, aria-label on search inputs and buttons - Add role="group" + aria-label to duration-pills and sev-pills containers - Add aria-pressed to severity filter, duration, and refresh-interval pills - Keep aria-pressed in sync with JS (setDuration, applyRefreshPillUI, modal reset) - Add aria-label to events-search, host-search, links-search inputs - Add aria-label to host and UniFi device suppress buttons in templates - Replace dynamic style color strings in links.html stat cards with TDS utility classes (lt-text-red/green/amber) via downCls/errCls variables Co-Authored-By: Claude Sonnet 4.6 --- static/app.js | 14 ++++++++++---- templates/base.html | 28 +++++++++++++++------------- templates/index.html | 31 ++++++++++++++++++++----------- templates/links.html | 15 ++++++++------- templates/suppressions.html | 25 +++++++++++++++---------- 5 files changed, 68 insertions(+), 45 deletions(-) diff --git a/static/app.js b/static/app.js index 82c2010..2dfb050 100644 --- a/static/app.js +++ b/static/app.js @@ -276,9 +276,12 @@ function openSuppressModal(type, name, detail) { updateSuppressForm(); lt.modal.open('suppress-modal'); - document.querySelectorAll('#suppress-modal .pill').forEach(p => p.classList.remove('active')); + document.querySelectorAll('#suppress-modal .pill').forEach(p => { + p.classList.remove('active'); + p.setAttribute('aria-pressed', 'false'); + }); const manualPill = document.querySelector('#suppress-modal .pill-manual'); - if (manualPill) manualPill.classList.add('active'); + if (manualPill) { manualPill.classList.add('active'); manualPill.setAttribute('aria-pressed', 'true'); } const hint = document.getElementById('duration-hint'); if (hint) hint.textContent = 'Suppression will persist until manually removed.'; } @@ -297,8 +300,11 @@ function updateSuppressForm() { function setDuration(mins, el) { document.getElementById('sup-expires').value = mins || ''; - document.querySelectorAll('#suppress-modal .pill').forEach(p => p.classList.remove('active')); - if (el) el.classList.add('active'); + document.querySelectorAll('#suppress-modal .pill').forEach(p => { + p.classList.remove('active'); + p.setAttribute('aria-pressed', 'false'); + }); + if (el) { el.classList.add('active'); el.setAttribute('aria-pressed', 'true'); } const hint = document.getElementById('duration-hint'); if (hint) { if (mins) { diff --git a/templates/base.html b/templates/base.html index 21a4576..ec49357 100644 --- a/templates/base.html +++ b/templates/base.html @@ -231,12 +231,12 @@
-
- - - - - +
+ + + + +
Persists until manually removed.
@@ -286,12 +286,12 @@
-
- - - - - +
+ + + + +
@@ -381,7 +381,9 @@ function applyRefreshPillUI(interval) { document.querySelectorAll('#settings-refresh-pills .pill').forEach(function(p) { - p.classList.toggle('active', parseInt(p.dataset.refreshInterval) === interval); + var isActive = parseInt(p.dataset.refreshInterval) === interval; + p.classList.toggle('active', isActive); + p.setAttribute('aria-pressed', isActive ? 'true' : 'false'); }); var hint = document.getElementById('settings-refresh-hint'); if (hint) { diff --git a/templates/index.html b/templates/index.html index 7120eb0..1502373 100644 --- a/templates/index.html +++ b/templates/index.html @@ -73,12 +73,13 @@
-
- - - +
+ + +
@@ -316,7 +317,7 @@
@@ -357,7 +358,7 @@ data-sup-type="host" data-sup-name="{{ name }}" data-sup-detail="" - title="Suppress alerts for this host"> + aria-label="Suppress alerts for {{ name }}"> 🔕 Suppress + data-sup-detail="" + aria-label="Suppress alerts for {{ d.name }}"> 🔕 Suppress {% endif %} @@ -540,8 +542,12 @@ document.querySelector('.sev-pills')?.addEventListener('click', e => { const pill = e.target.closest('.pill[data-sev]'); if (!pill) return; - document.querySelectorAll('.sev-pills .pill').forEach(p => p.classList.remove('active')); + document.querySelectorAll('.sev-pills .pill').forEach(p => { + p.classList.remove('active'); + p.setAttribute('aria-pressed', 'false'); + }); pill.classList.add('active'); + pill.setAttribute('aria-pressed', 'true'); _filterSev = pill.dataset.sev; applyEventsFilter(); }); @@ -563,9 +569,12 @@ document.querySelectorAll('.lt-stat-card[data-stat-filter]').forEach(card => { card.addEventListener('click', () => { const sev = card.dataset.statFilter; - document.querySelectorAll('.sev-pills .pill').forEach(p => p.classList.remove('active')); + document.querySelectorAll('.sev-pills .pill').forEach(p => { + p.classList.remove('active'); + p.setAttribute('aria-pressed', 'false'); + }); const matchPill = document.querySelector(`.sev-pills .pill[data-sev="${sev}"]`); - if (matchPill) matchPill.classList.add('active'); + if (matchPill) { matchPill.classList.add('active'); matchPill.setAttribute('aria-pressed', 'true'); } _filterSev = sev; applyEventsFilter(); document.getElementById('events-table-wrap')?.scrollIntoView({ behavior: 'smooth', block: 'start' }); diff --git a/templates/links.html b/templates/links.html index 7bbf482..3adb4f5 100644 --- a/templates/links.html +++ b/templates/links.html @@ -17,7 +17,8 @@
@@ -407,8 +408,8 @@ function buildLinkSummary(hosts, unifiSwitches) { } const allTotal = totalIfaces + swTotal; const allDown = downIfaces + swDown; - const downColor = allDown > 0 ? 'var(--red)' : 'var(--green)'; - const errColor = errIfaces > 0 ? 'var(--amber)' : 'var(--green)'; + const downCls = allDown > 0 ? 'lt-text-red' : 'lt-text-green'; + const errCls = errIfaces > 0 ? 'lt-text-amber' : 'lt-text-green'; const downCardCls = allDown > 0 ? ' lt-stat-card--alert' : ''; const poeCard = totalPoe > 0 ? `
@@ -428,16 +429,16 @@ function buildLinkSummary(hosts, unifiSwitches) {
- +
- ${allDown} + ${allDown} Ports Down
- +
- ${errIfaces} + ${errIfaces} With Errors
diff --git a/templates/suppressions.html b/templates/suppressions.html index 8032b0e..7e74cf8 100644 --- a/templates/suppressions.html +++ b/templates/suppressions.html @@ -58,12 +58,12 @@
-
- - - - - +
+ + + + +
Persists until manually removed.
@@ -110,7 +110,8 @@ {{ s.created_at }} {% if s.expires_at %}{{ s.expires_at }}{% else %}manual{% endif %} - + {% endfor %} @@ -221,8 +222,11 @@ function setDur(mins, el) { document.getElementById('s-expires').value = mins || ''; - document.querySelectorAll('.duration-pills .pill').forEach(p => p.classList.remove('active')); - if (el) el.classList.add('active'); + document.querySelectorAll('.duration-pills .pill').forEach(p => { + p.classList.remove('active'); + p.setAttribute('aria-pressed', 'false'); + }); + if (el) { el.classList.add('active'); el.setAttribute('aria-pressed', 'true'); } const hint = document.getElementById('s-dur-hint'); if (mins) { const h = Math.floor(mins/60), m = mins%60; @@ -251,7 +255,8 @@ ${lt.escHtml(s.suppressed_by)} ${lt.escHtml(s.created_at || '')} ${s.expires_at ? lt.escHtml(s.expires_at) : 'manual'} - + `).join(''); wrap.innerHTML = `