<!-- Protocore Design System — CopyButton -->
# CopyButton

- **Category:** Data Display (`data-display`)
- **Slug:** `data-display/copy-button`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { CopyButton } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/data-display/copy-button

> Copies a value to the clipboard and confirms with a check state; renders a labelled button or a render-prop.

## When to use it

**CopyButton** turns any short, copyable value into a one-click affordance with unambiguous confirmation — the check state is the receipt that the copy landed. Reach for it beside addresses, API keys, transaction hashes, invite codes, and config snippets.

Use the default labelled button for standalone chrome, or the `(copied, copy)` render-prop when the trigger has to be a different element — an icon-only button in a dense table, an item inside a menu, or a wrapper around a whole [CodeBlock](/data-display/code-block). For a secret that should stay hidden until revealed, compose it with [MaskedValue](/data-display/masked-value) instead of exposing the raw value.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `children` | `((copied: boolean, copy: () => void) => ReactNode)` | no | — | Render-prop: takes over rendering entirely. Receives the current `copied` flag and a `copy` callback to wire onto your own trigger. |
| `className` | `string` | no | — | — |
| `copiedLabel` | `string` | no | `Copied` | Confirmed label on the default button. |
| `label` | `string` | no | `Copy` | Idle label on the default button. |
| `size` | `enum` | no | `sm` | Control size for the default button: `sm` 24px · `md` 28px icon box. |
| `style` | `CSSProperties` | no | — | — |
| `timeout` | `number` | no | `1500` | How long the "copied" state persists, in ms. |
| `value` | `string` | yes | — | The string written to the clipboard when activated. |

## Examples

### Basics

Pass a `value` and the button writes it to the clipboard on click, flipping its glyph and label to a check + "Copied" for `timeout` ms (default 1500), then reverting.

```tsx
import { CopyButton } from "@protocore/pds";

export default function Basics() {
  return <CopyButton value="proto1qz8f9x2c4v6b8n0m2k4h6g8d0s2a4f6h8j0k2" />;
}
```

### Next to a value

The common pairing — a mono value (an address, a key, a hash) with a compact copy affordance beside it. Customize `label`/`copiedLabel` to fit the context.

```tsx
import { CopyButton, Code, HStack } from "@protocore/pds";

export default function Inline() {
  return (
    <HStack gap={2} align="center">
      <Code>0x8f2c4a9e…c2</Code>
      <CopyButton value="0x8f2c4a9e1b3d5f7a9c1e3b5d7f9a1c3e5b7d9f2c" label="Copy address" />
    </HStack>
  );
}
```

## Do & don't

**Do**

- Use it for short, discrete values a user will paste elsewhere.
- Keep the default ~1.5s confirmation.
- Use the render-prop when the trigger is an icon button or menu item.
- Label it for its context ("Copy address", "Copy hash").

**Don't**

- For long documents, offer a download or select-all.
- For a secret, pair with MaskedValue rather than showing plaintext.
- Keep the copied-state confirmation visible.
- Skip your own `setTimeout`; it manages the copied window.

## Accessibility

**Keyboard**

| Keys | Action |
| --- | --- |
| `Tab` | Moves focus to the button. |
| `Enter / Space` | Copies the value and enters the copied state. |

**Notes**

- The default button carries a visible text label alongside the icon, so it has an accessible name without extra ARIA.
- The copied transition is announced through a polite `role="status"` live region, so screen-reader users hear the confirmation, not just see it.
- Copy/check are inline SVG icons (`currentColor`), never text glyphs, so they never render as emoji and inherit the button's color.
- It uses the async Clipboard API when available and falls back gracefully; the copied state still fires so the UI stays truthful.
- With the render-prop, giving your trigger an accessible name is your responsibility — CopyButton only supplies `copied` and `copy`.

## Related

`masked-value`, `code-block`, `code-ref`, `kbd`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
