Skip to content

Commit 63cc6aa

Browse files
Vijaykv5peterj
andauthored
fix : copy button functionality in code blocks (#665)
* fix(ui): Fix copy button functionality in code blocks Signed-off-by: vijaykv5 <vijaykv2228@gmail.com> * fix : add type safety Signed-off-by: vijaykv5 <vijaykv2228@gmail.com> * making the button more proportional Signed-off-by: Peter Jausovec <peter.jausovec@solo.io> --------- Signed-off-by: vijaykv5 <vijaykv2228@gmail.com> Signed-off-by: Peter Jausovec <peter.jausovec@solo.io> Co-authored-by: Peter Jausovec <peterj@users.noreply.github.com> Co-authored-by: Peter Jausovec <peter.jausovec@solo.io>
1 parent 2218819 commit 63cc6aa

File tree

1 file changed

+32
-4
lines changed

1 file changed

+32
-4
lines changed

ui/src/components/chat/CodeBlock.tsx

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,36 @@
11
"use client";
2+
import React, { useState } from "react";
23
import { Check, Copy } from "lucide-react";
3-
import { useState } from "react";
44
import { Button } from "../ui/button";
55

6+
const hasChildren = (props: unknown): props is { children: React.ReactNode } => {
7+
return typeof props === 'object' && props !== null && 'children' in props;
8+
};
9+
10+
const extractTextFromReactNode = (node: React.ReactNode): string => {
11+
if (typeof node === "string") {
12+
return node;
13+
}
14+
if (Array.isArray(node)) {
15+
return node.map(extractTextFromReactNode).join("");
16+
}
17+
if (React.isValidElement(node) && node.props && hasChildren(node.props)) {
18+
return extractTextFromReactNode(node.props.children);
19+
}
20+
return String(node || "");
21+
};
22+
623
const CodeBlock = ({ children, className }: { children: React.ReactNode[]; className: string }) => {
724
const [copied, setCopied] = useState(false);
8-
const codeContent = children[0] || "";
25+
26+
const getCodeContent = (): string => {
27+
if (!children || children.length === 0) return "";
28+
return extractTextFromReactNode(children[0]);
29+
};
930

1031
const handleCopy = async () => {
11-
if (typeof codeContent === "string") {
32+
const codeContent = getCodeContent();
33+
if (codeContent) {
1234
await navigator.clipboard.writeText(codeContent);
1335
setCopied(true);
1436
setTimeout(() => setCopied(false), 2000);
@@ -20,7 +42,13 @@ const CodeBlock = ({ children, className }: { children: React.ReactNode[]; class
2042
<pre className={className}>
2143
<code className={className}>{children}</code>
2244
</pre>
23-
<Button variant="link" onClick={handleCopy} className="absolute top-2 right-2 p-1.5 rounded-md opacity-0 group-hover:opacity-100 transition-opacity" aria-label="Copy to clipboard">
45+
<Button
46+
variant="link"
47+
onClick={handleCopy}
48+
className="absolute top-2 right-2 p-2.5 rounded-md opacity-0 group-hover:opacity-100 transition-opacity bg-background/80 hover:bg-background/90"
49+
aria-label="Copy to clipboard"
50+
title={copied ? "Copied!" : "Copy to clipboard"}
51+
>
2452
{copied ? <Check size={16} /> : <Copy size={16} />}
2553
</Button>
2654
</div>

0 commit comments

Comments
 (0)