Files
Agentic-OS/frontend/components/toast.tsx
nearxos 6185b9b85a Initial commit: Agentic OS troubleshooting platform
Self-hosted, Docker-based agentic troubleshooting platform: FastAPI backend +
LangGraph agent, Next.js UI, tiered LLM routing (local Ollama -> Gemini ->
DeepSeek -> OpenRouter), MCP server manager, encrypted device credentials,
RBAC, audit log, project-memory + Obsidian integrations, and editable
troubleshooting decision rules tuned for the GeneseasX vessel stack.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 22:11:07 +03:00

76 lines
2.2 KiB
TypeScript

"use client";
import { createContext, useCallback, useContext, useEffect, useState } from "react";
type ToastKind = "success" | "error" | "info";
type Toast = { id: number; kind: ToastKind; message: string };
type ToastContextValue = {
toast: (message: string, kind?: ToastKind) => void;
success: (message: string) => void;
error: (message: string) => void;
};
const ToastContext = createContext<ToastContextValue | null>(null);
let _id = 0;
export function ToastProvider({ children }: { children: React.ReactNode }) {
const [toasts, setToasts] = useState<Toast[]>([]);
const remove = useCallback((id: number) => {
setToasts((prev) => prev.filter((t) => t.id !== id));
}, []);
const toast = useCallback(
(message: string, kind: ToastKind = "info") => {
const id = ++_id;
setToasts((prev) => [...prev, { id, kind, message }]);
setTimeout(() => remove(id), 4500);
},
[remove]
);
const value: ToastContextValue = {
toast,
success: (m) => toast(m, "success"),
error: (m) => toast(m, "error"),
};
return (
<ToastContext.Provider value={value}>
{children}
<div
className="pointer-events-none fixed inset-x-0 bottom-4 z-[100] flex flex-col items-center gap-2 px-4"
aria-live="polite"
role="status"
>
{toasts.map((t) => (
<button
key={t.id}
onClick={() => remove(t.id)}
className={`pointer-events-auto w-full max-w-md rounded-xl border px-4 py-3 text-left text-sm shadow-lg backdrop-blur transition ${
t.kind === "success"
? "border-good/40 bg-good/15 text-good"
: t.kind === "error"
? "border-bad/40 bg-bad/15 text-bad"
: "border-edge bg-panel/90 text-slate-200"
}`}
>
{t.message}
</button>
))}
</div>
</ToastContext.Provider>
);
}
export function useToast(): ToastContextValue {
const ctx = useContext(ToastContext);
if (!ctx) {
// No-op fallback so components don't crash outside the provider.
return { toast: () => {}, success: () => {}, error: () => {} };
}
return ctx;
}