Copy button
Copy a value with immediate confirmation.
actionutility
Preview
Copy button preview
Live · keyboard ready
When to use
- Next to API keys, install commands, links, or code snippets.
- Icon-only copy controls in dense rows, with an accessible label.
- Any copy action that should confirm Copied or Could not copy in place.
When not to use
- Use split-button when copying has alternatives, such as Copy link and Copy as Markdown.
- Use code-block for full code samples, which include their own copy control.
shadcn CLI
Also installs (1)
- manicat-foundation
Manual install(+)
registry.jsonjson
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "copy-button",
"type": "registry:ui",
"title": "Copy button",
"description": "Copy a value with immediate confirmation.",
"categories": [
"actions"
],
"dependencies": [
"lucide-react",
"motion"
],
"registryDependencies": [
"https://manicat.viraza.net/r/manicat-foundation.json"
],
"files": [
{
"path": "registry/components/copy-button/copy-button.tsx",
"type": "registry:component",
"target": "@components/manicat/copy-button/copy-button.tsx"
},
{
"path": "registry/components/copy-button/copy-button.module.css",
"type": "registry:component",
"target": "@components/manicat/copy-button/copy-button.module.css"
},
{
"path": "lib/use-copy-feedback.ts",
"type": "registry:lib",
"target": "@components/manicat/lib/use-copy-feedback.ts"
}
],
"docs": "Docs and live preview: https://uiarc.dev/components/copy-button",
"meta": {
"tier": "free",
"kind": "component",
"docs": "https://manicat.viraza.net/components/copy-button",
"markdown": "https://uiarc.dev/components/copy-button/markdown",
"tags": [
"action",
"utility"
]
}
}Usage
Install the component, then copy this into your app. Change the content and the props to fit your screen.
example.tsxtsx
"use client";
import { CopyButton } from "@/components/manicat/copy-button/copy-button";
export function CopyButtonExample() {
return <CopyButton value="npx shadcn@latest add https://manicat.dev/r/button.json" label="Copy install command" />;
}
Examples
Real screens rather than isolated props. Switch to Code to copy a whole example into your project.
Copy install command A copy button next to the command it copies.
Copy install command
A copy button next to the command it copies. preview
Live · keyboard ready
npx shadcn@latest add https://manicat.dev/r/button.jsoncopy-install-command-a-copy-button-next-to-the-command-it-copies-.tsxtsx
Keyboard interactions
| Keys | Action |
|---|---|
| Enter / Space | Copies the value. |
Accessibility
- Native button named by label, including when iconOnly.
- A polite role="status" region announces "<label>: Copied" or "<label>: Could not copy".
- The label cell reserves the widest of its three states, so the layout never shifts.
Motion
- Icons trade places through a blur on a slow, nearly critically damped spring, and the check draws its stroke in.
- Only the changed letters of the label move; the same motion plays in reverse on reset.
- Reduced motion swaps icon and text with an instant fade and skips the stroke draw.
Responsive behavior
- The label reserves the width of its widest state, so the button never shifts its neighbours when it changes.
- It sizes to max-content with max-width 100%, so it stays compact in narrow rows.
Performance
- Only changed letters animate; the icon swap and stroke draw are a single short spring per copy.
- Clipboard access is async and needs a secure context; failures show the Failed state rather than throwing.
Notes for AI
- Use next to any copyable value: API keys, install commands, links, code. For a copy action that also has alternatives use split-button.
- Named export only; there is no default export.
- Clipboard state and reset timing come from lib/use-copy-feedback, so copy that file along with the component.