diff --git a/dialog.js b/dialog.js new file mode 100644 index 0000000..4098ae5 --- /dev/null +++ b/dialog.js @@ -0,0 +1,79 @@ +export class Dialog extends HTMLElement { + constructor() { + super() + this.attachShadow({mode: 'open'}) + this.headerEl = document.createElement('div') + this.headerEl.classList.add('header') + this.bodyEl = document.createElement('div') + this.bodyEl.classList.add('body') + this.footerEl = document.createElement('div') + this.footerEl.classList.add('footer') + this.dialogEl = document.createElement('dialog') + this.dialogEl.replaceChildren( + this.headerEl, this.bodyEl, this.footerEl + ) + this.dialogEl.addEventListener('click', e => { + const rect = this.dialogEl.getBoundingClientRect(); + const clickedInDialog = ( + rect.top <= e.clientY && + e.clientY <= rect.top + rect.height && + rect.left <= e.clientX && + e.clientX <= rect.left + rect.width + ) + if (e.target === this.dialogEl && !clickedInDialog) { + this.close() + } + }) + this.shadowRoot.appendChild(this.dialogEl) + } + + connectedCallback() { + const style = document.createElement('style') + style.textContent = ` + dialog { + margin-top: 120px; + min-width: 200px; + border: 1px solid rgba(0, 0, 0, 0.3); + border-radius: 6px; + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + } + dialog::backdrop { + opacity: 0; + transition: opacity 0.3s ease-in; + background-color: rgba(0, 0, 0, .25); + } + dialog.opened::backdrop { + opacity: 1; + } + dialog.closing { + visibility: hidden; + } + dialog.closing::backdrop { + visibility: visible; + } + .header, .footer, .body { + display: flex; + align-items: stretch; + flex-direction: column; + } + ` + this.shadowRoot.append(style) + this.headerEl.setAttribute('part', 'header') + this.bodyEl.setAttribute('part', 'body') + this.footerEl.setAttribute('part', 'footer') + } + + open() { + this.dialogEl.showModal(); + this.dialogEl.classList.add('opened') + } + + close() { + this.dialogEl.classList.remove('opened') + this.dialogEl.classList.add('closing') + setTimeout(() => { + this.dialogEl.close() + this.dialogEl.classList.remove('closing') + }, 500) + } +} \ No newline at end of file