Preview
Preparing...
Installation
shadcn/ui
shadcn/ui Command
pnpm dlx shadcn@latest add https://code-blocks.pheralb.dev/r/copy-button.jsonManual
- Create a utility function to handle clipboard copying:
.ts
export const copyToClipboard = async (text: string) => {
try {
await navigator.clipboard.writeText(text);
return true;
} catch (err) {
console.error("Failed to copy text: ", err);
return false;
}
};- Create a
src/components/code-block/copy-button.tsxfile and add the following code:
.tsx
"use client";
import { useEffect, useState, type ComponentProps } from "react";
import { cn } from "@/utils/cn";
import { copyToClipboard } from "@/utils/copy";
import { CheckIcon, CopyIcon } from "lucide-react";
interface CopyButtonProps extends ComponentProps<"button"> {
content: string;
iconSize?: number;
}
const CopyButton = ({ content, iconSize = 14, className, ...props }: CopyButtonProps) => {
const [isCopied, setIsCopied] = useState<boolean>(false);
useEffect(() => {
if (!isCopied) return;
const timeout = setTimeout(() => {
setIsCopied(false);
}, 2000);
return () => clearTimeout(timeout);
}, [isCopied]);
const handleCopy = async () => {
await copyToClipboard(content);
setIsCopied(true);
};
return (
<button
title="Copy to clipboard"
className={cn(
"cursor-pointer",
"transition-colors duration-200 ease-in-out",
"text-neutral-600 dark:text-neutral-400",
"hover:text-neutral-950 hover:dark:text-neutral-50",
className,
)}
onClick={handleCopy}
{...props}
>
{isCopied ? (
<CheckIcon
size={iconSize}
className="animate-in zoom-in-50 text-green-900 duration-200 dark:text-green-400"
/>
) : (
<CopyIcon
size={iconSize}
className="animate-in zoom-in-50 duration-200"
/>
)}
</button>
);
};
export { CopyButton };Usage
.tsx
import { CopyButton } from "@/components/code-block/copy-button";
const Example = () => {
return <CopyButton content="Text to be copied" />;
};
export default Example;Or with <CodeBlock> component:
.tsx
import {
CodeBlock,
CodeBlockHeader,
CodeBlockContent,
} from "@/components/code-block/code-block";
import { CopyButton } from "@/components/code-block/copy-button";
const Example = () => {
return (
<CodeBlock>
<CodeBlockHeader>
<CopyButton content={`console.log('Hello, World!');`} />
</CodeBlockHeader>
<CodeBlockContent>
{/* Your syntax highlighted code goes here. */}
</CodeBlockContent>
</CodeBlock>
);
};
export default Example;Props
React Props
| Prop | Type | Required | |
|---|---|---|---|
| content | string | Yes | |
| iconSize | number | No | |
| Included: DOMAttributes<HTMLDivElement> | |||