CopyButton

CopyButton writes a string to the clipboard via the Clipboard API and cycles through three states: idle, copied, and error. Each state transition is animated, the icon swaps with a spring scale, and the label slides vertically. After a configurable timeout the button resets to idle automatically.

Preview

CopyButton

Click to copy

Variants

Custom labels

Override copyLabel and copiedLabel for different copy contexts.

Custom labels

Clone workflow

Long timeout

Set timeout to keep the copied state visible longer.

Long timeout

Stays green for 3 seconds

Short timeout

A snappy reset after a brief confirmation.

Short timeout

Resets in 800ms

Install

Add the item with the shadcn CLI.

npx shadcn@latest add @evilbuttons/copy-button

Usage

[]txt
import { CopyButton } from "@/components/evil-buttons/copy-button";

export function ButtonDemo() {
  return (
    <CopyButton
      value="npm install evil-buttons"
      onCopy={(v) => console.log("copied:", v)}
    />
  );
}

Props

The component spreads any <button> HTML attributes except value and onCopy.

PropTypeDefaultDescription
valuestring-The string written to the clipboard on click. Required.
timeoutnumber1500Milliseconds before the button resets from copied or error state back to idle.
copyLabelReact.ReactNode"Copy"Label shown in the idle state.
copiedLabelReact.ReactNode"Copied"Label shown after a successful copy.
onCopy(value: string) => void-Callback fired with the copied value on a successful write.
classNamestring-Extra classes passed to the button.

Notes

  • Uses navigator.clipboard.writeText. On browsers or contexts where the Clipboard API is unavailable, the button transitions to the error state instead of throwing.
  • Each click resets the auto-reset timer so rapid clicks do not stack timeouts.
  • The copiedLabel and copyLabel accept React.ReactNode, so you can pass icons or custom markup as labels.
  • aria-live="polite" announces state changes to screen readers.

Registry

The registry item includes components/evil-buttons/copy-button.tsx and installs clsx, tailwind-merge, and motion as dependencies.