Files
Charon/frontend/src/components/Toast.tsx
GitHub Actions bc9c6e2abd feat: Add end-to-end tests for DNS Provider Types and UI interactions
- Implement API tests for DNS Provider Types, validating built-in and custom providers.
- Create UI tests for provider selection, ensuring all types are displayed and descriptions are shown.
- Introduce fixtures for consistent test data across DNS Provider tests.
- Update manual DNS provider tests to improve structure and accessibility checks.
2026-01-15 01:37:21 +00:00

61 lines
1.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useEffect, useState } from 'react'
import { toastCallbacks, Toast } from '../utils/toast'
export function ToastContainer() {
const [toasts, setToasts] = useState<Toast[]>([])
useEffect(() => {
const callback = (toast: Toast) => {
setToasts(prev => [...prev, toast])
setTimeout(() => {
setToasts(prev => prev.filter(t => t.id !== toast.id))
}, 5000)
}
toastCallbacks.add(callback)
return () => {
toastCallbacks.delete(callback)
}
}, [])
const removeToast = (id: number) => {
setToasts(prev => prev.filter(t => t.id !== id))
}
return (
<div className="fixed bottom-4 right-4 z-50 flex flex-col gap-2 pointer-events-none" data-testid="toast-container">
{toasts.map(toast => (
<div
key={toast.id}
role="status"
aria-live="polite"
data-testid={`toast-${toast.type}`}
className={`pointer-events-auto px-4 py-3 rounded-lg shadow-lg flex items-center gap-3 min-w-[300px] max-w-[500px] animate-slide-in ${
toast.type === 'success'
? 'bg-green-600 text-white'
: toast.type === 'error'
? 'bg-red-600 text-white'
: toast.type === 'warning'
? 'bg-yellow-600 text-white'
: 'bg-blue-600 text-white'
}`}
>
<div className="flex-1">
{toast.type === 'success' && <span className="mr-2"></span>}
{toast.type === 'error' && <span className="mr-2"></span>}
{toast.type === 'warning' && <span className="mr-2"></span>}
{toast.type === 'info' && <span className="mr-2"></span>}
{toast.message}
</div>
<button
onClick={() => removeToast(toast.id)}
className="text-white/80 hover:text-white transition-colors"
aria-label="Close"
>
×
</button>
</div>
))}
</div>
)
}