GitHub
Open Github

UseCopy

Copy text to the clipboard with visual feedback.

Installation

pnpm add @hookraft/use-copy

useCopy

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

PropTypeDefault
duration
number
200
stagger
number
5
resetDelay
number
1500

Returns

PropTypeDefault
textRef
React.RefObject<HTMLElement | null>
-
iconRef
React.RefObject<HTMLButtonElement | null>
-
copied
boolean
-
trigger
() => void
-

Notes

  • Character spans are appended directly to document.body on click and removed when the animation finishes — no wrappers or portals needed
  • The original text element's opacity is set to 0 during 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