Skip to content

Instantly share code, notes, and snippets.

@nolanlawson
Last active June 13, 2022 14:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nolanlawson/13cbc222f8aa47ffd3e5e28838122d4b to your computer and use it in GitHub Desktop.
Save nolanlawson/13cbc222f8aa47ffd3e5e28838122d4b to your computer and use it in GitHub Desktop.
Modal with inert demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Pseudo-dialog using inert and shadow DOM</title>
<style>
body {
margin: 0 auto;
max-width: 400px;
padding: 40px;
}
[role=dialog] {
display: none;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 2;
background-color: rgba(30, 30, 30, 0.3);
}
[role=dialog].open {
display: flex;
}
.dialog-inner {
max-width: 90vw;
margin: 0 auto;
overflow-x: auto;
padding: 20px;
}
</style>
</head>
<body>
<h1>Pseudo-dialog using inert and shadow DOM</h1>
<p>Browser supports <code>inert</code>? <span id="supports"></span></p>
<p>Tab around with the keyboard, open a pseudo-dialog using <code>inert</code>, press Esc to close.</p>
<button>Focusable button</button>
<button class="modal-button">Click to open modal dialog</button>
<button>Another focusable button</button>
<div role="dialog">
<div class="dialog-inner">
<div>
<button>Light button</button>
<open-shadow></open-shadow>
<button>Another light button</button>
</div>
<video controls src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.webm"></video>
<div>
<button>Light button</button>
<closed-shadow></closed-shadow>
<button>Another light button</button>
</div>
</div>
</div>
<script>
document.querySelector('#supports').textContent = 'inert' in HTMLElement.prototype ? 'Yes' : 'No'
function addStyle(root) {
const css = `
button:focus {
outline: 4px dashed blue;
outline-offset: -2px;
}
button {
font-size: 1.2em;
padding: 5px;
margin: 5px;
}`
const style = document.createElement('style')
style.textContent = css
root.appendChild(style)
}
class ClosedShadow extends HTMLElement {
constructor () {
super()
const shadow = this.attachShadow({ mode: 'closed' })
shadow.innerHTML = '<button>Closed shadow button!</button>'
addStyle(shadow)
}
}
class OpenShadow extends HTMLElement {
constructor () {
super()
const shadow = this.attachShadow({ mode: 'open' })
shadow.innerHTML = '<button>Open shadow button!</button>'
addStyle(shadow)
}
}
customElements.define('closed-shadow', ClosedShadow)
customElements.define('open-shadow', OpenShadow)
function openOrCloseDialog(open) {
for (const element of document.body.children) {
if (element !== dialog) {
if (open) {
element.setAttribute('inert', 'true')
} else {
element.removeAttribute('inert')
}
}
}
dialog.classList.toggle('open', open)
}
const dialog = document.querySelector('[role=dialog]')
const launchButton = document.querySelector('.modal-button')
launchButton.addEventListener('click', () => {
openOrCloseDialog(true)
dialog.querySelector('button').focus()
})
dialog.addEventListener('keydown', e => {
if (e.key === 'Escape') {
e.preventDefault()
e.stopPropagation()
openOrCloseDialog(false)
launchButton.focus()
}
})
addStyle(document.head)
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment