<div class="dialog-wrapper" ref:node> <div class="close-dialog-button-wrapper"> <button class="close-dialog-button" aria-label="Close dialog" on:click="close()"> <span aria-hidden="true">×</span> </button> </div> <slot></slot> </div> <style> :global(.modal-dialog) { position: fixed; top: 50%; transform: translate(0, -50%); background: #000; padding: 0; border: 3px solid var(--main-border); } :global(.modal-dialog-wrapper) { display: flex; flex-direction: column; align-items: center; justify-content: center; max-width: calc(100vw - 40px); } .close-dialog-button-wrapper { text-align: right; width: 100%; background: var(--nav-bg) } .close-dialog-button { margin: 0 0 2px; padding: 0; background: none; border: none; } .close-dialog-button span { padding: 0 15px; font-size: 48px; color: var(--button-primary-text); } :global(dialog::backdrop, .backdrop) { background: rgba(51, 51, 51, 0.9) !important; /* TODO: hack for Safari */ } </style> <script> import { importDialogPolyfill } from '../_utils/asyncModules' import { registerFocusRestoreDialog } from '../_utils/dialogs' export default { oncreate() { // TODO: this hack is for Edge 16, which makes the modal too wide if (typeof setImmediate === 'function' && navigator.userAgent.match(/Edge/)) { this.getDialogElement().style.width = `${this.get('width')}px` } this.observe('shown', shown => { if (shown) { this.show() } }) this.registration = this.register() this.onDocumentClick = (e) => { let dialog = this.getDialogElement() if (!dialog.open) { return; } if (e.target !== dialog) { return; } this.close() // close when clicked outside of dialog } document.body.addEventListener('click', this.onDocumentClick); }, methods: { async register() { if (typeof HTMLDialogElement === 'undefined') { let dialogPolyfill = await importDialogPolyfill() dialogPolyfill.registerDialog(this.getDialogElement()) } registerFocusRestoreDialog(this.getDialogElement()) }, async show() { await this.registration this.getDialogElement().showModal() }, close() { this.getDialogElement().close() document.body.removeChild(this.getDialogElement()) document.body.removeEventListener('click', this.onDocumentClick); }, getDialogElement() { return this.refs.node.parentElement } } } </script>