Hooks/Utilities/useClipboardCopyNew

useClipboardCopy

A custom React hook that provides clipboard copy functionality with state management and error handling.

useClipboardCopy is a custom React hook that provides an easy way to copy text to the clipboard with automatic state management. It tracks the copied state, handles errors gracefully, and automatically resets the state after a configurable timeout. The hook uses the modern Clipboard API under the hood for reliable functionality.

Example

Loading...

Install

npx shadcn@latest add https://unlogg.com/r/use-clipboard-copy.json
pnpm dlx shadcn@latest add https://unlogg.com/r/use-clipboard-copy.json
bunx shadcn@latest add https://unlogg.com/r/use-clipboard-copy.json

Notes

  • Uses the modern Clipboard API (navigator.clipboard.writeText)
  • Automatically tracks copied state with configurable timeout
  • Provides comprehensive error handling for clipboard failures
  • Includes success and error callbacks for custom behavior
  • Supports manual state reset functionality
  • Works with any text content including code, URLs, and emojis

API Reference

Parameters

PropTypeDefault
options?
UseClipboardCopyOptions
{}

UseClipboardCopyOptions

PropTypeDefault
onError?
(error: Error) => void
undefined
onSuccess?
(text: string) => void
undefined
timeout?
number
2000

Returns

PropTypeDefault
reset?
() => void
-
error?
Error | null
-
copy?
(text: string) => Promise<void>
-
copied?
boolean
-

Usage

import { useClipboardCopy } from "@/hooks/use-clipboard-copy";

function CopyButton() {
  const { copy, copied, error } = useClipboardCopy({
    timeout: 2000,
    onSuccess: (text) => console.log('Copied:', text),
    onError: (err) => console.error('Copy failed:', err)
  });

  const handleCopy = () => {
    copy('Hello, World!');
  };

  return (
    <button onClick={handleCopy}>
      {copied ? 'Copied!' : 'Copy'}
      {error && <span>Failed to copy</span>}
    </button>
  );
}

Advanced Usage

Code Block with Copy Button

Create a reusable code block component with copy functionality:

function CodeBlock({ code, language }: { code: string; language: string }) {
  const { copy, copied } = useClipboardCopy({ timeout: 3000 });

  return (
    <div className="relative">
      <pre className={`language-${language}`}>
        <code>{code}</code>
      </pre>
      <button
        onClick={() => copy(code)}
        className="absolute top-2 right-2"
      >
        {copied ? '✓ Copied!' : 'Copy Code'}
      </button>
    </div>
  );
}

URL Sharing Component

Combine with other hooks for URL sharing functionality:

function ShareURL() {
  const { copy, copied, error } = useClipboardCopy({
    timeout: 1500,
    onSuccess: () => toast.success('URL copied to clipboard!'),
    onError: () => toast.error('Failed to copy URL')
  });
  
  const currentURL = window.location.href;

  return (
    <div className="flex gap-2">
      <input value={currentURL} readOnly className="flex-1" />
      <button onClick={() => copy(currentURL)}>
        {copied ? '✓ Copied' : 'Share URL'}
      </button>
      {error && <span className="text-red-500">Error: {error.message}</span>}
    </div>
  );
}

Multi-Text Copy Manager

Handle multiple copyable items with individual state tracking:

function ContactCard({ contact }: { contact: Contact }) {
  const emailCopy = useClipboardCopy({ timeout: 2000 });
  const phoneCopy = useClipboardCopy({ timeout: 2000 });
  const addressCopy = useClipboardCopy({ timeout: 2000 });

  return (
    <div className="space-y-2">
      <div className="flex justify-between">
        <span>Email: {contact.email}</span>
        <button onClick={() => emailCopy.copy(contact.email)}>
          {emailCopy.copied ? '✓' : 'Copy'}
        </button>
      </div>
      <div className="flex justify-between">
        <span>Phone: {contact.phone}</span>
        <button onClick={() => phoneCopy.copy(contact.phone)}>
          {phoneCopy.copied ? '✓' : 'Copy'}
        </button>
      </div>
      <div className="flex justify-between">
        <span>Address: {contact.address}</span>
        <button onClick={() => addressCopy.copy(contact.address)}>
          {addressCopy.copied ? '✓' : 'Copy'}
        </button>
      </div>
    </div>
  );
}

Error Handling and Fallbacks

Implement graceful fallbacks for unsupported browsers:

function RobustCopyButton({ text }: { text: string }) {
  const { copy, copied, error, reset } = useClipboardCopy({
    timeout: 3000,
    onError: (err) => {
      console.error('Clipboard copy failed:', err);
      // Implement fallback logic
      fallbackCopyToClipboard(text);
    }
  });

  const fallbackCopyToClipboard = (text: string) => {
    const textArea = document.createElement('textarea');
    textArea.value = text;
    document.body.appendChild(textArea);
    textArea.focus();
    textArea.select();
    try {
      document.execCommand('copy');
    } catch (err) {
      console.error('Fallback copy failed:', err);
    }
    document.body.removeChild(textArea);
  };

  return (
    <div>
      <button onClick={() => copy(text)}>
        {copied ? '✓ Copied!' : 'Copy Text'}
      </button>
      {error && (
        <div className="text-red-500 text-sm">
          Copy failed. Please try selecting and copying manually.
          <button onClick={reset} className="underline ml-2">
            Dismiss
          </button>
        </div>
      )}
    </div>
  );
}

Use Cases

  • Code Documentation: Add copy buttons to code examples and snippets
  • URL Sharing: Allow users to easily copy and share URLs
  • Contact Information: Enable copying of email addresses, phone numbers, and addresses
  • API Keys & Tokens: Provide secure copying of sensitive information
  • Social Sharing: Copy pre-formatted social media content
  • Form Data: Allow copying of generated content like passwords or IDs
  • Error Messages: Enable copying of error details for support requests
  • Configuration Values: Copy configuration snippets and settings