prvi kod za live uporabu
Some checks failed
ERP CI Pipeline / test (push) Has been cancelled

This commit is contained in:
mariomitte
2026-07-09 21:21:17 +02:00
parent 857bb65d52
commit 5d39e048ba
239 changed files with 25151 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
import type { ToastMessage } from '../../hooks/useToast';
const STYLES: Record<ToastMessage['type'], string> = {
success: 'border-emerald-300 bg-emerald-500/15 text-emerald-100',
error: 'border-red-300 bg-red-500/15 text-red-100',
warning: 'border-amber-300 bg-amber-500/15 text-amber-100',
info: 'border-sky-300 bg-sky-500/15 text-sky-100',
};
interface ToastItemProps {
toast: ToastMessage;
onClose: (id: string) => void;
}
export default function ToastItem({ toast, onClose }: ToastItemProps) {
return (
<article
className={`pointer-events-auto rounded-lg border px-4 py-3 shadow-lg backdrop-blur ${STYLES[toast.type]}`}
role="status"
aria-live="polite"
>
<div className="flex items-start justify-between gap-3">
<p className="text-sm">{toast.message}</p>
<button
type="button"
className="text-xs opacity-80 hover:opacity-100"
onClick={() => onClose(toast.id)}
aria-label="Close toast"
>
</button>
</div>
</article>
);
}

View File

@@ -0,0 +1,28 @@
import { useEffect } from 'preact/hooks';
import ToastItem from './ToastItem';
import { removeToast, toastMessages } from '../../hooks/useToast';
export default function ToastProvider() {
const toasts = Array.isArray(toastMessages.value) ? toastMessages.value : [];
useEffect(() => {
const timers = toasts.map((toast) =>
window.setTimeout(() => removeToast(toast.id), toast.durationMs)
);
return () => {
timers.forEach((timer) => window.clearTimeout(timer));
};
}, [toasts]);
if (!toasts.length) {
return null;
}
return (
<section className="pointer-events-none fixed right-4 top-4 z-[80] flex w-full max-w-sm flex-col gap-2">
{toasts.map((toast) => (
<ToastItem key={toast.id} toast={toast} onClose={removeToast} />
))}
</section>
);
}