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()
  ...