Files
mockupAWS/frontend/src/components/ui/toaster.tsx
Luca Sacchi Ricciardi d222d21618 docs: update documentation for v0.4.0 release
- Update README.md with v0.4.0 features and screenshots placeholders
- Update architecture.md with v0.4.0 implementation status
- Update progress.md marking all 27 tasks as completed
- Create CHANGELOG.md with complete release notes
- Add v0.4.0 frontend components and hooks
2026-04-07 18:07:23 +02:00

45 lines
1.3 KiB
TypeScript

import { useState, useEffect } from 'react'
import type { Toast } from './toast-utils'
type ToastEvent = CustomEvent<Toast>
const Toaster = () => {
const [toasts, setToasts] = useState<Toast[]>([])
useEffect(() => {
const handleToast = (e: ToastEvent) => {
const toastItem = { ...e.detail, id: Math.random().toString(36) }
setToasts((prev) => [...prev, toastItem])
setTimeout(() => {
setToasts((prev) => prev.filter((t) => t.id !== toastItem.id))
}, 5000)
}
window.addEventListener('toast', handleToast as EventListener)
return () => window.removeEventListener('toast', handleToast as EventListener)
}, [])
if (toasts.length === 0) return null
return (
<div className="fixed bottom-4 right-4 z-50 flex flex-col gap-2">
{toasts.map((toastItem) => (
<div
key={toastItem.id}
className={`rounded-lg border p-4 shadow-lg ${
toastItem.variant === 'destructive'
? 'border-destructive bg-destructive text-destructive-foreground'
: 'border-border bg-background'
}`}
>
{toastItem.title && <div className="font-semibold">{toastItem.title}</div>}
{toastItem.description && <div className="text-sm">{toastItem.description}</div>}
</div>
))}
</div>
)
}
export { Toaster }