npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@parsonic/copy-to-clipboard

v1.5.0

Published

Copy text to clipboard web component

Readme

Copy To Clipboard

A web component for copying items to the clipboard.

Install

npm install --save @parsonic/copy-to-clipboard

Usage

Use copy-to-clipboard with your favourite bundler or directly from a CDN. A minified build is provided as min.js with a source map.

Quick start

Add a script tag with the minified build and use the element in your page.

<script
  defer
  src="https://cdn.jsdelivr.net/npm/@parsonic/copy-to-clipboard/min.js"></script>
<copy-to-clipboard>
  <pre><code>npm install --save @parsonic/copy-to-clipboard</code></pre>
</copy-to-clipboard>

Bundler

Import the CopyToClipboard component at the root of your application and register it.

import CopyToClipboard from '@parsonic/copy-to-clipboard/CopyToClipboard.js'

CopyToClipboard.register()

// Use <copy-to-clipboard></copy-to-clipboard> in your page or components

CDN

Import the CopyToClipboard component from the CDN and register it before using.

<script type="module">
  import CopyToClipboard from 'https://cdn.jsdelivr.net/npm/@parsonic/copy-to-clipboard/CopyToClipboard.js'

  CopyToClipboard.register()
</script>

<copy-to-clipboard>
  <!-- Content to copy -->
</copy-to-clipboard>

If you prefer to give the element an alternative tag name you can pass this to the register method.

// To use as <my-copy-to-clipboard></my-copy-to-clipboard>
CopyToClipboard.register('my-copy-to-clipboard')

Providing the item to copy

The text content of the element will be copied to the clipboard when the copy button is pressed unless the clipboard item is explicitly set.

<copy-to-clipboard>
  <p>This text will be copied to the clipboard</p>
</copy-to-clipboard>

To better format the text either pass the text content to the data-text attribute on the element or set it using the item property on the underlying object. This property is useful when using the element with a JavaScript framework like React.

<copy-to-clipboard data-text="This is the text copied to the clipboard">
  <!-- Page content -->
</copy-to-clipboard>
const copyToClipboard = document.querySelector('copy-to-clipboard')
copyToClipboard.item = new ClipboardItem({
  'text/plain': formattedText,
})

Copying other data types

To copy other data types like an image to the clipboard pass the URL to the data in the data-url attribute. The URL may point to a separate file or contain the data directly as a data URL.

<copy-to-clipboard data-url="./my-image-full.png">
  <img src="./my-image.png" />
</copy-to-clipboard>

<copy-to-clipboard data-url="data:image/png;...">
  <img src="./my-image.png" />
</copy-to-clipboard>

As with text the item property of the underlying object can be used for other data types.

// Copy blob to clipboard if type is supported
if (ClipboardItem.supports(blob.type)) {
  const copyToClipboard = document.querySelector('copy-to-clipboard')
  copyToClipboard.item = new ClipboardItem({
    [blob.type]: blob,
  })
}

Customising the copy button

The default button comprises of a button element with two SVG icons, the clipboard icon and the done icon. When the button is pressed an animation is applied to the icons to briefly show the done icon as a visual indicator that the copy was successful. A default ARIA label of Copy is applied to the button that can be set using the data-button-label attribute.

<copy-to-clipboard
  data-button-label="Copy image to clipboard"></copy-to-clipboard>

The button can be replaced entirely using the slot named button or styled. via the button CSS part.

<copy-to-clipboard>
  <pre>Text to copy...</pre>
  <button slot="button">Copy</button>
</copy-to-clipboard>

To style the icons inside the button use the copy-icon and done-icon CSS parts to target the SVG elements.

copy-to-clipboard::part(done-icon) {
  stroke: lightgreen;
}

To replace the icons use the copy-icon and done-icon slots.

<copy-to-clipboard>
  <pre>...</pre>
  <svg
    slot="copy-icon"
    xmlns="http://www.w3.org/2000/svg"
    width="16"
    height="16"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    stroke-linecap="round"
    stroke-linejoin="round">
    <rect width="14" height="14" x="8" y="8" rx="2" ry="2" />
    <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" />
  </svg>
</copy-to-clipboard>

The button may also be styled using the CSS custom properties listed below.

:root {
  --ctc-button-background: rgb(255 255 255 / 8%);
  --ctc-button-border: none;
  --ctc-button-color: inherit;
  --ctc-button-icon-size: 1rem;
  --ctc-button-inset: 0.5rem 0.5rem auto auto;
  --ctc-button-padding: 0.5rem;
  --ctc-button-radius: 0.5rem;
}

Announcement text

A successful copy will be announced to screen readers by updating a live region in the copy button with a message. To override the default announcement of 'Copied!', supply a message in the data-announcement attribute.

<copy-to-clipboard
  data-announcement="Text copied to clipboard!"></copy-to-clipboard>

The announcement text is visually hidden by default, to style the text use the announcement and button-wrapper CSS parts.

copy-to-clipboard {
  &::part(button-wrapper) {
    align-items: center;
    display: flex;
    flex-flow: row-reverse;
    gap: 0.25rem;
  }

  &::part(announcement) {
    height: unset;
    position: unset;
    width: unset;
  }
}

copy event

When the copy button is pressed the element dispatches a ClipboardEvent of type copy. The event is set to bubble and is cancellable and contains the clipboardData data transfer object. An event handler may set plain text data to be copied on the data transfer.

<copy-to-clipboard>
  <label for="field">A form field</label>
  <textarea id="field">Some text to copy</textarea>
</copy-to-clipboard>

<script>
  document.addEventListener('copy', (ev) => {
    const fieldValue = ev.target.querySelector('textarea').value
    ev.clipboardData.setData('text/plain', fieldValue)
  })
</script>

copyResult event

Once the item is written to the clipboard the element dispatches a copyResult custom event. If successful the event detail has a result of 'success' and contains the ClipboardItem as data. If an error occurred the result will be 'error' and the error is provided.

document.querySelector('copyResult', (ev) => {
  if (ev.detail.result === 'success') {
    console.log('Item copied to ciipbard', ev.detail.data)
  } else {
    console.error('Failed to copy', ev.detail.error)
  }
})