Full-Stack Development

React-Markdown - How To Create a Copy Code Button

In this tutorial, I'll show you how to create a code copy button to our React-Markdown code syntax block.

JS
Jay Simons
Author
React-Markdown - How To Create a Copy Code Button

Markdown is the markup language of choice for tech-savvy bloggers and publishing code samples is commonplace. When creating tutorials (such as this one), it's nice to have a quick way to copy a code block to the clipboard, instead of having to drag-select the code.

This tutorial will use two React libraries: react-markdown and react-syntax-highlighter.

We start with a component called postBody. This is responsible for rendering our markdown as HTML:

JS
import ReactMarkdown from 'react-markdown';
import rehypeRaw from 'rehype-raw';
import remarkGfm from 'remark-gfm';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
import { a11yDark } from 'react-syntax-highlighter/dist/cjs/styles/prism'
import CodeCopyBtn from './codeCopyBtn';

export default function PostBody({ content }) {
    // Add the CodeCopyBtn component to our PRE element
    const Pre = ({ children }) => <pre className="blog-pre">
        <CodeCopyBtn>{children}</CodeCopyBtn>
        {children}
    </pre>

    return (
        <ReactMarkdown
            className='post-markdown'
            linkTarget='_blank'
            rehypePlugins={[rehypeRaw]}
            remarkPlugins={[remarkGfm]}
            components={{
                pre: Pre,
                code({ node, inline, className = "blog-code", children, ...props }) {
                    const match = /language-(\w+)/.exec(className || '')
                    return !inline && match ? (
                        <SyntaxHighlighter
                            style={a11yDark}
                            language={match[1]}
                            PreTag="div"
                            {...props}
                        >
                            {String(children).replace(/\n$/, '')}
                        </SyntaxHighlighter>
                    ) : (
                        <code className={className} {...props}>
                            {children}
                        </code>
                    )
                }
            }}
        >
            {content}
        </ReactMarkdown>
    )
}

And then we'll create a component called codeCopyBtn:

JS
import React from "react";

export default function CodeCopyBtn({ children }) {
    const [copyOk, setCopyOk] = React.useState(false);

    const iconColor = copyOk ? '#0af20a' : '#ddd';
    const icon = copyOk ? 'fa-check-square' : 'fa-copy';

    const handleClick = (e) => {
        navigator.clipboard.writeText(children[0].props.children[0]);
        console.log(children)

        setCopyOk(true);
        setTimeout(() => {
            setCopyOk(false);
        }, 500);
    }

    return (
        <div className="code-copy-btn">
            <i className={`fas ${icon}`} onClick={handleClick} style={{color: iconColor}} />
        </div>
    )
}

And here's the CSS:

CSS
.blog-pre {
    margin-bottom: 3em !important;
    -webkit-box-shadow: -10px 0px 13px -7px #000000, 10px 0px 13px -7px #000000, 35px -23px 2px -16px rgba(0, 0, 0, 0);
    box-shadow: -10px 0px 13px -7px #000000, 10px 0px 13px -7px #000000, 35px -23px 2px -16px rgba(0, 0, 0, 0);
    position: relative;
}

.code-copy-btn {
    color: white;
    position: absolute;
    right: 10px;
    top: -2px;
    font-size: 1.5em;
    cursor: pointer;
    transition: all 0.3s ease-in-out;
}

.code-copy-btn:hover {
    transform: scale(1.1);
    opacity: 0.9;
}

I hope you found this tutorial useful. Happy coding!

For more greate information, please Visit our Blog.

Tags

Comments (1)

Join the discussion and share your thoughts on this post.

Ayush

Ayush

thanks for the code!
Ayush
Ayush
navigator.clipboard.writeText(children[0].props.children[0]); // write this instead. navigator.clipboard.writeText(children.props.children); //never mind a small mistake.
Ayush
Ayush
hello sir, earlier I was using markdown, now I am using HTMl code but am not able to create a copy button in it, please tell me -
mc
mc
The performance of the code is really bad if the messagee is dynamically generated for example from LLM completion if make browser hangs or crash.

© 2025 Jay Simons. All rights reserved.