Copy text
Add data-copy to a named button. Clicking it copies the attribute's literal text
and announces the result in a snackbar.
<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.