From f31383800ed48f7e42c1d70fcf08a3aa642fc31e Mon Sep 17 00:00:00 2001 From: mi Date: Fri, 14 Nov 2025 18:42:59 +1000 Subject: [PATCH] :wheelchair: live region --- static/css/style.css | 13 +++++++++++++ static/js/comic-nav.js | 16 ++++++++++++++++ templates/comic.html | 3 +++ templates/index.html | 35 +++++++++++++++++++---------------- 4 files changed, 51 insertions(+), 16 deletions(-) diff --git a/static/css/style.css b/static/css/style.css index d547642..5329bd5 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -65,6 +65,19 @@ body { background-color: var(--color-background); } +/* Screen reader only content - visually hidden but accessible to assistive technologies */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; +} + /* Focus indicators for accessibility */ a:focus, button:focus, diff --git a/static/js/comic-nav.js b/static/js/comic-nav.js index ae19f43..fbe0248 100644 --- a/static/js/comic-nav.js +++ b/static/js/comic-nav.js @@ -32,6 +32,12 @@ const title = comic.title || `#${comic.number}`; currentComicNumber = comic.number; + // Announce comic change to screen readers + const announcer = document.getElementById('comic-announcer'); + if (announcer) { + announcer.textContent = `Loaded comic ${title}, dated ${comic.formatted_date || comic.date}`; + } + // Update container class for full-width option const container = document.querySelector('.comic-container'); if (comic.full_width) { @@ -244,12 +250,16 @@ return; } + const announcer = document.getElementById('comic-announcer'); + switch(event.key) { case 'ArrowLeft': // Previous comic if (currentComicNumber > 1) { event.preventDefault(); loadComic(currentComicNumber - 1); + } else if (announcer) { + announcer.textContent = 'Already at the first comic'; } break; case 'ArrowRight': @@ -257,6 +267,8 @@ if (currentComicNumber < totalComics) { event.preventDefault(); loadComic(currentComicNumber + 1); + } else if (announcer) { + announcer.textContent = 'Already at the latest comic'; } break; case 'Home': @@ -264,6 +276,8 @@ if (currentComicNumber > 1) { event.preventDefault(); loadComic(1); + } else if (announcer) { + announcer.textContent = 'Already at the first comic'; } break; case 'End': @@ -271,6 +285,8 @@ if (currentComicNumber < totalComics) { event.preventDefault(); loadComic(totalComics); + } else if (announcer) { + announcer.textContent = 'Already at the latest comic'; } break; } diff --git a/templates/comic.html b/templates/comic.html index 64a48de..5790e74 100644 --- a/templates/comic.html +++ b/templates/comic.html @@ -5,6 +5,9 @@ {% block og_image %}{{ site_url }}/static/images/thumbs/{{ comic.filename }}{% endblock %} {% block content %} + +
+
{% if not comic.plain %}
diff --git a/templates/index.html b/templates/index.html index 06337b0..9d5812f 100644 --- a/templates/index.html +++ b/templates/index.html @@ -7,6 +7,9 @@ {% endif %} {% block content %} + +
+

{{ comic.title if comic.title else '#' ~ comic.number }}

@@ -34,17 +37,17 @@ {# Icon-based navigation #} {% if comic.number > 1 %} - First + - Previous + {% else %} - - First + + - - Previous + + {% endif %} @@ -52,17 +55,17 @@ {% if comic.number < total_comics %} - Next + - Latest + {% else %} - - Next + + - - Latest + + {% endif %} {% else %} @@ -71,8 +74,8 @@ First Previous {% else %} - First - Previous + First + Previous {% endif %} {{ comic.formatted_date }} @@ -81,8 +84,8 @@ Next Latest {% else %} - Next - Latest + Next + Latest {% endif %} {% endif %}