The CopyButton component provides a button interface for copying text to the clipboard. It's commonly used for code snippets, URLs, and any text content that users need to copy quickly.
import { CopyButton } from '@dashflowx/core'export default function CopyButtonExample() {return (<CopyButtonvalue="Hello, World!"/>)}
Preview:
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | 'Copy this text' | The text to copy to the clipboard |
className | string | '' | Additional CSS classes for the button |
src | string | - | Optional source reference |
<CopyButtonvalue="Hello, World!"/>
Preview:
<CopyButtonvalue="npm install @dashflowx/core"/>
Preview:
<CopyButtonvalue="https://dashflowx.com"/>
Preview:
<CopyButtonvalue="Custom styled copy button"className="border-2 border-blue-500 rounded-xl"/>
Preview:
<CopyButtonvalue="This is a very long text that demonstrates how the copy button handles longer content. It should still work perfectly and copy the entire text to the clipboard."/>
Preview:
const codeSnippet = `import { Button } from '@dashflowx/core'export default function MyComponent() {return (<Button variant="primary">Click me</Button>)}`;<div className="relative"><pre className="bg-gray-100 p-4 rounded-lg overflow-x-auto"><code>{codeSnippet}</code></pre><div className="absolute top-2 right-2"><CopyButton value={codeSnippet} /></div></div>
const apiEndpoints = ['GET /api/users','POST /api/users','PUT /api/users/:id','DELETE /api/users/:id'];<div className="space-y-2">{apiEndpoints.map((endpoint, index) => (<div key={index} className="flex items-center justify-between p-3 border rounded-lg"><code className="text-sm font-mono">{endpoint}</code><CopyButton value={endpoint} /></div>))}</div>
const configExamples = [{name: 'Environment Variables',value: 'NODE_ENV=production\nAPI_URL=https://api.example.com\nDATABASE_URL=postgresql://...'},{name: 'Package.json Scripts',value: '{\n "scripts": {\n "dev": "next dev",\n "build": "next build",\n "start": "next start"\n }\n}'},{name: 'Docker Compose',value: 'version: "3.8"\nservices:\n app:\n build: .\n ports:\n - "3000:3000"'}];<div className="space-y-4">{configExamples.map((config, index) => (<div key={index} className="border rounded-lg p-4"><div className="flex items-center justify-between mb-2"><h3 className="font-semibold">{config.name}</h3><CopyButton value={config.value} /></div><pre className="bg-gray-100 p-3 rounded text-sm overflow-x-auto"><code>{config.value}</code></pre></div>))}</div>
const commands = ['git clone https://github.com/user/repo.git','cd repo','npm install','npm run dev','npm run build','npm run test'];<div className="space-y-2"><h3 className="font-semibold mb-4">Setup Commands</h3>{commands.map((command, index) => (<div key={index} className="flex items-center justify-between p-3 bg-gray-50 rounded-lg"><code className="text-sm font-mono">{command}</code><CopyButton value={command} /></div>))}</div>
const packageCommands = {npm: 'npm install @dashflowx/core',yarn: 'yarn add @dashflowx/core',pnpm: 'pnpm add @dashflowx/core',bun: 'bun add @dashflowx/core'};<div className="space-y-2"><h3 className="font-semibold mb-4">Installation Commands</h3>{Object.entries(packageCommands).map(([manager, command]) => (<div key={manager} className="flex items-center justify-between p-3 border rounded-lg"><div className="flex items-center space-x-3"><span className="font-semibold text-sm">{manager}</span><code className="text-sm font-mono">{command}</code></div><CopyButton value={command} /></div>))}</div>
Use clear and descriptive text for copy buttons.
// ✅ Good - Clear copy target<CopyButton value="npm install @dashflowx/core" />// ❌ Avoid - Unclear copy target<CopyButton value="install" />
Use appropriate button sizes for different contexts.
// ✅ Good - Appropriate sizing<div className="flex items-center space-x-2"><code>npm install package</code><CopyButton value="npm install package" className="h-6 w-6" /></div>
Provide visual feedback when copying is successful.
// ✅ Good - Visual feedbackconst [copied, setCopied] = useState(false);<CopyButtonvalue={text}onClick={() => {copyToClipboard(text);setCopied(true);setTimeout(() => setCopied(false), 2000);}}/>
Ensure copy buttons are accessible to all users.
// ✅ Good - Accessible<CopyButtonvalue={text}aria-label={`Copy ${text}`}title={`Copy: ${text}`}/>
Handle copy failures gracefully.
// ✅ Good - Error handlingconst handleCopy = async (text: string) => {try {await navigator.clipboard.writeText(text);setCopied(true);} catch (error) {console.error('Failed to copy:', error);// Fallback or user notification}};
You can customize the copy button appearance using CSS classes:
<CopyButtonvalue="Custom styled"className="border-2 border-purple-500 rounded-xl bg-purple-50 hover:bg-purple-100"/>
Use different themes for different contexts:
// Light theme<CopyButtonvalue="Light theme"className="bg-white border-gray-200 hover:bg-gray-50"/>// Dark theme<CopyButtonvalue="Dark theme"className="bg-gray-900 border-gray-700 text-white hover:bg-gray-800"/>
Use different sizes for different emphasis levels:
// Small copy button<CopyButtonvalue="Small"className="h-6 w-6 text-xs"/>// Large copy button<CopyButtonvalue="Large"className="h-12 w-12 text-lg"/>
const [toast, setToast] = useState('');const handleCopy = async (text: string) => {try {await navigator.clipboard.writeText(text);setToast('Copied to clipboard!');setTimeout(() => setToast(''), 3000);} catch (error) {setToast('Failed to copy');setTimeout(() => setToast(''), 3000);}};return (<div><CopyButton value={text} onClick={() => handleCopy(text)} />{toast && (<div className="fixed top-4 right-4 bg-green-500 text-white px-4 py-2 rounded">{toast}</div>)}</div>);
const handleCopy = async (text: string, context: string) => {try {await navigator.clipboard.writeText(text);// Track copy eventanalytics.track('copy_button_clicked', {context,text_length: text.length,timestamp: new Date().toISOString()});} catch (error) {console.error('Copy failed:', error);}};
const copyWithFallback = async (text: string) => {try {// Try modern clipboard APIawait navigator.clipboard.writeText(text);} catch (error) {try {// Fallback to legacy methodconst textArea = document.createElement('textarea');textArea.value = text;document.body.appendChild(textArea);textArea.select();document.execCommand('copy');document.body.removeChild(textArea);} catch (fallbackError) {console.error('Copy failed:', fallbackError);// Show user notification}}};
const copyFormatted = async (text: string, format: 'plain' | 'markdown' | 'html') => {let formattedText = text;switch (format) {case 'markdown':formattedText = `\`\`\`\n${text}\n\`\`\``;break;case 'html':formattedText = `<pre><code>${text}</code></pre>`;break;default:formattedText = text;}await navigator.clipboard.writeText(formattedText);};
- Button: For general button functionality
- Toast: For copy notifications
- Tooltip: For copy button tooltips
- Code: For code display
- Input: For text input
For the complete API reference and advanced usage patterns, see the CopyButton API documentation.
