Skip to content

Commit 6c0e52a

Browse files
kkadhithfacebook-github-bot
authored andcommitted
Add copy button to source code view panel (#82)
Summary: This commit introduces the a feature to allow users to copy source code in each code viewer panel. Changes: - Added CopyCodeButton.tsx, a reusable button component to click and copy code passed in through a prop - Modified CodeComparisonViews to integrate the button Testing/Verification: 1. Run a build with this commit 2. Open a Triton log file, then view IR code comparison 3. Verify the button exists in the code viewer panel next to the display language 4. Verify clicking the button correctly copies code and changes behavior by showing a checkmark Fixes: #78 Pull Request resolved: #82 Reviewed By: adamomainz Differential Revision: D81042409 Pulled By: FindHao fbshipit-source-id: b652626b9b31be29d68c57ea12a561dbac45de0b
1 parent 2c71c04 commit 6c0e52a

File tree

3 files changed

+81
-6
lines changed

3 files changed

+81
-6
lines changed

website/src/components/CodeComparisonView.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { useState, useCallback } from "react";
22
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
33
import CodeViewer from "./CodeViewer";
4+
import CopyCodeButton from "./CopyCodeButton";
45
import {
56
IRFile,
67
PythonSourceCodeInfo,
@@ -334,9 +335,15 @@ const CodeComparisonView: React.FC<CodeComparisonViewProps> = ({
334335
<div className="h-full">
335336
<div className="bg-blue-600 text-white p-2 font-medium flex justify-between items-center">
336337
<span>{title}</span>
337-
<span className="text-sm bg-blue-700 px-2 py-1 rounded">
338-
{displayLanguage}
339-
</span>
338+
<div className="flex items-center gap-2">
339+
<span className="text-sm bg-blue-700 px-2 py-1 rounded">
340+
{displayLanguage}
341+
</span>
342+
<CopyCodeButton
343+
code={code}
344+
className="text-sm bg-blue-700 px-2 py-1 rounded"
345+
/>
346+
</div>
340347
</div>
341348
<CodeViewer
342349
code={code}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import React, { useState } from "react";
2+
3+
/**
4+
* Props for the CopyCodeButton component.
5+
*/
6+
interface CopyCodeButtonProps {
7+
/** Code passed in so it can be copied */
8+
code: string;
9+
/** To modify styling on the fly (so the component can be used anywhere)*/
10+
className?: string;
11+
}
12+
13+
/**
14+
* A reusable copy code button component with styling that can be modified.
15+
*/
16+
const CopyCodeButton: React.FC<CopyCodeButtonProps> = ({
17+
code,
18+
className = "",
19+
}) => {
20+
const [copied, setCopied] = useState(false);
21+
22+
const handleCopy = async () => {
23+
try {
24+
await navigator.clipboard.writeText(code);
25+
setCopied(true);
26+
setTimeout(() => setCopied(false), 3000);
27+
} catch (err) {
28+
console.error("Failed to copy code:", err);
29+
}
30+
};
31+
32+
return (
33+
<div className="flex items-center">
34+
<button
35+
onClick={handleCopy}
36+
className={`${className}`}
37+
title={copied ? "Copied!" : "Copy code"}
38+
aria-label={copied ? "Code copied to clipboard" : "Copy code to clipboard"}
39+
>
40+
{copied ? (
41+
// https://heroicons.com/
42+
<span>
43+
{/* Checkmark SVG icon */}
44+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" className="size-5">
45+
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" />
46+
</svg>
47+
</span>
48+
) : (
49+
<span>
50+
{/* Clipboard copy icon */}
51+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" className="size-5">
52+
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 7.5V6.108c0-1.135.845-2.098 1.976-2.192.373-.03.748-.057 1.123-.08M15.75 18H18a2.25 2.25 0 0 0 2.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 0 0-1.123-.08M15.75 18.75v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5A3.375 3.375 0 0 0 6.375 7.5H5.25m11.9-3.664A2.251 2.251 0 0 0 15 2.25h-1.5a2.251 2.251 0 0 0-2.15 1.586m5.8 0c.065.21.1.433.1.664v.75h-6V4.5c0-.231.035-.454.1-.664M6.75 7.5H4.875c-.621 0-1.125.504-1.125 1.125v12c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V16.5a9 9 0 0 0-9-9Z" />
53+
</svg>
54+
</span>
55+
)}
56+
</button>
57+
</div>
58+
);
59+
};
60+
61+
export default CopyCodeButton;

website/src/components/SingleCodeViewer.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { useState } from "react";
22
import CodeViewer from "./CodeViewer";
33
import { IRFile } from "../utils/dataLoader";
44
import { getDisplayLanguage } from "./TritonIRs";
5+
import CopyCodeButton from "./CopyCodeButton";
56

67
/**
78
* Props for the SingleCodeViewer component
@@ -114,9 +115,15 @@ const SingleCodeViewer: React.FC<SingleCodeViewerProps> = ({
114115
{/* Panel title bar */}
115116
<div className="bg-blue-600 text-white p-2 font-medium flex justify-between items-center">
116117
<span>{title}</span>
117-
<span className="text-sm bg-blue-700 px-2 py-1 rounded">
118-
{displayLanguage}
119-
</span>
118+
<div className="flex items-center gap-2">
119+
<span className="text-sm bg-blue-700 px-2 py-1 rounded">
120+
{displayLanguage}
121+
</span>
122+
<CopyCodeButton
123+
code={codeContent}
124+
className="text-sm bg-blue-700 px-2 py-1 rounded"
125+
/>
126+
</div>
120127
</div>
121128
{/* Code content area with fixed height */}
122129
<div className="h-[calc(100vh-12rem)]">

0 commit comments

Comments
 (0)