Skip to content

Commit 539de0f

Browse files
add copy button
1 parent f9cb2c1 commit 539de0f

File tree

3 files changed

+35
-31
lines changed

3 files changed

+35
-31
lines changed

client/src/components/JsonView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const JsonView = memo(
3333
: data;
3434

3535
return (
36-
<div className="font-mono text-sm transition-all duration-300 ">
36+
<div className="font-mono text-sm transition-all duration-300">
3737
<JsonNode
3838
data={normalizedData as JsonValue}
3939
name={name}

client/src/components/ToolsTab.tsx

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ import {
1313
ListToolsResult,
1414
Tool,
1515
} from "@modelcontextprotocol/sdk/types.js";
16-
import { Send } from "lucide-react";
17-
import { useEffect, useState } from "react";
16+
import { Copy, Send, CheckCheck } from "lucide-react";
17+
import { useCallback, useEffect, useState } from "react";
1818
import ListPane from "./ListPane";
1919
import JsonView from "./JsonView";
20+
import { toast } from "react-toastify";
2021

2122
const ToolsTab = ({
2223
tools,
@@ -43,6 +44,22 @@ const ToolsTab = ({
4344
setParams({});
4445
}, [selectedTool]);
4546

47+
const [copied, setCopied] = useState(false);
48+
49+
const handleCopy = useCallback(() => {
50+
try {
51+
navigator.clipboard.writeText(JSON.stringify(toolResult));
52+
setCopied(true);
53+
setTimeout(() => {
54+
setCopied(false);
55+
}, 500);
56+
} catch (error) {
57+
toast.error(
58+
`There was an error coping result into the clipboard: ${error instanceof Error ? error.message : String(error)}`,
59+
);
60+
}
61+
}, [toolResult]);
62+
4663
const renderToolResult = () => {
4764
if (!toolResult) return null;
4865

@@ -52,7 +69,8 @@ const ToolsTab = ({
5269
return (
5370
<>
5471
<h4 className="font-semibold mb-2">Invalid Tool Result:</h4>
55-
<div className="p-4 border rounded">
72+
<div className="p-4 border rounded relative">
73+
<Copy className="size-4 text-primary" />
5674
<JsonView data={toolResult} />
5775
</div>
5876
<h4 className="font-semibold mb-2">Errors:</h4>
@@ -75,7 +93,19 @@ const ToolsTab = ({
7593
{structuredResult.content.map((item, index) => (
7694
<div key={index} className="mb-2">
7795
{item.type === "text" && (
78-
<div className="p-4 border rounded">
96+
<div className="p-4 border rounded relative">
97+
<Button
98+
size="icon"
99+
variant="ghost"
100+
className="absolute top-2 right-2"
101+
onClick={handleCopy}
102+
>
103+
{copied ? (
104+
<CheckCheck className="size-4 dark:text-green-700 text-green-600" />
105+
) : (
106+
<Copy className="size-4 text-foreground" />
107+
)}
108+
</Button>
79109
<JsonView data={item.text} />
80110
</div>
81111
)}

client/src/index.css

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -38,29 +38,6 @@ h1 {
3838
line-height: 1.1;
3939
}
4040

41-
button {
42-
border-radius: 8px;
43-
border: 1px solid transparent;
44-
padding: 0.6em 1.2em;
45-
font-size: 1em;
46-
font-weight: 500;
47-
font-family: inherit;
48-
background-color: #1a1a1a;
49-
cursor: pointer;
50-
transition: border-color 0.25s;
51-
}
52-
button:hover {
53-
border-color: #646cff;
54-
}
55-
button:focus,
56-
button:focus-visible {
57-
outline: 4px auto -webkit-focus-ring-color;
58-
}
59-
60-
button[role="checkbox"] {
61-
padding: 0;
62-
}
63-
6441
@media (prefers-color-scheme: light) {
6542
:root {
6643
color: #213547;
@@ -69,9 +46,6 @@ button[role="checkbox"] {
6946
a:hover {
7047
color: #747bff;
7148
}
72-
button {
73-
background-color: #f9f9f9;
74-
}
7549
}
7650

7751
@layer base {

0 commit comments

Comments
 (0)