♿ live region
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
{% block og_image %}{{ site_url }}/static/images/thumbs/{{ comic.filename }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- ARIA live region for screen reader announcements -->
|
||||
<div aria-live="polite" aria-atomic="true" class="sr-only" id="comic-announcer"></div>
|
||||
|
||||
<div class="comic-container{% if comic.full_width %} comic-container-fullwidth{% endif %}{% if comic.plain %} comic-container-plain{% endif %}" data-comic-number="{{ comic.number }}" data-total-comics="{{ total_comics }}">
|
||||
{% if not comic.plain %}
|
||||
<div class="comic-header">
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
{% endif %}
|
||||
|
||||
{% block content %}
|
||||
<!-- ARIA live region for screen reader announcements -->
|
||||
<div aria-live="polite" aria-atomic="true" class="sr-only" id="comic-announcer"></div>
|
||||
|
||||
<div class="comic-container" data-comic-number="{{ comic.number }}" data-total-comics="{{ total_comics }}">
|
||||
<div class="comic-header">
|
||||
<h1>{{ comic.title if comic.title else '#' ~ comic.number }}</h1>
|
||||
@@ -34,17 +37,17 @@
|
||||
{# Icon-based navigation #}
|
||||
{% if comic.number > 1 %}
|
||||
<a href="{{ url_for('comic', comic_id=1) }}" class="btn-icon-nav" aria-label="First">
|
||||
<img src="{{ url_for('static', filename='images/icons/first.png') }}" alt="First">
|
||||
<img src="{{ url_for('static', filename='images/icons/first.png') }}" alt="">
|
||||
</a>
|
||||
<a href="{{ url_for('comic', comic_id=comic.number - 1) }}" class="btn-icon-nav" aria-label="Previous">
|
||||
<img src="{{ url_for('static', filename='images/icons/previous.png') }}" alt="Previous">
|
||||
<img src="{{ url_for('static', filename='images/icons/previous.png') }}" alt="">
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="btn-icon-nav btn-icon-disabled" aria-label="First">
|
||||
<img src="{{ url_for('static', filename='images/icons/first.png') }}" alt="First">
|
||||
<span class="btn-icon-nav btn-icon-disabled" aria-label="First" aria-disabled="true">
|
||||
<img src="{{ url_for('static', filename='images/icons/first.png') }}" alt="">
|
||||
</span>
|
||||
<span class="btn-icon-nav btn-icon-disabled" aria-label="Previous">
|
||||
<img src="{{ url_for('static', filename='images/icons/previous.png') }}" alt="Previous">
|
||||
<span class="btn-icon-nav btn-icon-disabled" aria-label="Previous" aria-disabled="true">
|
||||
<img src="{{ url_for('static', filename='images/icons/previous.png') }}" alt="">
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
@@ -52,17 +55,17 @@
|
||||
|
||||
{% if comic.number < total_comics %}
|
||||
<a href="{{ url_for('comic', comic_id=comic.number + 1) }}" class="btn-icon-nav" aria-label="Next">
|
||||
<img src="{{ url_for('static', filename='images/icons/next.png') }}" alt="Next">
|
||||
<img src="{{ url_for('static', filename='images/icons/next.png') }}" alt="">
|
||||
</a>
|
||||
<a href="{{ url_for('comic', comic_id=total_comics) }}" class="btn-icon-nav" aria-label="Latest">
|
||||
<img src="{{ url_for('static', filename='images/icons/latest.png') }}" alt="Latest">
|
||||
<img src="{{ url_for('static', filename='images/icons/latest.png') }}" alt="">
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="btn-icon-nav btn-icon-disabled" aria-label="Next">
|
||||
<img src="{{ url_for('static', filename='images/icons/next.png') }}" alt="Next">
|
||||
<span class="btn-icon-nav btn-icon-disabled" aria-label="Next" aria-disabled="true">
|
||||
<img src="{{ url_for('static', filename='images/icons/next.png') }}" alt="">
|
||||
</span>
|
||||
<span class="btn-icon-nav btn-icon-disabled" aria-label="Latest">
|
||||
<img src="{{ url_for('static', filename='images/icons/latest.png') }}" alt="Latest">
|
||||
<span class="btn-icon-nav btn-icon-disabled" aria-label="Latest" aria-disabled="true">
|
||||
<img src="{{ url_for('static', filename='images/icons/latest.png') }}" alt="">
|
||||
</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
@@ -71,8 +74,8 @@
|
||||
<a href="{{ url_for('comic', comic_id=1) }}" class="btn btn-nav">First</a>
|
||||
<a href="{{ url_for('comic', comic_id=comic.number - 1) }}" class="btn btn-nav">Previous</a>
|
||||
{% else %}
|
||||
<span class="btn btn-nav btn-disabled">First</span>
|
||||
<span class="btn btn-nav btn-disabled">Previous</span>
|
||||
<span class="btn btn-nav btn-disabled" aria-disabled="true">First</span>
|
||||
<span class="btn btn-nav btn-disabled" aria-disabled="true">Previous</span>
|
||||
{% endif %}
|
||||
|
||||
<span class="comic-date-display">{{ comic.formatted_date }}</span>
|
||||
@@ -81,8 +84,8 @@
|
||||
<a href="{{ url_for('comic', comic_id=comic.number + 1) }}" class="btn btn-nav">Next</a>
|
||||
<a href="{{ url_for('comic', comic_id=total_comics) }}" class="btn btn-nav">Latest</a>
|
||||
{% else %}
|
||||
<span class="btn btn-nav btn-disabled">Next</span>
|
||||
<span class="btn btn-nav btn-disabled">Latest</span>
|
||||
<span class="btn btn-nav btn-disabled" aria-disabled="true">Next</span>
|
||||
<span class="btn btn-nav btn-disabled" aria-disabled="true">Latest</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user