Skip to content

Instantly share code, notes, and snippets.

@SteveJonesDev
Created June 20, 2024 17:28
Show Gist options
  • Save SteveJonesDev/6381545e670ee10445aba53c9f884262 to your computer and use it in GitHub Desktop.
Save SteveJonesDev/6381545e670ee10445aba53c9f884262 to your computer and use it in GitHub Desktop.
Accessible Popup Modal
/**
* 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