From da303de1bc4ccb8589806cbb49a2f4a8e7c03036 Mon Sep 17 00:00:00 2001 From: gnacho Date: Thu, 29 Oct 2026 08:00:41 +0100 Subject: [PATCH] fix(landing): label the slider thumbnails and make the comparison table reachable --- landing/app.js | 17 +++++++++++++++++ landing/i18n.js | 2 ++ landing/index.html | 10 +++++----- landing/styles.css | 1 + 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/landing/app.js b/landing/app.js index 702a6dc..ba8d8c3 100644 --- a/landing/app.js +++ b/landing/app.js @@ -56,10 +56,14 @@ function renderThumbs() { thumbs.innerHTML = ""; + var dict = I18N[lang] || I18N.es; activeSlides().forEach(function (s, i) { var b = document.createElement("button"); b.setAttribute("role", "tab"); b.setAttribute("aria-selected", i === slideIndex ? "true" : "false"); + b.setAttribute("aria-controls", "slideViewport"); + b.setAttribute("aria-label", dict[s.cap] || ""); + b.tabIndex = i === slideIndex ? 0 : -1; var img = document.createElement("img"); img.src = s.src; img.alt = ""; img.loading = "lazy"; img.decoding = "async"; img.width = 96; img.height = 64; @@ -82,6 +86,7 @@ slideCaption.textContent = (I18N[lang] || I18N.es)[s.cap] || ""; [...thumbs.children].forEach(function (b, j) { b.setAttribute("aria-selected", j === slideIndex ? "true" : "false"); + b.tabIndex = j === slideIndex ? 0 : -1; }); } @@ -118,6 +123,18 @@ }, 180); } + // Arrow keys move between screenshots, the way a tablist behaves. + thumbs.addEventListener("keydown", function (e) { + var keys = ["ArrowLeft", "ArrowRight", "Home", "End"]; + if (keys.indexOf(e.key) === -1) return; + e.preventDefault(); + var n = activeSlides().length; + var next = e.key === "Home" ? 0 : e.key === "End" ? n - 1 : slideIndex + (e.key === "ArrowRight" ? 1 : -1); + showSlide(next, e.key === "ArrowLeft" || e.key === "Home" ? -1 : 1); + var btn = thumbs.children[mod(next, n)]; + if (btn) btn.focus(); + }); + document.getElementById("slidePrev").addEventListener("click", function () { showSlide(slideIndex - 1, -1); }); document.getElementById("slideNext").addEventListener("click", function () { showSlide(slideIndex + 1, 1); }); diff --git a/landing/i18n.js b/landing/i18n.js index 4a053f7..e19727f 100644 --- a/landing/i18n.js +++ b/landing/i18n.js @@ -53,6 +53,7 @@ const I18N = { "shots.capDark": "Ventana principal, tema oscuro", "shots.alt": "Ventana principal de NextSync", "compare.title": "El compañero GNOME que faltaba", + "compare.tableLabel": "Tabla comparativa", "compare.lead": "Comparativa con los clientes de escritorio oficiales, contrastada el 20 de agosto de 2026 contra sus repos públicos.", "compare.h0": "Función", "compare.r1": "Interfaz nativa GNOME (GTK 4 / Libadwaita)", @@ -153,6 +154,7 @@ const I18N = { "shots.capDark": "Main window, dark theme", "shots.alt": "NextSync main window", "compare.title": "The GNOME companion that was missing", + "compare.tableLabel": "Comparison table", "compare.lead": "Compared with the official desktop clients, checked on August 20, 2026 against their public repos.", "compare.h0": "Feature", "compare.r1": "GNOME-native interface (GTK 4 / Libadwaita)", diff --git a/landing/index.html b/landing/index.html index 3566867..f02ae62 100644 --- a/landing/index.html +++ b/landing/index.html @@ -26,7 +26,7 @@ - + - - + + diff --git a/landing/styles.css b/landing/styles.css index 025013e..b2dbf39 100644 --- a/landing/styles.css +++ b/landing/styles.css @@ -261,6 +261,7 @@ a:hover { text-decoration: underline; } /* ---------- Comparativa ---------- */ .table-wrap { overflow-x: auto; border-radius: var(--radius); box-shadow: var(--shadow); } +.table-wrap:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; } .matrix { width: 100%; border-collapse: collapse; background: var(--card); font-size: 0.98rem; } .matrix th, .matrix td { padding: 0.9rem 1.1rem; text-align: left; border-bottom: 1px solid var(--card-border); } .matrix thead th { font-weight: 700; background: var(--btn-bg); }