Files
workorders/web/components/shared/ui-toast.mjs
T

52 lines
2.0 KiB
JavaScript

class UiToastContainer extends HTMLElement {
connectedCallback() {
Object.assign(this.style, {
position: 'fixed', top: '1rem', right: '1rem', zIndex: '9999',
display: 'flex', flexDirection: 'column', gap: '.5rem',
maxWidth: '380px', pointerEvents: 'none',
});
}
show(message, type = 'info') {
const colors = { success: 'var(--success)', error: 'var(--danger)', info: 'var(--teal)', warning: 'var(--warning)' };
const icons = { success: 'check-circle', error: 'x-circle', info: 'info', warning: 'alert-triangle' };
const toast = document.createElement('div');
Object.assign(toast.style, {
display: 'flex', alignItems: 'center', gap: '.6rem',
padding: '.75rem 1rem', borderRadius: '8px', color: '#fff',
fontSize: '.875rem', fontFamily: 'inherit',
boxShadow: '0 4px 12px rgba(0,0,0,.25)',
background: colors[type] || colors.info,
animation: 'toastIn .2s ease', pointerEvents: 'auto',
minWidth: '260px',
});
toast.innerHTML = `<i data-lucide="${icons[type] || 'info'}" style="width:16px;height:16px;flex-shrink:0"></i><span>${message}</span>`;
this.appendChild(toast);
if (window.lucide) lucide.createIcons({ root: toast });
const style = document.createElement('style');
style.textContent = `@keyframes toastIn{from{opacity:0;transform:translateX(1rem)}to{opacity:1;transform:none}}`;
if (!document.getElementById('toast-keyframes')) {
style.id = 'toast-keyframes';
document.head.appendChild(style);
}
setTimeout(() => {
toast.style.opacity = '0';
toast.style.transition = 'opacity .3s';
setTimeout(() => toast.remove(), 300);
}, 4000);
}
}
customElements.define('ui-toast-container', UiToastContainer);
let _container = null;
export function showToast(message, type = 'info') {
if (!_container) {
_container = document.createElement('ui-toast-container');
document.body.appendChild(_container);
}
_container.show(message, type);
}