Installation
pnpm add @hookraft/use-copyuseCopy
Animate text characters flying toward the copy icon when the user clicks it. Each character launches from its original screen position and swoops into the button with a scale-to-zero effect — giving a satisfying "sucked in" feel before the clipboard write completes.
Works on any element with text content: code blocks, install commands, wallet addresses, invite links, or any copyable string.
import { useCopy } from "@hookraft/use-copy"const { textRef, iconRef, copied, trigger } = useCopy()Full Example
"use client"
import { useRef } from "react"
import { useCopy } from "@hookraft/use-copy"
function CopyCommand() {
const { textRef, iconRef, copied, trigger } = useCopy()
return (
<div className="flex items-center gap-2 rounded-lg border px-4 py-3 font-mono text-sm">
<code ref={textRef}>npm install @hookraft/use-copy</code>
<button ref={iconRef} onClick={trigger} aria-label="Copy">
{copied ? <CheckIcon /> : <CopyIcon />}
</button>
</div>
)
}You can also tune the animation timing to match your UI's feel:
const { textRef, iconRef, copied, trigger } = useCopy({
duration: 200,
stagger: 5,
resetDelay: 1500,
})Options
| Prop | Type | Default |
|---|---|---|
duration | number | 200 |
stagger | number | 5 |
resetDelay | number | 1500 |
Returns
| Prop | Type | Default |
|---|---|---|
textRef | React.RefObject<HTMLElement | null> | - |
iconRef | React.RefObject<HTMLButtonElement | null> | - |
copied | boolean | - |
trigger | () => void | - |
Notes
- Character spans are appended directly to
document.bodyon click and removed when the animation finishes — no wrappers or portals needed - The original text element's opacity is set to
0during the animation and restored immediately after, so layout is never affected - Uses the Web Animations API under the hood — no animation library required
- If the user clicks again while an animation is running, the second click is silently ignored until the first animation completes
- The clipboard write happens immediately on click, before the animation starts — so slow connections or animation jank never block the copy
- Works in Next.js App Router — add
"use client"to the component that calls the hook