MCP-WebGPU / src /components /ResultBlock.tsx
shreyask's picture
feat: implement debounced auto-save for conversations and enhance ResultBlock component with truncation support
4513a96 verified
import React, { useState, useMemo } from "react";
interface ResultBlockProps {
error?: string;
result?: unknown;
}
const ResultBlock: React.FC<ResultBlockProps> = ({
error,
result,
}) => {
const [isExpanded, setIsExpanded] = useState(false);
const MAX_LENGTH = 10000; // Characters to show before truncating
const formattedResult = useMemo(() => {
if (result === undefined || result === null) {
return "No result";
}
if (typeof result !== "object") {
return String(result);
}
try {
const fullString = JSON.stringify(result, null, 2);
// If the result is very large, provide truncation
if (fullString.length > MAX_LENGTH && !isExpanded) {
return fullString.substring(0, MAX_LENGTH);
}
return fullString;
} catch (err) {
// Handle circular references or other JSON.stringify errors
return String(result);
}
}, [result, isExpanded]);
const isTruncated = useMemo(() => {
if (typeof result !== "object" || result === null) return false;
try {
return JSON.stringify(result, null, 2).length > MAX_LENGTH;
} catch {
return false;
}
}, [result]);
return (
<div
className={
error
? "bg-red-900 border border-red-600 rounded p-3"
: "bg-gray-700 border border-gray-600 rounded p-3"
}
>
{error ? <p className="text-red-300 text-sm">Error: {error}</p> : null}
<pre className="text-sm text-gray-300 whitespace-pre-wrap overflow-auto mt-2 max-h-96">
{formattedResult}
{isTruncated && !isExpanded && (
<span className="text-yellow-400">... (truncated)</span>
)}
</pre>
{isTruncated && (
<button
onClick={() => setIsExpanded(!isExpanded)}
className="mt-2 text-xs text-blue-400 hover:text-blue-300 underline"
>
{isExpanded ? "Show less" : "Show full result"}
</button>
)}
</div>
);
};
export default ResultBlock;