Copy to Clipboard
Copy text to the clipboard using the native
navigator.clipboard API. Pass a CSS selector to copy an
element's content, or pass a literal string directly.
Usage
npm install @erikt/ui
async function copyToClipboard({ selector, text } = {}) {
function getElementText(el) {
if (!el) return null;
return ("value" in el ? el.value : el.textContent).trim();
}
const value = selector
? getElementText(document.querySelector(selector))
: text;
if (value == null) return;
await navigator.clipboard.writeText(value);
}
// copy an element's content
copyToClipboard({ selector: "#snippet" });
// copy a literal string
copyToClipboard({ text: "npm install @erikt/ui" });Web Component
Wrap the same logic in a custom element. Give it a
for attribute to copy the content of a matching element,
or a value attribute to copy a literal string directly.
It dispatches a bubbling clipboard-copy event on success,
so a page can react (e.g. show "Copied!") without the component being
opinionated about the UI.
npm install @erikt/ui
<copy-to-clipboard for="#snippet">
<button type="button">Copy</button>
</copy-to-clipboard>
<pre id="snippet">npm install @erikt/ui</pre>
<copy-to-clipboard value="npm install @erikt/ui">
<button type="button">Copy</button>
</copy-to-clipboard>
class CopyToClipboard extends HTMLElement {
connectedCallback() {
this.addEventListener("click", this.copy);
}
disconnectedCallback() {
this.removeEventListener("click", this.copy);
}
copy = async () => {
const selector = this.getAttribute("for");
const source = selector ? document.querySelector(selector) : null;
const text = source
? ("value" in source ? source.value : source.textContent).trim()
: this.getAttribute("value");
if (text == null) return;
await navigator.clipboard.writeText(text);
this.dispatchEvent(
new CustomEvent("clipboard-copy", { bubbles: true, detail: { text } }),
);
};
}
if (!customElements.get("copy-to-clipboard")) {
customElements.define("copy-to-clipboard", CopyToClipboard);
}