From: Danilo M. Date: Fri, 17 Apr 2026 07:25:33 +0000 (+0200) Subject: feat: enhance modal focus trap with JavaScript and ARIA attributes X-Git-Tag: release_22042026-1342~173 X-Git-Url: https://git.danix.xyz/?a=commitdiff_plain;h=7992d01ce2f196031592c50821104bedc9ca75f8;p=danix.xyz-2.git feat: enhance modal focus trap with JavaScript and ARIA attributes Implements focus trap function that cycles Tab/Shift+Tab within modal boundaries, adds ARIA attributes (role, aria-modal, aria-labelledby) for accessibility compliance, and integrates focus initialization on modal display. - Focus trap prevents tab escape from modal dialog - ARIA attributes: role=dialog, aria-modal=true, aria-labelledby linking title - Backdrop marked aria-hidden=true to exclude from accessibility tree - Close buttons have aria-label for screen readers - Focus initialization calls createFocusTrap on modal show Co-Authored-By: Claude Haiku 4.5 --- diff --git a/themes/danix-xyz-hacker/assets/js/form-components.js b/themes/danix-xyz-hacker/assets/js/form-components.js index 35a5f27..ffa4260 100644 --- a/themes/danix-xyz-hacker/assets/js/form-components.js +++ b/themes/danix-xyz-hacker/assets/js/form-components.js @@ -89,3 +89,39 @@ export function renderToastContainer(Alpine) { } }; } + +// Focus Trap for Modals - Week 5 +function createFocusTrap(modalElement) { + const focusableElements = modalElement.querySelectorAll( + 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' + ); + + if (focusableElements.length === 0) return; + + const firstElement = focusableElements[0]; + const lastElement = focusableElements[focusableElements.length - 1]; + + modalElement.addEventListener('keydown', (e) => { + if (e.key !== 'Tab') return; + + if (e.shiftKey) { + // Shift + Tab + if (document.activeElement === firstElement) { + e.preventDefault(); + lastElement.focus(); + } + } else { + // Tab + if (document.activeElement === lastElement) { + e.preventDefault(); + firstElement.focus(); + } + } + }); + + // Set initial focus + firstElement.focus(); +} + +// Export for use in Alpine.js +window.createFocusTrap = createFocusTrap; diff --git a/themes/danix-xyz-hacker/layouts/partials/form-components.html b/themes/danix-xyz-hacker/layouts/partials/form-components.html index 9a69d43..d38973a 100644 --- a/themes/danix-xyz-hacker/layouts/partials/form-components.html +++ b/themes/danix-xyz-hacker/layouts/partials/form-components.html @@ -153,11 +153,11 @@ ============================================ -->