Componentform0.86 KB gzipZero dependencies
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-buttonOr install the full npm package:
npm install bigbulluiUsage
Open in StackBlitzimport { CopyButton } from "@/components/ui/copy-button";
<CopyButton value="npm install bigbullui" />Usage guidance
Use Copy Button when a ticket stub surface needs Tactile button with clipboard feedback and check state. Keep props minimal and prefer composition with sibling stubs.
Avoid Copy Button for long form flows or dense data grids where a dedicated layout block fits better.
Source code
copy-button.tsxZero 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
| Prop | Type | Description |
|---|---|---|
| value | string | |
| timeout? | number | |
| className? | string |