From c4da5de4917c939be724cd662c4e73a20fb1862f Mon Sep 17 00:00:00 2001 From: popovskik Date: Tue, 4 Aug 2026 00:57:27 +0200 Subject: [PATCH] a11y: make mobile menu toggle keyboard & screen-reader accessible The mobile hamburger is a
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) --- docs/PRE-LAUNCH-CHECKLIST.md | 53 ++++++++++++++++++++++++++++++++++++ main.js | 27 ++++++++++++++++-- 2 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 docs/PRE-LAUNCH-CHECKLIST.md diff --git a/docs/PRE-LAUNCH-CHECKLIST.md b/docs/PRE-LAUNCH-CHECKLIST.md new file mode 100644 index 00000000..bd03c14d --- /dev/null +++ b/docs/PRE-LAUNCH-CHECKLIST.md @@ -0,0 +1,53 @@ +# MSOS Pre-Launch Placeholder Checklist + +_Auto-generated. Applies to EN + MK + SI unless noted. Tick as you replace._ + +## 1. Homepage — template placeholder content (HIGH) +- [ ] Replace **Lorem ipsum testimonials** on the homepage (en/mk/si `index.html`, testimonials section) +- [ ] Replace the template line **"Everything you need to know about the product and billing"** with real MSOS copy + +## 2. "Coming soon" cards +- [ ] Blog index: **9 'Coming soon' cards** — publish or hide (en/mk/si) +- [ ] News index: **3 'Coming soon' cards** — publish or hide (en/mk/si) + +## 3. Student-guide hero images — 30 pages ×3 languages +Each has a styled "Image placeholder" box awaiting a real hero image: +- [ ] `student-welcome-guide/academic-life/` +- [ ] `student-welcome-guide/administrative-basics/` +- [ ] `student-welcome-guide/admission-and-enrolment/` +- [ ] `student-welcome-guide/application-deadlines/` +- [ ] `student-welcome-guide/arrival-checklist/` +- [ ] `student-welcome-guide/bachelor-application/` +- [ ] `student-welcome-guide/choose-a-programme/` +- [ ] `student-welcome-guide/complete-student-journey/` +- [ ] `student-welcome-guide/document-preparation/` +- [ ] `student-welcome-guide/evs-application-guide/` +- [ ] `student-welcome-guide/healthcare-in-slovenia/` +- [ ] `student-welcome-guide/master-application/` +- [ ] `student-welcome-guide/means-accommodation-address/` +- [ ] `student-welcome-guide/official-sources-and-checklists/` +- [ ] `student-welcome-guide/prepare-to-move/` +- [ ] `student-welcome-guide/recognition-of-education/` +- [ ] `student-welcome-guide/renew-change-graduate/` +- [ ] `student-welcome-guide/rm-si-3-health-insurance/` +- [ ] `student-welcome-guide/student-accommodation/` +- [ ] `student-welcome-guide/student-budget/` +- [ ] `student-welcome-guide/student-meals/` +- [ ] `student-welcome-guide/student-organisations-and-extracurriculars/` +- [ ] `student-welcome-guide/student-residence-permit/` +- [ ] `student-welcome-guide/student-transport/` +- [ ] `student-welcome-guide/student-work/` +- [ ] `student-welcome-guide/study-cities/` +- [ ] `student-welcome-guide/tuition-and-scholarships/` +- [ ] `student-welcome-guide/visa-and-residence-explained/` +- [ ] `student-welcome-guide/wellbeing-and-community/` +- [ ] `student-welcome-guide/where-to-apply-for-residence/` + +## 4. MSOS Hub — temporary photos (see code comments) +- [ ] `msos-hub/`: hub-story-bg (wide renovated-Hub shot) +- [ ] `msos-hub/`: hub-use-img photos +- [ ] `msos-hub/`: hub-shot gallery photos + +## 5. Verify (not placeholders, but confirm before launch) +- [ ] Support page bank details real & correct (IBAN SI56 0284 3026 6115 703 / SWIFT LJBASI2X) +- [ ] MK/SI meta descriptions on legal/msos-hub/support proofread by a native speaker diff --git a/main.js b/main.js index 6e5aa738..2ecc76de 100644 --- a/main.js +++ b/main.js @@ -14,21 +14,42 @@ document.addEventListener('DOMContentLoaded', function() { if (!icon) { console.error('Mobile menu icon not found.'); } else { + // Accessibility: the icon is a
, 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); } }); }