57 lines
2.6 KiB
JavaScript
57 lines
2.6 KiB
JavaScript
class UiDialog extends HTMLElement {
|
|
connectedCallback() {
|
|
this.attachShadow({ mode: 'open' });
|
|
this.shadowRoot.innerHTML = `
|
|
<style>
|
|
:host { display: contents; }
|
|
dialog {
|
|
border: none; border-radius: var(--radius-lg); padding: 0;
|
|
background: var(--surface); color: var(--text);
|
|
box-shadow: var(--shadow-lg); max-height: 90vh; overflow: hidden;
|
|
display: flex; flex-direction: column;
|
|
}
|
|
dialog[open] { display: flex; }
|
|
dialog::backdrop { background: rgba(0,0,0,.45); backdrop-filter: blur(2px); }
|
|
.size-sm { width: min(400px, 95vw); }
|
|
.size-md { width: min(600px, 95vw); }
|
|
.size-lg { width: min(860px, 95vw); }
|
|
.header {
|
|
display: flex; align-items: center; justify-content: space-between;
|
|
padding: 1.1rem 1.25rem; border-bottom: 1px solid var(--border);
|
|
flex-shrink: 0;
|
|
}
|
|
.header h2 { font-size: 1rem; font-weight: 600; }
|
|
.close-btn {
|
|
background: none; border: none; cursor: pointer; color: var(--text-muted);
|
|
padding: .25rem; border-radius: var(--radius-sm); display: flex;
|
|
transition: color .15s;
|
|
}
|
|
.close-btn:hover { color: var(--text); }
|
|
.body { padding: 1.25rem; overflow-y: auto; flex: 1; }
|
|
@media (max-width: 768px) {
|
|
dialog { width: 100vw !important; max-height: 85vh; border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
|
|
dialog[open] { position: fixed; bottom: 0; left: 0; margin: 0; }
|
|
}
|
|
</style>
|
|
<dialog class="size-${this.getAttribute('size') || 'md'}">
|
|
<div class="header">
|
|
<h2>${this.getAttribute('title') || ''}</h2>
|
|
<button class="close-btn" aria-label="Close">
|
|
<i data-lucide="x" style="width:18px;height:18px"></i>
|
|
</button>
|
|
</div>
|
|
<div class="body"><slot></slot></div>
|
|
</dialog>`;
|
|
|
|
const dialog = this.shadowRoot.querySelector('dialog');
|
|
this.shadowRoot.querySelector('.close-btn').addEventListener('click', () => this.close());
|
|
dialog.addEventListener('click', e => { if (e.target === dialog) this.close(); });
|
|
document.addEventListener('keydown', e => { if (e.key === 'Escape') this.close(); });
|
|
if (window.lucide) lucide.createIcons({ root: this.shadowRoot });
|
|
}
|
|
|
|
open() { this.shadowRoot?.querySelector('dialog')?.showModal(); }
|
|
close() { this.shadowRoot?.querySelector('dialog')?.close(); this.dispatchEvent(new CustomEvent('ui:close', { bubbles: true, composed: true })); }
|
|
}
|
|
customElements.define('ui-dialog', UiDialog);
|