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-buttonUsage
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.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | - | The string written to the clipboard on click. Required. |
timeout | number | 1500 | Milliseconds before the button resets from copied or error state back to idle. |
copyLabel | React.ReactNode | "Copy" | Label shown in the idle state. |
copiedLabel | React.ReactNode | "Copied" | Label shown after a successful copy. |
onCopy | (value: string) => void | - | Callback fired with the copied value on a successful write. |
className | string | - | 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
copiedLabelandcopyLabelacceptReact.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.