useCopyToClipboard

useCopyToClipboard provides an async copy function backed by the browser Clipboard API and returns the latest successfully copied text.

When to use

  • Copy commands, share links, and code snippets from UI actions.
  • Show optimistic/success/error feedback after copy attempts.
  • Reuse clipboard behavior consistently across components.

Return value

  • copiedText: the most recent text that was copied successfully, or null.
  • copy(text): returns { success, message, description? } with operation result details.

Example

const [copiedText, copy] = useCopyToClipboard();

const handleCopy = async () => {
  const result = await copy('npm install @branditdev/hooks');

  if (!result.success) {
    console.error(result.description ?? result.message);
  }
};

Usage

import { useState } from 'react';

import { useCopyToClipboard } from '@branditdev/hooks';

export function UseCopyToClipboardDemo() {
  const [text, setText] = useState('npm install @branditdev/hooks');
  const [copiedText, copy] = useCopyToClipboard();
  const [status, setStatus] = useState<string | null>(null);

  const handleCopy = async () => {
    const result = await copy(text);
    setStatus(
      result.success ? result.message : (result.description ?? result.message)
    );
  };

  return (
    <div>
      <label htmlFor='copy-input'>Text to copy</label>
      <input
        id='copy-input'
        value={text}
        onChange={event => setText(event.target.value)}
      />
      <button type='button' onClick={() => void handleCopy()}>
        Copy text
      </button>
      <p>Copied value: {copiedText ?? 'Nothing copied yet'}</p>
      {status ? <p>{status}</p> : null}
    </div>
  );
}

API

useCopyToClipboard(): [CopiedValue, CopyFn]

Defined in: browser/useCopyToClipboard/useCopyToClipboard.ts:24

Copies text to the system clipboard and stores the latest copied value.

Returns

[CopiedValue, CopyFn]

A tuple with the most recently copied text and an async copy function.

Source

import { useCallback, useState } from 'react';

export type CopiedValue = string | null;

export interface CopyFnReturnType {
  success: boolean;
  message: string;
  description?: string;
}

export type CopyFn = (text: string) => Promise<CopyFnReturnType>;

export function useCopyToClipboard(): [CopiedValue, CopyFn] {
  const [copiedText, setCopiedText] = useState<CopiedValue>(null);

  const copy: CopyFn = useCallback(async text => {
    if (!navigator?.clipboard) {
      setCopiedText(null);
      return {
        success: false,
        message: 'Clipboard not supported',
        description: 'Your browser does not support the Clipboard API.',
      };
    }

    try {
      await navigator.clipboard.writeText(text);
      setCopiedText(text);
      return { success: true, message: 'Copied to clipboard' };
    } catch (error) {
      setCopiedText(null);
      return {
        success: false,
        message: 'Copy failed',
        description:
          error instanceof Error
            ? error.message
            : 'Please try again or check your browser permissions.',
      };
    }
  }, []);

  return [copiedText, copy];
}