# Copy Button

Copy Button [#copy-button]

The **Copy Button** copies its `value` to the clipboard and shows a 2-second
"Copied" confirmation before reverting. It disables itself when there is nothing
to copy, and treats an unavailable clipboard (insecure context or denied
permission) as a silent no-op — so it never throws in a hostile environment.

> **Presentational + controlled.** Pass the text via `value`; the button owns
> only its transient "Copied" state. Use it beside any generated text, code
> block, or result.

**When to use it:** anywhere the user should be able to copy a value with clear
visual confirmation — generated answers, model ids, export payloads, snippets.

Preview [#preview]

```tsx
'use client';

import { CopyButton } from '@/components/copy-button';

/**
 * Demo for CopyButton, used by the docs live preview. Click to copy — the label
 * flips to "Copied" for two seconds. The empty-value button stays disabled.
 */
export default function CopyButtonDemo() {
  return (
    <div className="flex flex-wrap items-center gap-3">
      <CopyButton value="npx shadcn add @localmode/ui/input-controls/copy-button" />
      <CopyButton value="" />
    </div>
  );
}
```

Installation [#installation]

```bash
npx shadcn@latest add @localmode/ui/input-controls/copy-button
```

Dependencies [#dependencies]

* **Data source:** copies the `value` string you pass — works with any backend.
* `lucide-react` — the copy / check icons
* `clsx` + `tailwind-merge` — via the shared `cn()` util (installed automatically as a registry dependency)

Files installed [#files-installed]

* `copy-button.tsx` — the component
* `lib/utils.ts` — the `cn()` helper (if not already present)

Props [#props]

**CopyButton**

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `string` | — | **Required.** The text written to the clipboard on click. |
| `disabled` | `boolean` | — | Disable the button (also disabled automatically when `value` is empty). |

Examples [#examples]

Copy a generated result [#copy-a-generated-result]

```tsx
import { CopyButton } from '@/components/copy-button';

export function ResultToolbar({ text }) {
  return <CopyButton value={text} />;
}
```

Force-disable while streaming [#force-disable-while-streaming]

```tsx
<CopyButton value={partial} disabled={isStreaming} />
```

Customization [#customization]

The button uses `border-border` / `hover:bg-muted` token utilities and merges
your `className`. Because you own the copied file, you can change the confirmation
duration (the `2000` ms timeout), swap the icons, or make it icon-only.