Hazine

Copy Button

A button that copies text to the clipboard with animated check feedback.

npx shadcn@latest add @hazine/copy-button

Installation

npx shadcn@latest add @hazine/copy-button

Source

"use client"

import * as React from "react"
import { CheckIcon, CopyIcon } from "lucide-react"

import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"

interface CopyButtonProps extends React.ComponentProps<typeof Button> {
  value: string
  timeout?: number
}

export function CopyButton({
  value,
  timeout = 2000,
  className,
  children,
  ...props
}: CopyButtonProps) {
  const [copied, setCopied] = React.useState(false)
  const timer = React.useRef<ReturnType<typeof setTimeout>>(undefined)

  React.useEffect(() => () => clearTimeout(timer.current), [])

  async function copy() {
    await navigator.clipboard.writeText(value)
    setCopied(true)
    clearTimeout(timer.current)
    timer.current = setTimeout(() => setCopied(false), timeout)
  }

  return (
    <Button
      variant="ghost"
      size={children ? "sm" : "icon-sm"}
      aria-label={copied ? "Copied" : "Copy to clipboard"}
      className={cn("shrink-0", className)}
      onClick={copy}
      {...props}
    >
      {copied ? (
        <CheckIcon className="text-emerald-500" />
      ) : (
        <CopyIcon />
      )}
      {children}
    </Button>
  )
}

Dependencies