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
This commit is contained in:
@@ -1,44 +1,40 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import type { Toast } from './toast-utils'
|
||||
|
||||
interface Toast {
|
||||
id: string
|
||||
title?: string
|
||||
description?: string
|
||||
variant?: 'default' | 'destructive'
|
||||
}
|
||||
type ToastEvent = CustomEvent<Toast>
|
||||
|
||||
const Toaster = () => {
|
||||
const [toasts, setToasts] = useState<Toast[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
const handleToast = (e: CustomEvent<Toast>) => {
|
||||
const toast = { ...e.detail, id: Math.random().toString(36) }
|
||||
setToasts((prev) => [...prev, toast])
|
||||
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 !== toast.id))
|
||||
setToasts((prev) => prev.filter((t) => t.id !== toastItem.id))
|
||||
}, 5000)
|
||||
}
|
||||
|
||||
window.addEventListener('toast' as any, handleToast)
|
||||
return () => window.removeEventListener('toast' as any, handleToast)
|
||||
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((toast) => (
|
||||
{toasts.map((toastItem) => (
|
||||
<div
|
||||
key={toast.id}
|
||||
key={toastItem.id}
|
||||
className={`rounded-lg border p-4 shadow-lg ${
|
||||
toast.variant === 'destructive'
|
||||
toastItem.variant === 'destructive'
|
||||
? 'border-destructive bg-destructive text-destructive-foreground'
|
||||
: 'border-border bg-background'
|
||||
}`}
|
||||
>
|
||||
{toast.title && <div className="font-semibold">{toast.title}</div>}
|
||||
{toast.description && <div className="text-sm">{toast.description}</div>}
|
||||
{toastItem.title && <div className="font-semibold">{toastItem.title}</div>}
|
||||
{toastItem.description && <div className="text-sm">{toastItem.description}</div>}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -46,6 +42,3 @@ const Toaster = () => {
|
||||
}
|
||||
|
||||
export { Toaster }
|
||||
export const toast = (props: Omit<Toast, 'id'>) => {
|
||||
window.dispatchEvent(new CustomEvent('toast', { detail: props }))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user