Vanilla Breeze

data-copy

Clipboard copy and paste via data attributes. Add data-copy, data-copy-target, or data-paste-target to any button for clipboard functionality with visual and screen-reader feedback.

Overview

The data-copy attribute enhances native buttons with clipboard copy behavior. No wrapper element needed — just add the attribute directly to a <button>.

How It Works

Add one of these attributes to any <button>:

  • data-copy — the attribute value is the text to copy
  • data-copy-target — a CSS selector pointing to another element whose textContent will be copied
  • data-copy-target + data-copy-attr — copies the named attribute of the target instead of its textContent
  • data-paste-target — a CSS selector for an element to receive the clipboard text on click

On click, the text is written to the clipboard, data-state="copied" is set for 1.5 seconds, a screen reader announcement fires, and a copy custom event is dispatched.

Attributes

Attribute Type Description
data-copy string Static text to copy to the clipboard.
data-copy-target string CSS selector for the element whose textContent to copy.
data-copy-attr string When paired with data-copy-target, copies the named attribute of the target instead of its textContent. Missing attributes copy an empty string.
data-paste-target string CSS selector for the element to receive the pasted clipboard text. Form controls get .value; other elements get .textContent.
data-state string Set to "copied" after a successful copy, or "pasted" after a successful paste. Held for 1.5s. Use in CSS for feedback styling.
data-copy-init boolean Set automatically to prevent double-binding. Do not set manually.

Copy from Target Element

Use data-copy-target with a CSS selector to copy text from another element on the page.

const greeting = "Hello, world!";

Copy from an Attribute

For state-bearing elements where the value you want is stored in an attribute rather than the text content, add data-copy-attr alongside data-copy-target. The button reads target.getAttribute(attrName) at click time.

Common targets:

  • <output value="..."> — computed values that don't appear as text
  • Custom elements that reflect state to an attribute (e.g. <color-picker value="...">)
  • Any element where authored data lives in an attribute

Note: Form controls' live .value property does not reflect to the value attribute after user input. data-copy-attr="value" on an <input> copies the initial markup value, not what the user has typed. For live form state, use the JavaScript API.

With Icons

Pair with <icon-wc> for a more visual button.

Events

The button dispatches a copy event on successful clipboard write.

Event Detail Description
copy { text: string } Fired after text is copied. The detail.text property contains the copied string.
paste { text: string } Fired after text is pasted into the target. The detail.text property contains the pasted string.

Common Use Cases

Code Block Copy Button

Position a copy button inside a code block:

npm install vanilla-breeze

Share Link

Quick share-by-link button:

Styling Feedback

The data-state="copied" attribute is set for 1.5 seconds after copying. Use it to style the copied state:

The default styles change the button text color to --color-success during the copied state.

JavaScript API

For components that need to copy computed strings (formatted output, JSON, CSS), import copyText() from the same module. It performs the clipboard write with the same visual feedback, screen-reader announcement, and copy event dispatch as the attribute pattern.

Option Type Default Description
button HTMLElement Receives data-state="copied" and dispatches the copy event. Omit for "fire and forget" copies.
announceMessage string "Copied to clipboard" Screen-reader announcement text.
duration number 1500 Milliseconds to hold data-state="copied".

Returns Promise<boolean> — resolves to true on success, false if the Clipboard API is unavailable or permission is denied. Never throws.

Paste from clipboard

The symmetric counterpart to data-copy-target. Add data-paste-target="<selector>" to a button to read the clipboard and write it into another element on click. Form controls (input, textarea, select) receive .value; other elements receive .textContent. An input event is dispatched on the target so framework listeners notice the change.

On success, data-state="pasted" is set for 1.5s, the screen reader hears "Pasted from clipboard", and a paste CustomEvent fires from the button with detail.text. Failures (permission denied, no clipboard text) are silent.

Most browsers prompt the user the first time a page calls navigator.clipboard.readText(). The button stays inert if the user denies permission.

Returns Promise<string | null> — the pasted text on success, null on failure. Never throws.

Rich clipboard (multi-format)

For payloads richer than text — copying a color as both hex and a swatch image, or a QR code as both the URL and a PNG — import copyRich(). It writes a ClipboardItem with any combination of text/plain, text/html, and a binary Blob (typically image/png). When the browser doesn't support ClipboardItem or rejects a specific MIME type, it transparently falls back to text-only via copyText().

Receiving apps choose the format they understand. Pasting into Slack or Figma uses the image; pasting into a code editor uses the text. The screen-reader announcement, data-state="copied" hook, and copy event behave exactly as with copyText().

VB's <qr-code> uses copyRich() internally via its copy() method.

Dynamic Buttons

Buttons added to the DOM after page load are automatically enhanced via a MutationObserver. No manual initialization is needed.