Skip to content

Commit fc25948

Browse files
committed
Add copy code button
1 parent 0358b41 commit fc25948

File tree

4 files changed

+52
-4
lines changed

4 files changed

+52
-4
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
"react-hot-toast": "^2.4.0",
6969
"react-icons": "^4.8.0",
7070
"react-markdown": "^8.0.5",
71+
"react-node-to-string": "^0.1.1",
7172
"react-scroll-to-bottom": "^4.2.0",
7273
"react-spinners": "^0.13.8",
7374
"react-textarea-autosize": "^8.4.0",

src/app/components/Markdown/index.tsx

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,46 @@
11
/* eslint-disable react/prop-types */
2+
import reactNodeToString from 'react-node-to-string'
3+
import cx from 'classnames'
24
import 'github-markdown-css/github-markdown-light.css'
35
import 'highlight.js/styles/github.css'
4-
import { FC } from 'react'
6+
import { FC, ReactNode, useEffect, useMemo, useState } from 'react'
7+
import { CopyToClipboard } from 'react-copy-to-clipboard'
8+
import { BsClipboard } from 'react-icons/bs'
9+
import { FiClipboard } from 'react-icons/fi'
10+
import { BiClipboard } from 'react-icons/bi'
511
import ReactMarkdown from 'react-markdown'
612
import rehypeHighlight from 'rehype-highlight'
713
import remarkGfm from 'remark-gfm'
814
import supersub from 'remark-supersub'
915
import Tooltip from '../Tooltip'
1016
import './markdown.css'
1117

18+
function CustomCode(props: { children: ReactNode; className?: string }) {
19+
const [copied, setCopied] = useState(false)
20+
21+
const code = useMemo(() => reactNodeToString(props.children), [props.children])
22+
23+
useEffect(() => {
24+
if (copied) {
25+
setTimeout(() => setCopied(false), 1000)
26+
}
27+
}, [copied])
28+
29+
return (
30+
<div className="flex flex-col">
31+
<div className="bg-[#e6e7e8] text-xs p-2">
32+
<CopyToClipboard text={code} onCopy={() => setCopied(true)}>
33+
<div className="flex flex-row items-center gap-2 cursor-pointer w-fit ml-1">
34+
<BsClipboard />
35+
<span>{copied ? 'copied' : 'copy code'}</span>
36+
</div>
37+
</CopyToClipboard>
38+
</div>
39+
<code className={cx(props.className, 'px-4')}>{props.children}</code>
40+
</div>
41+
)
42+
}
43+
1244
const Markdown: FC<{ children: string }> = ({ children }) => {
1345
return (
1446
<ReactMarkdown
@@ -27,6 +59,17 @@ const Markdown: FC<{ children: string }> = ({ children }) => {
2759
</Tooltip>
2860
)
2961
},
62+
code: ({ node, inline, className, children, ...props }) => {
63+
if (inline) {
64+
return (
65+
<code className={className} {...props}>
66+
{children}
67+
</code>
68+
)
69+
}
70+
console.log(node, props)
71+
return <CustomCode className={className}>{children}</CustomCode>
72+
},
3073
}}
3174
>
3275
{children}

src/app/components/Markdown/markdown.css

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@
1515
margin-bottom: 5px;
1616
}
1717
> pre {
18-
margin-bottom: 5px;
19-
}
20-
> pre code.hljs {
2118
padding: 0;
19+
margin-top: 10px;
20+
margin-bottom: 10px;
2221
}
2322
> pre code {
2423
white-space: pre-wrap;

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4656,6 +4656,11 @@ react-markdown@^8.0.5:
46564656
unist-util-visit "^4.0.0"
46574657
vfile "^5.0.0"
46584658

4659+
react-node-to-string@^0.1.1:
4660+
version "0.1.1"
4661+
resolved "https://registry.yarnpkg.com/react-node-to-string/-/react-node-to-string-0.1.1.tgz#857a5e223ef2ea75d5d10e72d3c6b0d9a31000ab"
4662+
integrity sha512-BufjWy2h2dOFcQp1IY/iXgdJzVbhAX6rM4/aNcmyp2VgMpUCU0py/t3MHRBLPxMULB6dCQeNebM+s6iI/46Xqw==
4663+
46594664
react-refresh@^0.13.0:
46604665
version "0.13.0"
46614666
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.13.0.tgz#cbd01a4482a177a5da8d44c9755ebb1f26d5a1c1"

0 commit comments

Comments
 (0)