Created
June 20, 2024 17:28
-
-
Save SteveJonesDev/6381545e670ee10445aba53c9f884262 to your computer and use it in GitHub Desktop.
Accessible Popup Modal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Adds an accessible popup to the footer. | |
* | |
* This function outputs the HTML, CSS, and JavaScript needed for an accessible popup. | |
* The popup can be opened with a button click, and it traps focus within itself when open. | |
* The popup can be closed with a button click or by pressing the Escape key. | |
*/ | |
function add_accessible_popup_to_footer() { | |
?> | |
<!-- Accessible Popup HTML --> | |
<button id="open-popup-button" aria-haspopup="dialog" aria-controls="popup">Open Popup</button> | |
<div id="popup" class="popup" role="dialog" aria-labelledby="popup-title" aria-modal="true" hidden> | |
<div class="popup-content"> | |
<h2 id="popup-title">Popup Title</h2> | |
<p>This is an accessible popup example.</p> | |
<a href="https://stevejonesdev.com">This is a link example</a> | |
<button id="close-popup-button" aria-label="Close Popup">Close</button> | |
</div> | |
</div> | |
<style> | |
body { | |
font-family: Arial, sans-serif; | |
} | |
.popup { | |
position: fixed; | |
top: 50%; | |
left: 50%; | |
transform: translate(-50%, -50%); | |
background-color: white; | |
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); | |
width: 80%; | |
max-width: 400px; | |
z-index: 1000; | |
padding: 1em; | |
} | |
.popup-content { | |
position: relative; | |
} | |
.popup-content h2 { | |
margin-top: 0; | |
} | |
#close-popup-button { | |
position: absolute; | |
top: 10px; | |
right: 10px; | |
} | |
.hidden { | |
display: none; | |
} | |
.popup-overlay { | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background: rgba(0, 0, 0, 0.5); | |
z-index: 999; | |
} | |
</style> | |
<script> | |
document.addEventListener('DOMContentLoaded', () => { | |
const openPopupButton = document.getElementById('open-popup-button'); | |
const closePopupButton = document.getElementById('close-popup-button'); | |
const popup = document.getElementById('popup'); | |
let lastFocusedElement = null; | |
openPopupButton.addEventListener('click', () => { | |
lastFocusedElement = document.activeElement; | |
popup.removeAttribute('hidden'); | |
const focusableElements = popup.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'); | |
if (focusableElements.length) { | |
focusableElements[0].focus(); | |
} | |
const firstFocusableElement = focusableElements[0]; | |
const lastFocusableElement = focusableElements[focusableElements.length - 1]; | |
function trapFocus(event) { | |
if (event.key === 'Tab') { | |
if (event.shiftKey) { | |
if (document.activeElement === firstFocusableElement) { | |
event.preventDefault(); | |
lastFocusableElement.focus(); | |
} | |
} else { | |
if (document.activeElement === lastFocusableElement) { | |
event.preventDefault(); | |
firstFocusableElement.focus(); | |
} | |
} | |
} else if (event.key === 'Escape') { | |
closePopup(); | |
} | |
} | |
function closePopup() { | |
popup.setAttribute('hidden', true); | |
document.removeEventListener('keydown', trapFocus); | |
lastFocusedElement.focus(); | |
} | |
closePopupButton.addEventListener('click', closePopup); | |
document.addEventListener('keydown', trapFocus); | |
}); | |
closePopupButton.addEventListener('click', () => { | |
popup.setAttribute('hidden', true); | |
lastFocusedElement.focus(); | |
}); | |
document.addEventListener('keydown', (event) => { | |
if (event.key === 'Escape' && !popup.hasAttribute('hidden')) { | |
popup.setAttribute('hidden', true); | |
lastFocusedElement.focus(); | |
} | |
}); | |
}); | |
</script> | |
<?php | |
} | |
add_action('wp_footer', 'add_accessible_popup_to_footer'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment