type ToastOptions = { duration?: number; }; export class Toast { private container: HTMLDivElement; constructor() { this.container = document.createElement('div'); this.container.style.position = 'fixed'; this.container.style.top = '10px'; this.container.style.right = '10px'; this.container.style.display = 'flex'; this.container.style.flexDirection = 'column'; this.container.style.gap = '10px'; this.container.style.zIndex = '9999'; document.body.appendChild(this.container); } show(message: string, options?: ToastOptions) { const toast = document.createElement('div'); toast.textContent = message; Object.assign(toast.style, { background: 'rgba(0,0,0,0.8)', color: 'white', padding: '10px 15px', borderRadius: '5px', fontFamily: 'sans-serif', fontSize: '14px', boxShadow: '0 2px 5px rgba(0,0,0,0.3)', opacity: '0', // start invisible transform: 'translateX(100%)', // slide in from right transition: 'opacity 0.3s, transform 0.3s' }); this.container.appendChild(toast); requestAnimationFrame(() => { toast.style.opacity = '1'; toast.style.transform = 'translateX(0)'; }); const duration = options?.duration ?? 3000; setTimeout(() => this.removeToast(toast), duration); } private removeToast(toast: HTMLDivElement) { toast.style.opacity = '0'; toast.style.transform = 'translateX(100%)'; toast.addEventListener('transitionend', () => { toast.remove(); }); } }