feat: add dialog accessibility semantics and focus management to project modals

Co-authored-by: itziarZG <70289074+itziarZG@users.noreply.github.com>
Agent-Logs-Url: https://github.com/itziarZG/me/sessions/acdd7d81-9ce8-4ee1-be85-625decdc9be6
This commit is contained in:
copilot-swe-agent[bot]
2026-03-22 18:57:50 +00:00
co-authored by itziarZG
parent ac0c6b983a
commit 5d4756657c
2 changed files with 40 additions and 2 deletions
+15
View File
@@ -612,6 +612,9 @@
<div
id="project-1-modal"
class="hidden fixed inset-0 bg-black/50 dark:bg-black/70 z-50 flex items-center justify-center p-4 backdrop-blur-sm"
role="dialog"
aria-modal="true"
aria-labelledby="project-1-modal-title"
onclick="closeModal('project-1')"
>
<div
@@ -621,6 +624,7 @@
<div class="p-8 md:p-12">
<div class="flex justify-between items-start mb-6">
<h2
id="project-1-modal-title"
class="text-3xl font-serif italic text-slate-900 dark:text-white"
>
AI Knowledge Pipeline
@@ -628,6 +632,7 @@
<button
class="text-2xl text-slate-400 hover:text-slate-900 dark:hover:text-white transition-colors"
onclick="closeModal('project-1')"
aria-label="Close dialog"
>
</button>
@@ -718,6 +723,9 @@
<div
id="project-2-modal"
class="hidden fixed inset-0 bg-black/50 dark:bg-black/70 z-50 flex items-center justify-center p-4 backdrop-blur-sm"
role="dialog"
aria-modal="true"
aria-labelledby="project-2-modal-title"
onclick="closeModal('project-2')"
>
<div
@@ -727,6 +735,7 @@
<div class="p-8 md:p-12">
<div class="flex justify-between items-start mb-6">
<h2
id="project-2-modal-title"
class="text-3xl font-serif italic text-slate-900 dark:text-white"
>
ChefGPT
@@ -734,6 +743,7 @@
<button
class="text-2xl text-slate-400 hover:text-slate-900 dark:hover:text-white transition-colors"
onclick="closeModal('project-2')"
aria-label="Close dialog"
>
</button>
@@ -832,6 +842,9 @@
<div
id="project-3-modal"
class="hidden fixed inset-0 bg-black/50 dark:bg-black/70 z-50 flex items-center justify-center p-4 backdrop-blur-sm"
role="dialog"
aria-modal="true"
aria-labelledby="project-3-modal-title"
onclick="closeModal('project-3')"
>
<div
@@ -841,6 +854,7 @@
<div class="p-8 md:p-12">
<div class="flex justify-between items-start mb-6">
<h2
id="project-3-modal-title"
class="text-3xl font-serif italic text-slate-900 dark:text-white"
>
Content Processing Automation
@@ -848,6 +862,7 @@
<button
class="text-2xl text-slate-400 hover:text-slate-900 dark:hover:text-white transition-colors"
onclick="closeModal('project-3')"
aria-label="Close dialog"
>
</button>
+25 -2
View File
@@ -58,20 +58,37 @@ function scrollToContact() {
// Modal Management
// ============================================
/** Element that had focus before a modal was opened */
let _modalPreviousFocus = null;
/**
* Open modal by project ID
* Open modal by project ID.
* Saves the currently focused element and moves focus into the modal.
* @param {string} projectId - The project identifier
*/
function openModal(projectId) {
const modal = document.getElementById(projectId + "-modal");
if (modal) {
_modalPreviousFocus = document.activeElement;
modal.classList.remove("hidden");
document.body.style.overflow = "hidden";
// Move focus to the first focusable element inside the modal
const focusable = modal.querySelectorAll(
'button, [href], input, select, textarea, [contenteditable="true"], [tabindex]:not([tabindex="-1"])'
);
if (focusable.length > 0) {
focusable[0].focus();
} else {
modal.setAttribute("tabindex", "-1");
modal.focus();
}
}
}
/**
* Close modal by project ID
* Close modal by project ID.
* Restores focus to the element that was focused before the modal opened.
* @param {string} projectId - The project identifier
*/
function closeModal(projectId) {
@@ -79,6 +96,12 @@ function closeModal(projectId) {
if (modal) {
modal.classList.add("hidden");
document.body.style.overflow = "auto";
// Return focus to the element that triggered the modal
if (_modalPreviousFocus) {
_modalPreviousFocus.focus();
_modalPreviousFocus = null;
}
}
}