interface AlertDetail { type: 'alert-info' | 'alert-warning' | 'alert-success' | 'alert-error' message: string } class AlertEvent extends CustomEvent { constructor(detail: AlertDetail) { super('alert', { detail }) } } const alertTemplate = document.createElement('template') alertTemplate.innerHTML = `
` class Alert extends HTMLElement { constructor(alertDetail: AlertDetail) { super() this.appendChild(alertTemplate.content.cloneNode(true)) const outer = this.querySelector('div')! outer.classList.add(alertDetail.type) const message = this.querySelector('span')! message.textContent = alertDetail.message } } const alertBoxTemplate = document.createElement('template') alertBoxTemplate.innerHTML = `
` class AlertBox extends HTMLElement { private readonly alertBox: HTMLDivElement constructor() { super() this.appendChild(alertBoxTemplate.content.cloneNode(true)) this.alertBox = this.querySelector('#alert-box')! } public add = (alertDetail: AlertDetail) => { const alert = new Alert(alertDetail) this.alertBox.appendChild(alert) setTimeout(() => alert.remove(), 7000) } public static define() { customElements.define('alert-element', Alert) customElements.define('alert-box', AlertBox) } } export default AlertBox export { AlertEvent, type AlertDetail }