Skip to content

Commit

Permalink
feat: Add copy to clipboard button to code blocks (#104)
Browse files Browse the repository at this point in the history
Co-authored-by: Lachlan Collins <[email protected]>
  • Loading branch information
beerose and lachlancollins authored Jan 9, 2024
1 parent 4c8defa commit dec72dd
Showing 1 changed file with 24 additions and 2 deletions.
26 changes: 24 additions & 2 deletions app/components/CodeBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import type { FC, HTMLAttributes, ReactElement } from 'react'
import {
useState,
type FC,
type HTMLAttributes,
type ReactElement,
} from 'react'
import invariant from 'tiny-invariant'
import type { Language } from 'prism-react-renderer'
import { Highlight, Prism } from 'prism-react-renderer'
import { FaCopy } from 'react-icons/fa'
import { svelteHighlighter } from '~/utils/svelteHighlighter'
// Add back additional language support after `prism-react` upgrade
;(typeof global !== 'undefined' ? global : window).Prism = Prism
Expand All @@ -25,13 +31,29 @@ function isLanguageSupported(lang: string): lang is Language {

export const CodeBlock: FC<HTMLAttributes<HTMLPreElement>> = ({ children }) => {
invariant(!!children, 'children is required')
const [copied, setCopied] = useState(false)
const child = children as ReactElement
const className = child.props?.className || ''
const userLang = getLanguageFromClassName(className)
const lang = isLanguageSupported(userLang) ? userLang : 'bash'
const code = child.props.children || ''
return (
<div className="w-full max-w-full">
<div className="w-full max-w-full relative">
<button
className="absolute right-1 top-3 z-10 p-2 group flex items-center"
onClick={() => {
setCopied(true)
navigator.clipboard.writeText(code.trim())
setTimeout(() => setCopied(false), 2000)
}}
aria-label="Copy code to clipboard"
>
{copied ? (
<span className="text-xs">Copied!</span>
) : (
<FaCopy className="text-gray-500 group-hover:text-gray-100 dark:group-hover:text-gray-200 transition duration-200" />
)}
</button>
<Highlight code={code.trim()} language={lang}>
{({ className, tokens, getLineProps, getTokenProps }) => (
<div className="relative not-prose">
Expand Down

1 comment on commit dec72dd

@vercel
Copy link

@vercel vercel bot commented on dec72dd Jan 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.