a11y: make mobile menu toggle keyboard & screen-reader accessible
The mobile hamburger is a <div class="mobile-menu-icon"> with a click handler, so it worked on tap but was invisible to keyboard and screen-reader users. Expose it as a button in main.js: role="button", tabindex="0", aria-label, aria-expanded toggling, and Enter/Space activation. Verified in a headless browser (focusable, Enter opens, aria state flips). Also adds docs/PRE-LAUNCH-CHECKLIST.md (dev-only, excluded from deploy): inventory of remaining content placeholders for the public launch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
9ce7450aa1
commit
c4da5de491
2 files changed
+77
-3
No files matched your search
@@ -14,21 +14,42 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
if (!icon) {
|
||||
console.error('Mobile menu icon not found.');
|
||||
} else {
|
||||
// Accessibility: the icon is a <div>, so expose it to keyboard and
|
||||
// screen-reader users as a button (focusable, labelled, toggle state).
|
||||
if (!icon.hasAttribute('role')) icon.setAttribute('role', 'button');
|
||||
if (!icon.hasAttribute('tabindex')) icon.setAttribute('tabindex', '0');
|
||||
if (!icon.hasAttribute('aria-label')) icon.setAttribute('aria-label', 'Open menu');
|
||||
icon.setAttribute('aria-expanded', 'false');
|
||||
|
||||
const setMenu = (open) => {
|
||||
root.classList.toggle('nav-open', open);
|
||||
icon.setAttribute('aria-expanded', open ? 'true' : 'false');
|
||||
icon.setAttribute('aria-label', open ? 'Close menu' : 'Open menu');
|
||||
};
|
||||
|
||||
icon.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
root.classList.toggle('nav-open');
|
||||
setMenu(!root.classList.contains('nav-open'));
|
||||
});
|
||||
|
||||
// Activate with Enter / Space like a native button.
|
||||
icon.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ' || e.key === 'Spacebar') {
|
||||
e.preventDefault();
|
||||
setMenu(!root.classList.contains('nav-open'));
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('click', (e) => {
|
||||
if (root.classList.contains('nav-open') && !e.target.closest('.mobile-nav-panel') && !e.target.closest('.mobile-menu-icon')) {
|
||||
root.classList.remove('nav-open');
|
||||
setMenu(false);
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
root.classList.remove('nav-open');
|
||||
setMenu(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user