VUE

useCopyToClipboard Composable

Composable for copying text to clipboard with success/error states and fallback for older browsers

Vue3ComposablesClipboardUI

Code

import { ref, type Ref } from 'vue';

export function useCopyToClipboard() {
  const isCopied = ref(false);
  const error = ref<Error | null>(null);
  const copyTimeout: Ref<ReturnType<typeof setTimeout> | null> = ref(null);

  const copy = __TOKEN_28__ (text: string): Promise<boolean> => {
    try {
      // Clear previous state
      error.value = null;
      __TOKEN_30__ (copyTimeout.value) clearTimeout(copyTimeout.value);

      // Use Clipboard API if available
      __TOKEN_31__ (navigator.clipboard) {
        await navigator.clipboard.writeText(text);
      } else {
        // Fallback for older browsers
        const textArea = document.createElement('textarea');
        textArea.value = text;
        textArea.style.position = 'fixed';
        textArea.style.left = '-999999px';
        textArea.style.top = '-999999px';
        document.body.appendChild(textArea);
        textArea.focus();
        textArea.select();
        document.execCommand('copy');
        document.body.removeChild(textArea);
      }

      // Set copied state (auto-reset after 2s)
      isCopied.value = true;
      copyTimeout.value = setTimeout(() => {
        isCopied.value = false;
      }, 2000);

      return true;
    } __TOKEN_36__ (e) {
      error.value = e instanceof Error ? e : new Error('Failed to copy text');
      isCopied.value = false;
      return false;
    }
  };

  // Cleanup timeout on unmount
  const cleanup = () => {
    __TOKEN_41__ (copyTimeout.value) clearTimeout(copyTimeout.value);
  };

  return {
    isCopied,
    error,
    copy,
    cleanup
  };
}

// Usage example
// const { isCopied, error, copy } = useCopyToClipboard();
// const handleCopy = async () => {
//   const success = await copy('Hello World!');
//   if (success) console.log('Copied!');
// };