React Copy Button
React copy button with one-click clipboard copying and visual feedback. Smooth animations and state management with TypeScript and shadcn/ui styling.
Building clipboard interactions?
Join our Discord community for help from other developers.
Every code snippet, every share link, every API key needs a copy button. Users expect them everywhere. But most implementations are terrible—no feedback, laggy animations, or worse, that ancient "Copied!" tooltip that never goes away. This React component gives you instant visual feedback with smooth icon transitions that users actually notice.
Instant clipboard copying
Click to copy with satisfying visual feedback that confirms the action:
Built for React applications with TypeScript and Next.js. Uses native Clipboard API with proper fallbacks. The icon animation runs on the GPU using Framer Motion, keeping interactions smooth even during heavy JavaScript operations. Works seamlessly with shadcn/ui design systems.
Installation
npx shadcn@latest add https://www.shadcn.io/registry/copy-button.json
npx shadcn@latest add https://www.shadcn.io/registry/copy-button.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/copy-button.json
bunx shadcn@latest add https://www.shadcn.io/registry/copy-button.json
Usage
import { CopyButton } from "@/components/ui/copy-button";
export default function ShareLink() {
const shareUrl = "https://example.com/shared-content";
return (
<div className="flex items-center gap-2">
<input
value={shareUrl}
readOnly
className="flex-1 px-3 py-2 border rounded-md"
/>
<CopyButton
content={shareUrl}
onCopy={() => console.log("Link copied!")}
/>
</div>
);
}
Why most copy buttons suck
Users click copy buttons and nothing happens. Or they get a tiny checkmark they miss. Or that annoying tooltip that blocks content. Most developers just slap navigator.clipboard.writeText
on a button and call it done.
The problem isn't the clipboard API—it's the feedback. Users need immediate, obvious confirmation. This React component morphs the icon from copy to check with a smooth scale animation. The state auto-resets after 3 seconds (configurable). No tooltips blocking content, no guessing if it worked.
Plus, it handles the edge cases: clipboard API failures, permission denials, old browsers. Your users get consistent behavior across all scenarios.
Examples
Button Variants
Different styles for different contexts—ghost for minimal UI, outline for forms:
Size Options
Scale appropriately for dense interfaces or touch targets:
Features
- Smooth icon morphing with Framer Motion spring animations that feel responsive
- Auto-resetting state with configurable delay for continuous copying workflows
- Six visual variants matching shadcn/ui design patterns (default, ghost, outline, secondary, muted, destructive)
- Four size presets optimized for different interface densities and touch targets
- TypeScript definitions with complete prop types and variant exports
- Controlled and uncontrolled modes for integration with form libraries or state management
- Clipboard API with fallbacks handling permissions and browser compatibility
- Accessible button semantics with proper ARIA attributes and keyboard support
API Reference
CopyButton
The main component for clipboard copying with visual feedback.
Prop | Type | Default | Description |
---|---|---|---|
content | string | - | Text content to copy to clipboard |
variant | "default" | "ghost" | "outline" | "secondary" | "muted" | "destructive" | "default" | Visual style variant matching shadcn/ui patterns |
size | "sm" | "default" | "md" | "lg" | "default" | Button and icon sizing preset |
delay | number | 3000 | Milliseconds before resetting to copy state |
onCopy | (content: string) => void | - | Callback fired when content is successfully copied |
isCopied | boolean | - | Controlled copy state for external management |
onCopyChange | (isCopied: boolean) => void | - | Callback for controlled state changes |
className | string | - | Additional CSS classes for customization |
...props | ButtonHTMLAttributes | - | All native button props are supported |
Size Specifications
Each size is optimized for specific use cases:
Size | Button | Icon | Use Case |
---|---|---|---|
sm | 24×24px | 12×12px | Dense interfaces, inline with text |
default | 32×32px | 16×16px | Standard UI, forms, toolbars |
md | 40×40px | 20×20px | Touch-friendly, mobile interfaces |
lg | 48×48px | 24×24px | Hero sections, prominent actions |
Common gotchas
Clipboard permissions: The Clipboard API requires HTTPS in production. It works on localhost for development but will fail silently on HTTP sites. Always test in production environment.
Mobile Safari quirks: On iOS, clipboard access might require user interaction. The component handles this, but avoid triggering copies programmatically without user action.
State reset timing: The default 3-second reset works for most cases. For rapid copying scenarios (like in data tables), reduce to 1500ms. For critical confirmations, increase to 5000ms.
Icon sizing with custom classes: If you override sizes with Tailwind classes, the icon might not scale properly. Use the size prop instead of custom width/height classes.
Async content generation: If your content comes from an async source, generate it before passing to the component. The copy happens synchronously for security reasons.
You might also like
Explore other interactive button components for React applications:
Ripple Button
Material Design-inspired ripple effects on click
Liquid Button
Fluid fill animations for engaging interactions
Flip Button
3D flip animations for state transitions
Icon Button
Icon-focused interactions with proper accessibility
Questions developers actually ask
React Animated Modal Button
React animated modal button with 3D perspective and backdrop blur. Framer Motion creates smooth modal transitions with TypeScript and shadcn/ui styling.
React Corner Accent Button
React button with animated corner accents and sliding background effect. Features expanding corners and smooth transitions with TypeScript and shadcn/ui.