mirror of
https://github.com/CopilotKit/CopilotKit.git
synced 2026-09-14 16:26:20 +08:00
b1b7bb5cb8
Baseline tab (new): - 33-feature x 25-partner correctness matrix from Notion Partner Hub - E3 cell treatment: status emoji + colored letter badges (C/A/I/▶/D/T/✱) - View/Edit toggle with commit/cancel accumulator (batch saves to PB) - PocketBase baseline collection with public read/write, SSE live updates - Stats bar, collapsible categories, fixed legend, 200ms CSS tooltips - Full-row hover highlight, zebra stripes matching Coverage tab Coverage tab fixes: - Depth chip: green = at max achievable (not hardcoded per level) - maxPossible computed from probe existence (CATALOG_TO_D5_KEY) - D5 false positives: removed shared key aliases - Stats bar derives green/amber/red from same logic as depth chips - Hide badges for non-existent tests (was strikethrough) - Render perf: memoize featuresByCategory, React.memo CategorySection - Load perf: getFullList single call (was 7 sequential round-trips) Both tabs: - Dark/light/system theme toggle (upper right) - Column order: Coverage first (1-18), Baseline extras (19-25) - LangGraph naming (orchestration layer, not model router) - Row hover highlight including sticky column
48 lines
1.1 KiB
TypeScript
48 lines
1.1 KiB
TypeScript
"use client";
|
|
import { useEffect, useState } from "react";
|
|
|
|
interface Toast {
|
|
id: number;
|
|
message: string;
|
|
}
|
|
|
|
let nextId = 0;
|
|
const listeners: Set<(toast: Toast) => void> = new Set();
|
|
|
|
export function showErrorToast(message: string): void {
|
|
const toast: Toast = { id: nextId++, message };
|
|
listeners.forEach((fn) => fn(toast));
|
|
}
|
|
|
|
export function BaselineToastContainer() {
|
|
const [toasts, setToasts] = useState<Toast[]>([]);
|
|
|
|
useEffect(() => {
|
|
const handler = (toast: Toast) => {
|
|
setToasts((prev) => [...prev, toast]);
|
|
setTimeout(() => {
|
|
setToasts((prev) => prev.filter((t) => t.id !== toast.id));
|
|
}, 5000);
|
|
};
|
|
listeners.add(handler);
|
|
return () => {
|
|
listeners.delete(handler);
|
|
};
|
|
}, []);
|
|
|
|
if (toasts.length === 0) return null;
|
|
|
|
return (
|
|
<div className="fixed bottom-20 right-4 z-[60] flex flex-col gap-2">
|
|
{toasts.map((t) => (
|
|
<div
|
|
key={t.id}
|
|
className="px-4 py-2.5 rounded-lg text-sm font-medium bg-[var(--danger)] text-white shadow-lg"
|
|
>
|
|
{t.message}
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|