# Copy Button

An accessible React copy to clipboard button for Next.js: the copy icon turns into a check, and screen readers hear "Copied".

Source: https://ui.fewtone.com/components/copy-button

## Installation

```bash
npx shadcn@latest add https://ui.fewtone.com/r/copy-button.json
```

## Usage

```tsx
import { CopyButton } from "@/components/ui/copy-button"

export function CopyCommand() {
  return <CopyButton value="npm install @fewtone/ui" />
}
```

## API reference

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `string` | – | The text to copy. |
| `copiedText` | `ReactNode` | – | Shown instead of the label once copied. |
| `onCopy` | `(value: string) => void` | – | Called after the text is copied. |
| `resetAfter` | `number` | `2000` | Milliseconds the check shows before the copy icon returns. |
| `icon` | `boolean` | `true` | Shows the copy icon and the check. Set false for a text-only button with a label. |
| `variant` | `Button variant` | `"ghost"` | The button style. |
| `size` | `Button size` | `"icon", or "md" with a label` | The button size. |

**When to use it:** Use CopyButton next to anything people copy: commands, code, links, API keys. Pass the text as value; add a label and copiedText when an icon alone isn't clear.
**Built on:** Button, Clipboard API.
**Accessibility pattern:** https://www.w3.org/WAI/ARIA/apg/patterns/button/
**npm packages (installed by the CLI):** lucide-react@^1.52.0, motion@^14.0.0.
**Installs these FewTone UI components with it:** `button`.

## Examples

### Variants

Icon only (named "Copy" for screen readers), or with a label that changes once it's copied, without the button changing width.

```tsx
import { CopyButton } from "@/components/ui/copy-button";
import { useId } from "react";

export default function CopyButtonVariants() {
  const id = useId();
  return (
    <ul className="flex flex-wrap items-end justify-center gap-x-10 gap-y-6">
      <li className="flex flex-col items-center gap-2">
        <CopyButton value="https://ui.fewtone.com" aria-describedby={`${id}-ghost`} />
        <span id={`${id}-ghost`} className="text-xs text-muted-foreground">
          Ghost
        </span>
      </li>
      <li className="flex flex-col items-center gap-2">
        <CopyButton value="https://ui.fewtone.com" variant="outline" aria-describedby={`${id}-outline`} />
        <span id={`${id}-outline`} className="text-xs text-muted-foreground">
          Outline
        </span>
      </li>
      <li className="flex flex-col items-center gap-2">
        <CopyButton value="https://ui.fewtone.com" variant="outline" copiedText="Copied">
          Copy link
        </CopyButton>
        <span className="text-xs text-muted-foreground">With text</span>
      </li>
    </ul>
  );
}
```

### A command

Next to a command or a snippet, in a small size.

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

const command = "npx shadcn@latest add https://ui.fewtone.com/r/copy-button.json";

export default function CopyButtonCommand() {
  return (
    <div className="flex w-full max-w-lg items-center gap-2 rounded-lg bg-muted py-1 ps-4 pe-1">
      <code className="min-w-0 flex-1 truncate font-mono text-sm">{command}</code>
      <CopyButton value={command} size="icon-sm" aria-label="Copy the command" />
    </div>
  );
}
```

### Next to a field

For links and keys people need to paste somewhere else.

```tsx
import { CopyButton } from "@/components/ui/copy-button";
import { Input } from "@/components/ui/input";
import { useId } from "react";

const link = "https://ui.fewtone.com/invite/k3x9";

export default function CopyButtonInput() {
  const id = useId();
  return (
    <div className="grid w-full max-w-sm gap-2">
      <label htmlFor={id} className="text-sm font-medium">
        Invite link
      </label>
      <div className="flex gap-2">
        <Input id={id} value={link} readOnly />
        <CopyButton value={link} variant="outline" copiedText="Copied">
          Copy
        </CopyButton>
      </div>
    </div>
  );
}
```

## Related

- [Button](https://ui.fewtone.com/components/button.md): An accessible React button for Next.js and Tailwind CSS with six variants, three sizes, icons and a soft tint on hover and press, built on a native button.
- [Loading Button](https://ui.fewtone.com/components/loading-button.md): An accessible React loading button for Next.js that shows loading, success and error states for async actions, without changing width.
- [Input](https://ui.fewtone.com/components/input.md): An accessible React text input with three sizes and clear invalid, disabled and file states, built on a native input.
