bigbullui logobigbullui
Componentform

Copy Button

Tactile button with clipboard feedback and check state.

Preview

Live Preview
npm install bigbullui

Installation

Tokens guide →

Add to your project via CLI (zero dependencies, code you own):

npx bigbullui add copy-button

Or install the full npm package:

npm install bigbullui

Usage

import { CopyButton } from "@/components/ui/copy-button";

<CopyButton value="npm install bigbullui" />

Source code

copy-button.tsx

Zero dependencies (only React + utils). Copy and paste directly into your project:

"use client";

import * as React from "react";
import { cn } from "./lib/utils";

export interface CopyButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  value: string;
  timeout?: number;
  className?: string;
}

export function CopyButton({
  value,
  timeout = 2000,
  className,
  ...props
}: CopyButtonProps) {
  const [copied, setCopied] = React.useState(false);

  const handleCopy = async () => {
    try {
      await navigator.clipboard.writeText(value);
      setCopied(true);
      setTimeout(() => setCopied(false), timeout);
    } catch {
      // fallback
    }
  };

  return (
    <button
      type="button"
      onClick={handleCopy}
      aria-label={copied ? "Copied" : "Copy to clipboard"}
      className={cn(
        "inline-flex cursor-pointer items-center gap-1.5 rounded-sm border border-dashed border-border bg-secondary px-2 py-1 font-mono text-[11px] font-medium text-secondary-foreground transition-all duration-150 active:scale-95",
        "hover:border-foreground/50 hover:bg-card focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
        copied && "border-accent text-accent",
        className
      )}
      {...props}
    >
      {copied ? (
        <>
          <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
            <polyline points="20 6 9 17 4 12" />
          </svg>
          <span>COPIED</span>
        </>
      ) : (
        <>
          <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
            <rect width="14" height="14" x="8" y="8" rx="2" ry="2" />
            <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" />
          </svg>
          <span>COPY</span>
        </>
      )}
    </button>
  );
}

Props

PropTypeDescription
valuestringText string to copy (required).
timeoutnumberDuration in ms to show check state (default 2000).