# Copy to clipboard

> Copy text or field values with accessible clipboard feedback.

## Copy text

Add `data-copy` to a named button. Clicking it copies the attribute's literal text and announces the result in a [snackbar](/snackbar.html.md).

Copy greeting

```
<button type="button" data-copy="Hello from ExpressiveCSS">Copy greeting</button>
```

The root bundle installs `Copy.Init()`. Buttons added later work through the same document listener. `AutoInit()` and per-element instances are unnecessary. Use HTTPS or localhost and a user click for clipboard access. A denied or unavailable Clipboard API shows the failure message; it does not copy the text.

## Copy an element

Use `data-copy-for="id"` to name a source in the button's document or shadow root. Inputs, textareas and selects supply their current `value`. Other elements supply trimmed `textContent`, including text hidden by CSS.

```
<pre id="install-command">npm install @expressivecss/expressive</pre>
<button type="button" data-copy-for="install-command">Copy install command</button>
```

`data-copy` wins if both attributes are present, including an empty string. A missing source does nothing. Disabled buttons and controls with `aria-disabled="true"` do nothing. Give icon-only buttons an accessible name.

## Feedback and translation

The defaults are `Copied` and `Couldn't copy`. Change `Copy.i18n.copied` and `Copy.i18n.failed` globally, or set `data-copy-message` and `data-copy-error` on one button.

```
<button type="button" data-copy="INV-42"
  data-copy-message="Invoice number copied"
  data-copy-error="Copy failed. Select the invoice number manually.">Copy invoice number</button>
```

Each attempt replaces the current snackbar so feedback appears at once. After the clipboard promise settles, `expressive:copy` bubbles from the button and crosses shadow roots. Its `detail` is `{ text, copied }`. `copied` is `false` when clipboard access fails.

```
document.addEventListener('expressive:copy', (event) => {
  console.log(event.detail.copied, event.detail.text);
});
```

## JavaScript API

```
import { Copy } from '@expressivecss/expressive/modular';

Copy.i18n.copied = 'Text copied';
Copy.i18n.failed = 'Clipboard unavailable';
Copy.Init();

const button = document.querySelector('[data-copy-for]');
const text = Copy.textFor(button); // string, or null if the source is missing
```

`Copy.Init()` installs the click listener. Repeated calls add no duplicate listener. `Copy.textFor(button)` resolves text without writing the clipboard, showing feedback or checking the button's disabled state. Copy has no `init(element)`, `getInstance()` or `destroy()` method.
