diff --git a/index.html b/index.html index 58ee1a2..25fd04a 100644 --- a/index.html +++ b/index.html @@ -1142,12 +1142,64 @@ } } + let previouslyFocusedElement = null; + let activeModalId = null; + function openModal(id) { - document.getElementById(id).classList.add('active'); + previouslyFocusedElement = document.activeElement; + activeModalId = id; + const modal = document.getElementById(id); + modal.classList.add('active'); + + // Focus first focusable element in modal + const focusable = modal.querySelectorAll('button, input, select, textarea, [tabindex]:not([tabindex="-1"])'); + if (focusable.length > 0) { + setTimeout(() => focusable[0].focus(), 50); + } + + // Add event listeners for focus trap and Escape + document.addEventListener('keydown', handleModalKeydown); } function closeModal(id) { document.getElementById(id).classList.remove('active'); + document.removeEventListener('keydown', handleModalKeydown); + activeModalId = null; + + // Restore focus to previously focused element + if (previouslyFocusedElement) { + previouslyFocusedElement.focus(); + previouslyFocusedElement = null; + } + } + + function handleModalKeydown(e) { + if (!activeModalId) return; + const modal = document.getElementById(activeModalId); + + // Close on Escape + if (e.key === 'Escape') { + e.preventDefault(); + closeModal(activeModalId); + return; + } + + // Trap focus on Tab + if (e.key === 'Tab') { + const focusable = modal.querySelectorAll('button, input, select, textarea, [tabindex]:not([tabindex="-1"])'); + if (focusable.length === 0) return; + + const first = focusable[0]; + const last = focusable[focusable.length - 1]; + + if (e.shiftKey && document.activeElement === first) { + e.preventDefault(); + last.focus(); + } else if (!e.shiftKey && document.activeElement === last) { + e.preventDefault(); + first.focus(); + } + } } async function verifyPin() {