# Clipboard

> A copy button puts the text of a field, a snippet or a literal string on the clipboard, and says so for a moment.

Add copy to clipboard buttons that copy a field, an element or a literal string, with a copied state and events.

Source: https://docs.tabler.io/ui/plugins/clipboard

---

## Overview

An API key, an invite link or an install command is there to be copied. Add `data-bs-toggle="clipboard"` to a button and point it at what to copy. Tabler writes the text with the browser's own clipboard API, so there is no library to load.

```html
<div class="input-group">
  <input type="text" id="clipboard-key" class="form-control" value="tblr_live_8f2c41d0a7" readonly />
  <button type="button" class="btn" data-bs-toggle="clipboard" data-bs-target="#clipboard-key">
    <span class="clipboard-label">Copy</span>
    <span class="clipboard-feedback">Copied</span>
  </button>
</div>
```

## Usage

Put the two states in the markup: a `clipboard-label` for the resting button and a `clipboard-feedback` for the moment after a copy. Tabler hides one and shows the other, so both words stay in your own language.

```html
<button type="button" class="btn" data-bs-toggle="clipboard" data-bs-target="#api-key">
  <span class="clipboard-label">Copy</span>
  <span class="clipboard-feedback">Copied</span>
</button>
```

`data-bs-target` takes any selector. A field is read from its value, anything else from its text.

```html
<code id="clipboard-snippet" class="me-2">npm install @tabler/core</code>
<button type="button" class="btn btn-sm" data-bs-toggle="clipboard" data-bs-target="#clipboard-snippet">
  <span class="clipboard-label">Copy command</span>
  <span class="clipboard-feedback">Copied</span>
</button>
```

### Colour on the feedback

The feedback element takes any utility, so a `text-green` check confirms the copy in colour. The trigger itself carries a `copied` class while the state lasts, for styling that goes further.

```html
<div class="input-group input-group-flat">
  <input type="text" id="clipboard-green" class="form-control" value="tblr_live_8f2c41d0a7" readonly />
  <span class="input-group-text">
    <button type="button" class="link-secondary input-group-link border-0 bg-transparent p-0" data-bs-toggle="clipboard" data-bs-target="#clipboard-green" aria-label="Copy the API key">
      <svg xmlns="http://www.w3.org/2000/svg" class="icon clipboard-label" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
        <path stroke="none" d="M0 0h24v24H0z" fill="none" />
        <path d="M9 5h-2a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-12a2 2 0 0 0 -2 -2h-2" />
        <path d="M9 3m0 2a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2z" />
      </svg>
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon clipboard-feedback text-green">
        <path stroke="none" d="M0 0h24v24H0z" fill="none" />
        <path d="M5 12l5 5l10 -10" />
      </svg>
      <span class="clipboard-feedback visually-hidden">Copied</span>
    </button>
  </span>
</div>
```

### A literal string

Use `data-bs-text` when the text is not on the page.

```html
https://tabler.io/
```

### How long the copied state lasts

`data-bs-delay` sets the milliseconds before the button goes back to its label. The default is 2000. Set it to `0` to keep the copied state until you reset it from code.

```html
Tabler
```

## Options

| Option | Default | Description |
| --- | --- | --- |
| `target` | none | Selector of the element to read. A field gives its value, anything else its text. |
| `text` | none | A literal string to copy. Wins over `target`. |
| `delay` | `2000` | How long the copied state lasts, in milliseconds. `0` keeps it. |

## JavaScript

Tabler ships a `Clipboard` component that works like the Bootstrap components: it is created once per element and stored on it. On page load Tabler creates one for every element with `data-bs-toggle="clipboard"`. This is the code that runs:

```ts
initAll(SELECTOR_DATA_TOGGLE, Clipboard)
```

_Source: `core/js/src/clipboard.ts`_

Copy from your own code, for example after building a string:

```js
const button = document.getElementById('share');
tabler.Clipboard.getOrCreateInstance(button, { text: window.location.href }).copy();
```

A successful copy fires `copied.bs.clipboard`, a failed one `error.bs.clipboard`:

```js
button.addEventListener('error.bs.clipboard', () => {
  console.log('nothing copied');
});
```

| Method | Description |
| --- | --- |
| `copy()` | Copies the text and shows the copied state. Returns a promise. |
| `text` | Getter. The string the button would copy right now. |
| `dispose()` | Stops the timer and removes the component from the element. |
| `getInstance(element)` | Static. Returns the component for the element, or `null`. |
| `getOrCreateInstance(element, config)` | Static. Returns the component for the element and creates it when needed. |

## Accessibility

- Write both words in the markup. The feedback element is a `role="status"` and is revealed rather than restyled, so a screen reader announces the copy.
- Keep the button a real `button` with `type="button"`, so it is reachable by keyboard and does not submit a form.
- A button with only an icon needs an `aria-label` saying what it copies, for example `aria-label="Copy the API key"`.

## Browser support

The browser gives `navigator.clipboard` to secure contexts only: `https`, or `localhost` while you develop. On plain `http` the copy fails and `error.bs.clipboard` fires, so a page can say so instead of leaving the button silent.
