Skip to content

Commit b3bb235

Browse files
fix: handle clipboard error and add copy feedback in CodeBlock (#1670)
1 parent e76c241 commit b3bb235

File tree

1 file changed

+28
-8
lines changed

1 file changed

+28
-8
lines changed

frontend/src/components/layout/CodeBlock.tsx

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useState } from 'react'
12
import { EditorContent, useEditor } from '@tiptap/react'
23
import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight'
34
import { common, createLowlight } from 'lowlight'
@@ -27,6 +28,7 @@ type Props = {
2728
}
2829

2930
const CodeBlock = ({ code }: Props) => {
31+
const [copied, setCopied] = useState(false)
3032

3133
const editor = useEditor({
3234
editorProps: {
@@ -44,20 +46,38 @@ const CodeBlock = ({ code }: Props) => {
4446
content: `<pre><code>${code}</code></pre>`
4547
})
4648

47-
const onCopy = () => {
48-
navigator.clipboard.writeText(code)
49+
const onCopy = async () => {
50+
try {
51+
if (navigator?.clipboard?.writeText) {
52+
await navigator.clipboard.writeText(code)
53+
} else {
54+
const textarea = document.createElement('textarea')
55+
textarea.value = code
56+
textarea.setAttribute('readonly', '')
57+
textarea.style.position = 'absolute'
58+
textarea.style.left = '-9999px'
59+
document.body.appendChild(textarea)
60+
textarea.select()
61+
document.execCommand('copy')
62+
document.body.removeChild(textarea)
63+
}
64+
65+
setCopied(true)
66+
toast.success('Copied to clipboard', { duration: 800 })
67+
setTimeout(() => setCopied(false), 2500)
68+
} catch (err) {
69+
console.error('Copy failed:', err)
70+
toast.error('Failed to copy')
71+
}
72+
}
4973

50-
toast.success('Copied to clipboard', {
51-
duration: 800
52-
})
53-
}
5474

5575
if (!editor) return null
5676

5777
return (
5878
<div className='relative'>
5979
<EditorContent editor={editor} />
60-
<Tooltip content='Copy'>
80+
<Tooltip content={copied ? 'Copied' : 'Copy'}>
6181
<IconButton
6282
variant='ghost'
6383
size='2'
@@ -66,7 +86,7 @@ const CodeBlock = ({ code }: Props) => {
6686
className='absolute right-3 top-7 text-gray-8 hover:text-gray-1'
6787
onClick={onCopy}
6888
>
69-
<BiCopy />
89+
{copied ? <BiClipboard /> : <BiCopy />}
7090
</IconButton>
7191
</Tooltip>
7292
</div>

0 commit comments

Comments
 (0)