Add copy button to JSON & fix button styles override.
This commit is contained in:
@@ -33,7 +33,7 @@ const JsonView = memo(
|
||||
: data;
|
||||
|
||||
return (
|
||||
<div className="font-mono text-sm transition-all duration-300 ">
|
||||
<div className="font-mono text-sm transition-all duration-300">
|
||||
<JsonNode
|
||||
data={normalizedData as JsonValue}
|
||||
name={name}
|
||||
|
||||
@@ -13,10 +13,11 @@ import {
|
||||
ListToolsResult,
|
||||
Tool,
|
||||
} from "@modelcontextprotocol/sdk/types.js";
|
||||
import { AlertCircle, Send } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { AlertCircle, Copy, Send, CheckCheck } from "lucide-react";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import ListPane from "./ListPane";
|
||||
import JsonView from "./JsonView";
|
||||
import { toast } from 'react-toastify'
|
||||
|
||||
const ToolsTab = ({
|
||||
tools,
|
||||
@@ -44,6 +45,20 @@ const ToolsTab = ({
|
||||
setParams({});
|
||||
}, [selectedTool]);
|
||||
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
const handleCopy = useCallback(() => {
|
||||
try {
|
||||
navigator.clipboard.writeText(JSON.stringify(toolResult))
|
||||
setCopied(true)
|
||||
setTimeout(() => {
|
||||
setCopied(false)
|
||||
}, 500)
|
||||
} catch (error) {
|
||||
toast.error(`There was an error coping result into the clipboard: ${error instanceof Error ? error.message : String(error)}`)
|
||||
}
|
||||
}, [toolResult])
|
||||
|
||||
const renderToolResult = () => {
|
||||
if (!toolResult) return null;
|
||||
|
||||
@@ -53,7 +68,8 @@ const ToolsTab = ({
|
||||
return (
|
||||
<>
|
||||
<h4 className="font-semibold mb-2">Invalid Tool Result:</h4>
|
||||
<div className="p-4 border rounded">
|
||||
<div className="p-4 border rounded relative">
|
||||
<Copy className="size-4 text-primary" />
|
||||
<JsonView data={toolResult} />
|
||||
</div>
|
||||
<h4 className="font-semibold mb-2">Errors:</h4>
|
||||
@@ -76,7 +92,12 @@ const ToolsTab = ({
|
||||
{structuredResult.content.map((item, index) => (
|
||||
<div key={index} className="mb-2">
|
||||
{item.type === "text" && (
|
||||
<div className="p-4 border rounded">
|
||||
<div className="p-4 border rounded relative">
|
||||
<Button size="icon" variant="ghost" className="absolute top-2 right-2" onClick={handleCopy}>
|
||||
{copied ?
|
||||
<CheckCheck className="size-4 dark:text-green-700 text-green-600" />
|
||||
: <Copy className="size-4 text-foreground" />}
|
||||
</Button>
|
||||
<JsonView data={item.text} />
|
||||
</div>
|
||||
)}
|
||||
@@ -234,7 +255,7 @@ const ToolsTab = ({
|
||||
...params,
|
||||
[key]:
|
||||
prop.type === "number" ||
|
||||
prop.type === "integer"
|
||||
prop.type === "integer"
|
||||
? Number(e.target.value)
|
||||
: e.target.value,
|
||||
})
|
||||
|
||||
@@ -81,7 +81,6 @@ describe("ToolsTab", () => {
|
||||
expect(newInput.value).toBe("");
|
||||
});
|
||||
|
||||
|
||||
it("should display error message when error prop is provided", () => {
|
||||
const errorMessage = "Test error message";
|
||||
renderToolsTab({
|
||||
|
||||
@@ -38,29 +38,6 @@ h1 {
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
button:hover {
|
||||
border-color: #646cff;
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
button[role="checkbox"] {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #213547;
|
||||
@@ -69,9 +46,6 @@ button[role="checkbox"] {
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
|
||||
Reference in New Issue
Block a user