Copy button
Copy a value with immediate confirmation.
$ pnpm dlx shadcn@4.23.0 add @xzero-ui/copy-button- Type: Component (actions)
- Access: Free, open source
- Page: https://ui.xzero.co.uk/components/copy-button
- Markdown: https://ui.xzero.co.uk/components/copy-button/markdown
- Registry item: https://mcp.xzero.co.uk/r/copy-button.json
- Source file:
registry/components/copy-button/copy-button.tsx - Dependencies: motion, lucide-react
- Keywords: action, utility, react copy button, copy to clipboard, copy button animation, clipboard button, copy code button, copied feedback
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.
Installation
Register both Xzero UI namespaces in your project's components.json:
{
"registries": {
"@xzero-ui": "https://mcp.xzero.co.uk/r/{name}.json",
"@xzero-ui-pro": "https://mcp.xzero.co.uk/r/pro/{name}.json"
}
}
npx shadcn@4.23.0 add @xzero-ui/copy-button
Install xzero-foundation once, and import @/components/xzero/foundation.css in your app root. No Xzero token is used by this snapshot. For sample portraits, photos, fonts, or logos, download https://mcp.xzero.co.uk/install-assets.mjs and run node xzero-install-assets.mjs <receiving-project>.
Usage
import { CopyButton } from "@/components/xzero/copy-button/copy-button";
export function ApiKeyRow({ apiKey }: { apiKey: string }) {
return (
<div className="row">
<code>{apiKey}</code>
<CopyButton value={apiKey} label="Copy key" iconOnly />
</div>
);
}
API reference
CopyButton
Copies a string to the clipboard and crossfades its icon and label to Copied or Failed.
| Prop | Type | Default | Description |
|---|---|---|---|
value (required) | string | – | The text to copy. |
label | string | "Copy" | Idle label and accessible name. |
iconOnly | boolean | false | Hides the text and shows only the icon. |
variant | "outline" | "plain" | "outline" | Bordered or borderless. |
disabled | boolean | – | Disables the button. |
onCopied | () => void | – | Called after a successful copy. |
className | string | – | Extra class on the button. |
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
- The old icon and word fade out in about 100ms while the new ones fade in over about 160ms, with no blur; the check draws its stroke in.
- The label changes as one word, never letter by letter, and the same crossfade plays when it resets.
- 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
- Each copy is one short crossfade of the icon and the word (about 160ms) plus a quick stroke draw on the check; nothing animates per letter.
- 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.
Related
- Button: A clear, responsive action with quiet secondary states.
- Code block: Present code with legible hierarchy and copy access.
- Split button: A primary action with a menu of nearby alternatives.
- Action button: A compact button for frequent toolbar actions.
Also in buttons
- Button group: Related actions joined into one surface with hairline dividers: a hover highlight glides between segments, the pressed one answers in place, and an attached menu can close the row.
- Floating button group: Separate soft buttons in a quiet tray, with one shared highlight that morphs from button to button as you move, and a pressed state that settles in place.
- Expanding button group: Icon buttons in a compact group: the one you point at or focus grows to reveal its label while its neighbours slide aside, and an action confirms in place.
- Action swap: Swap an action label while preserving its place and intent.
- Icon morph: Icons that morph between states: menu to close, play to pause, copy to check, and more.
- Confirm morph: A destructive button that morphs into an inline confirmation, a spinner, and a result with undo.
Guidance for AI tools
Copy button: Copy a value with immediate confirmation. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.
Full library index: https://ui.xzero.co.uk/llms.txt