JSFiddle - React, Tailwind, and code Playground
by stevelove
HTML
<p>Ut exercitationem fugit sapiente sed magnam eum consequatur. Est cum ut iste. A nulla aut sit ipsam necessitatibus culpa quos eveniet.</p>
<button type="button" aria-haspopup="dialog" data-title="Alert dialog example" data-contents="Hello world!">
Show an alert dialog
</button>
<p>Optio voluptatem sunt perferendis. Totam provident ut et possimus id eveniet odit dolorum.</p>
<dialog></dialog>
JavaScript
let button = document.querySelector('[aria-haspopup="dialog"]')
button.addEventListener('click', function(event) {
let trigger = event.target
let dialog = document.querySelector('dialog')
openDialog(dialog)
let contents = trigger.dataset.contents
let title = trigger.dataset.title
let template = `<div>
<div role="document" tabindex="0">
<h1 id="dialog-title">${title}</h1>
<p id="dialog-description">${contents}</p>
<button class="close" type="button">Close</button>
</div>
</div>`
dialog.innerHTML = template
hideAllElse()
let close = dialog.querySelector('.close')
let dialogDoc = dialog.querySelector('[role="document"]')
close.focus()
close.addEventListener('click', closeDialog, false)
dialogDoc.addEventListener('keydown', function (event) {
let target = event.target
let keyCode = event.keyCode
if (target === close && keyCode === 9) {
dialogDoc.focus()
event.preventDefault()
} else if (target === dialogDoc && event.shiftKey && keyCode === 9) {
close.focus()
event.preventDefault()
} else if (event.keyCode === 27) {
closeDialog()
}
})
function hideAllElse() {
let allElse = document.querySelectorAll('body > *:not(dialog)')
Array.from(allElse, (elem) => {
elem.style.visibility = 'hidden'
})
}
function showAllElse () {
let allElse = document.querySelectorAll('body > *:not(dialog)')
Array.from(allElse, (elem) => {
elem.style.visibility = 'visible'
})
}
function openDialog(dialog) {
dialog.setAttribute('role', 'alertdialog')
dialog.setAttribute('aria-labelledby', 'dialog-title')
dialog.setAttribute('aria-describedby', 'dialog-description')
dialog.setAttribute('open', true)
}
function closeDialog () {
dialog.innerHTML = ''
let attrs = ['open', 'role', 'aria-labelledby', 'aria-describedby']
attrs.forEach(function (attr) {
dialog.removeAttribute(attr)
})
showAllElse()
...