Files
Charon/frontend/src/components/Toast.tsx
GitHub Actions 8294d6ee49 Add QA test outputs, build scripts, and Dockerfile validation
- Created `qa-test-output-after-fix.txt` and `qa-test-output.txt` to log results of certificate page authentication tests.
- Added `build.sh` for deterministic backend builds in CI, utilizing `go list` for efficiency.
- Introduced `codeql_scan.sh` for CodeQL database creation and analysis for Go and JavaScript/TypeScript.
- Implemented `dockerfile_check.sh` to validate Dockerfiles for base image and package manager mismatches.
- Added `sourcery_precommit_wrapper.sh` to facilitate Sourcery CLI usage in pre-commit hooks.
2025-12-11 18:26:24 +00:00

58 lines
1.8 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">
{toasts.map(toast => (
<div
key={toast.id}
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>
)
}