Copy Button
This library is a work-in-progress. We are releasing it early to gather feedback, but it is not ready for production.
An accessible button component that copies text to the clipboard with visual feedback. The CopyButton automatically toggles between copy and checkmark icons and provides customizable success messaging.
Examples
Live Preview
Basic Copy Button
Projected Icons
Sizes & Variants
Inline Code Example
npm install agnosticui-coreCopy From Input
Copy the value from the input using reactive binding.
View Vue Code
```vue
<template>
<section>
<div class="mbe4">
<h2>Basic Copy Button</h2>
</div>
<div class="stacked-mobile mbe4">
<VueCopyButton
text="https://agnosticui.com"
label="Copy URL"
/>
</div>
<div class="mbe4">
<h2>Projected Icons</h2>
</div>
<div class="stacked-mobile mbe4">
<VueCopyButton
text="Projected Icons Example"
label="Projected Icons"
>
<template #icon-copy>
<svg
width="100%"
height="100%"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7.5 3H14.6C16.8402 3 17.9603 3 18.816 3.43597C19.5686 3.81947 20.1805 4.43139 20.564 5.18404C21 6.03969 21 7.15979 21 9.4V16.5M6.2 21H14.3C15.4201 21 15.9802 21 16.408 20.782C16.7843 20.5903 17.0903 20.2843 17.282 19.908C17.5 19.4802 17.5 18.9201 17.5 17.8V9.7C17.5 8.57989 17.5 8.01984 17.282 7.59202C17.0903 7.21569 16.7843 6.90973 16.408 6.71799C15.9802 6.5 15.4201 6.5 14.3 6.5H6.2C5.0799 6.5 4.51984 6.5 4.09202 6.71799C3.71569 6.90973 3.40973 7.21569 3.21799 7.59202C3 8.01984 3 8.57989 3 9.7V17.8C3 18.9201 3 19.4802 3.21799 19.908C3.40973 20.2843 3.71569 20.5903 4.09202 20.782C4.51984 21 5.0799 21 6.2 21Z"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</template>
<template #icon-copied>
<svg
width="100%"
height="100%"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M20 6L9 17L4 12"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</template>
</VueCopyButton>
</div>
<div class="mbe4">
<h2>Sizes & Variants</h2>
</div>
<div class="stacked-mobile mbe4">
<VueCopyButton
text="Copy this"
size="xs"
/>
<VueCopyButton
text="Copy this"
size="sm"
/>
<VueCopyButton
text="Copy this"
size="md"
/>
<VueCopyButton
text="Copy this"
size="lg"
/>
<VueCopyButton
text="Copy this"
size="xl"
/>
</div>
<div class="stacked-mobile mbe4">
<VueCopyButton
text="Copy primary"
variant="primary"
/>
<VueCopyButton
text="Copy success"
variant="success"
/>
<VueCopyButton
text="Copy warning"
variant="warning"
/>
<VueCopyButton
text="Copy danger"
variant="danger"
/>
<VueCopyButton
text="Copy ghost"
variant="ghost"
/>
</div>
<div class="mbe4">
<h2>Inline Code Example</h2>
</div>
<div class="code-example mbe4">
<pre><code>npm install agnosticui-core</code></pre>
<VueCopyButton
class="code-copy"
text="npm install agnosticui-core"
label="Copy install command"
size="sm"
variant="ghost"
></VueCopyButton>
</div>
<div class="mbe4">
<h2>Copy From Input</h2>
<p
class="mbe2"
style="color: var(--ag-text-secondary); font-size: 0.875rem;"
>Copy the value from the input using reactive binding.</p>
</div>
<div class="stacked-mobile mbe4">
<div style="display:flex;gap:12px;align-items:center;flex:1;">
<input
v-model="inputValue"
aria-label="Copy input"
style="padding:8px;flex:1;border-radius:6px;border:1px solid var(--ag-border)"
/>
<VueCopyButton
:text="inputValue"
label="Copy input"
/>
</div>
</div>
</section>
</template>
<script>
import { VueCopyButton } from "agnosticui-core/copy-button/vue";
import { Clipboard, Check } from "lucide-vue-next";
export default {
name: "CopyButtonExamples",
components: {
VueCopyButton,
Clipboard,
Check,
},
data() {
return {
inputValue: "https://agnosticui.com/components/copybutton",
};
},
};
</script>
<style scoped>
.stacked-mobile {
align-items: center;
}
.code-example {
position: relative;
background: var(--ag-background-secondary);
padding: var(--ag-space-4);
border-radius: var(--ag-radius-md);
}
.code-copy {
position: absolute;
top: var(--ag-space-2);
right: var(--ag-space-2);
}
</style>
Live Preview
View Lit / Web Component Code
import { LitElement, html } from 'lit';
import 'agnosticui-core/copy-button';
export class CopyButtonLitExamples extends LitElement {
// Render in light DOM to access global utility classes
createRenderRoot() {
return this;
}
constructor() {
super();
this.inputValue = 'https://agnosticui.com/components/copybutton';
}
handleInputChange(e) {
this.inputValue = e.target.value;
this.requestUpdate();
}
render() {
return html`
<section>
<!-- Basic Copy Button -->
<div class="mbe4">
<h2>Basic Copy Button</h2>
</div>
<div class="stacked-mobile mbe4">
<ag-copy-button
text="https://agnosticui.com"
label="Copy URL"
></ag-copy-button>
</div>
<!-- Projected Icons -->
<div class="mbe4">
<h2>Projected Icons</h2>
</div>
<div class="stacked-mobile mbe4">
<ag-copy-button
text="Projected Icons Example"
label="Projected Icons"
>
<svg
slot="icon-copy"
width="100%"
height="100%"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7.5 3H14.6C16.8402 3 17.9603 3 18.816 3.43597C19.5686 3.81947 20.1805 4.43139 20.564 5.18404C21 6.03969 21 7.15979 21 9.4V16.5M6.2 21H14.3C15.4201 21 15.9802 21 16.408 20.782C16.7843 20.5903 17.0903 20.2843 17.282 19.908C17.5 19.4802 17.5 18.9201 17.5 17.8V9.7C17.5 8.57989 17.5 8.01984 17.282 7.59202C17.0903 7.21569 16.7843 6.90973 16.408 6.71799C15.9802 6.5 15.4201 6.5 14.3 6.5H6.2C5.0799 6.5 4.51984 6.5 4.09202 6.71799C3.71569 6.90973 3.40973 7.21569 3.21799 7.59202C3 8.01984 3 8.57989 3 9.7V17.8C3 18.9201 3 19.4802 3.21799 19.908C3.40973 20.2843 3.71569 20.5903 4.09202 20.782C4.51984 21 5.0799 21 6.2 21Z"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
<svg
slot="icon-copied"
width="100%"
height="100%"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M20 6L9 17L4 12"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</ag-copy-button>
</div>
<!-- Sizes & Variants -->
<div class="mbe4">
<h2>Sizes & Variants</h2>
</div>
<div class="stacked-mobile mbe4">
<ag-copy-button text="Copy this" size="xs"></ag-copy-button>
<ag-copy-button text="Copy this" size="sm"></ag-copy-button>
<ag-copy-button text="Copy this" size="md"></ag-copy-button>
<ag-copy-button text="Copy this" size="lg"></ag-copy-button>
<ag-copy-button text="Copy this" size="xl"></ag-copy-button>
</div>
<div class="stacked-mobile mbe4">
<ag-copy-button text="Copy primary" variant="primary"></ag-copy-button>
<ag-copy-button text="Copy success" variant="success"></ag-copy-button>
<ag-copy-button text="Copy warning" variant="warning"></ag-copy-button>
<ag-copy-button text="Copy danger" variant="danger"></ag-copy-button>
<ag-copy-button text="Copy ghost" variant="ghost"></ag-copy-button>
</div>
<!-- Inline Code Example -->
<div class="mbe4">
<h2>Inline Code Example</h2>
</div>
<div class="code-example mbe4">
<pre><code>npm install agnosticui-core</code></pre>
<ag-copy-button
class="code-copy"
text="npm install agnosticui-core"
label="Copy install command"
size="sm"
variant="ghost"
></ag-copy-button>
</div>
<!-- Copy From Input -->
<div class="mbe4">
<h2>Copy From Input</h2>
<p class="mbe2" style="color: var(--ag-text-secondary); font-size: 0.875rem;">
Copy the value from the input using reactive binding.
</p>
</div>
<div class="stacked-mobile mbe4">
<div style="display:flex;gap:12px;align-items:center;flex:1;">
<input
.value=${this.inputValue}
@input=${this.handleInputChange}
aria-label="Copy input"
style="padding:8px;flex:1;border-radius:6px;border:1px solid var(--ag-border)"
/>
<ag-copy-button
text=${this.inputValue}
label="Copy input"
></ag-copy-button>
</div>
</div>
</section>
`;
}
}
// Register the custom element
customElements.define('copybutton-lit-examples', CopyButtonLitExamples);
Interactive Preview: Click the "Open in StackBlitz" button below to see this example running live in an interactive playground.
View React Code
import { useState } from "react";
import { ReactCopyButton } from "agnosticui-core/copy-button/react";
export default function CopyButtonReactExamples() {
const [inputValue, setInputValue] = useState("https://agnosticui.com/components/copybutton");
const handleInputChange = (e) => {
setInputValue(e.target.value);
};
return (
<section>
{/* Basic Copy Button */}
<div className="mbe4">
<h2>Basic Copy Button</h2>
</div>
<div className="stacked-mobile mbe4">
<ReactCopyButton
text="https://agnosticui.com"
label="Copy URL"
/>
</div>
{/* Projected Icons */}
<div className="mbe4">
<h2>Projected Icons</h2>
</div>
<div className="stacked-mobile mbe4">
<ReactCopyButton
text="Projected Icons Example"
label="Projected Icons"
iconCopy={
<svg
width="100%"
height="100%"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7.5 3H14.6C16.8402 3 17.9603 3 18.816 3.43597C19.5686 3.81947 20.1805 4.43139 20.564 5.18404C21 6.03969 21 7.15979 21 9.4V16.5M6.2 21H14.3C15.4201 21 15.9802 21 16.408 20.782C16.7843 20.5903 17.0903 20.2843 17.282 19.908C17.5 19.4802 17.5 18.9201 17.5 17.8V9.7C17.5 8.57989 17.5 8.01984 17.282 7.59202C17.0903 7.21569 16.7843 6.90973 16.408 6.71799C15.9802 6.5 15.4201 6.5 14.3 6.5H6.2C5.0799 6.5 4.51984 6.5 4.09202 6.71799C3.71569 6.90973 3.40973 7.21569 3.21799 7.59202C3 8.01984 3 8.57989 3 9.7V17.8C3 18.9201 3 19.4802 3.21799 19.908C3.40973 20.2843 3.71569 20.5903 4.09202 20.782C4.51984 21 5.0799 21 6.2 21Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
}
iconCopied={
<svg
width="100%"
height="100%"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M20 6L9 17L4 12"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
}
/>
</div>
{/* Sizes & Variants */}
<div className="mbe4">
<h2>Sizes & Variants</h2>
</div>
<div className="stacked-mobile mbe4">
<ReactCopyButton text="Copy this" size="xs" />
<ReactCopyButton text="Copy this" size="sm" />
<ReactCopyButton text="Copy this" size="md" />
<ReactCopyButton text="Copy this" size="lg" />
<ReactCopyButton text="Copy this" size="xl" />
</div>
<div className="stacked-mobile mbe4">
<ReactCopyButton text="Copy primary" variant="primary" />
<ReactCopyButton text="Copy success" variant="success" />
<ReactCopyButton text="Copy warning" variant="warning" />
<ReactCopyButton text="Copy danger" variant="danger" />
<ReactCopyButton text="Copy ghost" variant="ghost" />
</div>
{/* Inline Code Example */}
<div className="mbe4">
<h2>Inline Code Example</h2>
</div>
<div className="code-example mbe4">
<pre><code>npm install agnosticui-core</code></pre>
<ReactCopyButton
className="code-copy"
text="npm install agnosticui-core"
label="Copy install command"
size="sm"
variant="ghost"
/>
</div>
{/* Copy From Input */}
<div className="mbe4">
<h2>Copy From Input</h2>
<p className="mbe2" style={{ color: "var(--ag-text-secondary)", fontSize: "0.875rem" }}>
Copy the value from the input using reactive binding.
</p>
</div>
<div className="stacked-mobile mbe4">
<div style={{ display: "flex", gap: "12px", alignItems: "center", flex: 1 }}>
<input
value={inputValue}
onChange={handleInputChange}
aria-label="Copy input"
style={{
padding: "8px",
flex: 1,
borderRadius: "6px",
border: "1px solid var(--ag-border)"
}}
/>
<ReactCopyButton
text={inputValue}
label="Copy input"
/>
</div>
</div>
</section>
);
}
Basic Usage
TIP
The framework examples below import AgnosticUI as an npm package. Alternatively, you can use the CLI for complete control, AI/LLM visibility, and full code ownership:
npx ag init --framework FRAMEWORK # react, vue, lit, svelte, etc.
npx ag add CopybuttonThe CLI copies source code directly into your project, giving you full visibility and control. After running npx ag add, you'll receive exact import instructions.
Lit (Web Components)
<script type="module">
import 'agnosticui-core/copy-button';
</script>
<ag-copy-button
text="npm install agnosticui-core"
label="Copy install command"
></ag-copy-button>
<ag-copy-button
text="console.log('Hello, AgnosticUI!');"
label="Copy code snippet"
success-label="Code copied!"
></ag-copy-button>
<ag-copy-button
id="copy-btn"
text="Event handling example"
label="Copy with event"
></ag-copy-button>
<script>
const copyBtn = document.querySelector('#copy-btn');
copyBtn?.addEventListener('copy', (e) => {
console.log('Copied to clipboard:', e.detail.text);
});
</script>Vue
<template>
<section>
<VueCopyButton
text="npm install agnosticui-core"
label="Copy install command"
/>
<VueCopyButton
id="vue-copy-btn"
text="Event handling example"
label="Copy with event"
/>
</section>
</template>
<script>
import VueCopyButton from 'agnosticui-core/copy-button/vue'
export default {
components: { VueCopyButton },
mounted() {
const copyBtn = document.querySelector('#vue-copy-btn');
copyBtn?.addEventListener('copy', (e) => {
console.log('Copied to clipboard (Vue):', e.detail.text);
});
}
}
</script>React
import React from 'react';
import { ReactCopyButton } from 'agnosticui-core/copy-button/react';
export default function Example() {
return (
<div>
<ReactCopyButton text="npm install agnosticui-core" label="Copy install command" />
<ReactCopyButton
text="Event handling example"
label="Copy with event"
onCopy={(e: any) => console.log('Copied to clipboard (React):', e.detail?.text)}
/>
</div>
);
}Custom Icons
The CopyButton allows you to provide custom SVG icons for both the copy and copied states while maintaining default fallbacks:
<ag-copy-button
text="Uses default Material Design icons"
label="Copy with defaults"
></ag-copy-button>
<ag-copy-button
text="Both icons customized"
label="Copy with custom icons"
>
<svg slot="icon-copy" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1z" />
<rect x="8" y="5" width="11" height="14" rx="2" ry="2" stroke="currentColor" fill="none" />
<path d="M8 7h8" stroke="currentColor" />
</svg>
<svg slot="icon-copied" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" fill="#16A34A" stroke="none">
<circle cx="12" cy="12" r="10" />
<path d="M9 12.5l2 2 4-5" fill="none" stroke="#fff" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</ag-copy-button>Using Icon Libraries
You can use any SVG icon library with the custom icon slots:
<ag-copy-button text="Heroicons example" label="Copy">
<svg slot="icon-copy" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 01-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 011.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 00-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 01-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 00-3.375-3.375h-1.5a1.125 1.125 0 01-1.125-1.125v-1.5a3.375 3.375 0 00-3.375-3.375H9.75" />
</svg>
<svg slot="icon-copied" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</ag-copy-button>
<ag-copy-button text="Feather Icons example" label="Copy">
<svg slot="icon-copy" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
<svg slot="icon-copied" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
<polyline points="22 4 12 14.01 9 11.01"></polyline>
</svg>
</ag-copy-button>Props
| Prop | Type | Default | Description |
|---|---|---|---|
text | string | '' | Required. The text to copy to the clipboard. |
label | string | 'Copy to clipboard' | Accessible label for the button (aria-label). Announced by screen readers. |
successLabel | string | 'Copied!' | Label to show when the text has been successfully copied. |
size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | Size of the button. Controls button dimensions and icon size. |
variant | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'ghost' | 'monochrome' | 'ghost' | Visual style variant. Inherits from IconButton styling. |
Slots
| Slot | Description |
|---|---|
icon-copy | Custom SVG icon for the default copy state. Falls back to a copy icon if not provided. |
icon-copied | Custom SVG icon for the success/copied state. Falls back to checkmark icon if not provided. |
Note: If you provide custom icons, you must supply both the
icon-copyandicon-copiedslots together. Providing only one will throw a runtime error.
Events
| Event | Detail | Description |
|---|---|---|
copy | { text: string } | Fired when text is successfully copied to the clipboard. Provides the copied text in the event detail. |
Event Handling Examples
<ag-copy-button id="event-example" text="Event example"></ag-copy-button>
<script>
const btn = document.querySelector('#event-example');
btn.addEventListener('copy', (e) => {
console.log('Copied:', e.detail.text);
showToast(`Copied: ${e.detail.text}`);
});
</script>
<script>
const copyBtn = document.querySelector('#multi-handler');
copyBtn.addEventListener('copy', (e) => {
trackEvent('copy_button', { text: e.detail.text });
});
copyBtn.addEventListener('copy', (e) => {
updateCopyCount();
});
</script>Accessibility
The CopyButton is built on top of IconButton and implements proper accessibility:
- Uses semantic
<button>element - Provides clear accessible labels via
aria-label - Announces state changes to screen readers (copy → copied)
- Keyboard accessible (Space and Enter keys)
- Clear focus indicators for keyboard navigation
- Minimum 44px touch target for mobile accessibility (WCAG 2.1 Level AAA)
Success Feedback
The success state provides feedback through:
- Visual: Icon changes from copy to checkmark
- Text: Label updates from "Copy to clipboard" to "Copied!"
- Assistive tech: Screen readers announce the new label
- Timing: Automatically reverts after 1 second
Common Patterns
Code Snippets
Use CopyButton alongside code blocks in documentation:
<div class="code-example">
<pre><code>npm install agnosticui-core</code></pre>
<ag-copy-button
text="npm install agnosticui-core"
label="Copy install command"
size="sm"
variant="ghost"
></ag-copy-button>
</div>
<style>
.code-example {
position: relative;
background: #f3f4f6;
padding: var(--ag-space-4);
border-radius: var(--ag-radius);
}
.code-example ag-copy-button {
position: absolute;
top: var(--ag-space-2);
right: var(--ag-space-2);
}
</style>API Keys and Tokens
Copy sensitive information with visual confirmation:
<div class="token-display">
<code id="api-token">sk_test_abc123xyz789...</code>
<ag-copy-button
text="sk_test_abc123xyz789..."
label="Copy API token"
success-label="Token copied!"
variant="monochrome"
size="sm"
></ag-copy-button>
</div>
<script>
const copyBtn = document.querySelector('.token-display ag-copy-button');
copyBtn.addEventListener('copy', () => {
console.log('API token copied at:', new Date().toISOString());
});
</script>Share URLs
Make sharing links easier:
<div class="share-section">
<label for="share-url">Share this page:</label>
<div class="share-input-group">
<input
id="share-url"
type="text"
readonly
value="https://agnosticui.com/components/copybutton"
/>
<ag-copy-button
text="https://agnosticui.com/components/copybutton"
label="Copy share link"
success-label="Link copied!"
variant="primary"
></ag-copy-button>
</div>
</div>Integration with Toast Notifications
Combine with toast notifications for enhanced feedback:
<ag-copy-button
id="toast-copy"
text="Content to copy"
label="Copy"
></ag-copy-button>
<script>
import 'agnosticui-core/toast';
const btn = document.querySelector('#toast-copy');
const toastContainer = document.querySelector('ag-toast-container');
btn.addEventListener('copy', (e) => {
const toast = document.createElement('ag-toast');
toast.type = 'success';
toast.textContent = `Copied: ${e.detail.text}`;
toastContainer.appendChild(toast);
});
</script>Browser Support
The CopyButton uses the Clipboard API which is supported in all modern browsers:
- Chrome/Edge 66+
- Firefox 63+
- Safari 13.1+
For older browsers, the copy operation will fail gracefully and log an error to the console.
Best Practices
- Provide clear context - Use descriptive labels that indicate what's being copied
- Position strategically - Place copy buttons near the content they copy
- Use appropriate variants - Ghost or monochrome work well in most contexts
- Consider mobile - The default sizes work well on touch devices
- Track failures - Listen for console errors if clipboard access fails
- Combine with feedback - Consider adding toast notifications for important copy actions
- Secure sensitive data - Log or audit when sensitive information is copied
When to Use
Use CopyButton when:
- Users need to copy code snippets, commands, or text
- You want to reduce friction in workflows (API keys, share links)
- Space is limited and you need a compact copy solution
- You have documentation or technical content
Consider alternatives when:
- The content is very long (let users select and copy themselves)
- Copy functionality isn't the primary action
- You need more context than a button provides