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.
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.
<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.
<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.
npm install @tabler/core<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.
<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.
<button type="button" class="btn" data-bs-toggle="clipboard" data-bs-text="https://tabler.io/">
<span class="clipboard-label">Copy link</span>
<span class="clipboard-feedback">Link copied</span>
</button>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.
<button type="button" class="btn" data-bs-toggle="clipboard" data-bs-text="Tabler" data-bs-delay="6000">
<span class="clipboard-label">Copy, six seconds</span>
<span class="clipboard-feedback">Copied</span>
</button>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:
initAll(SELECTOR_DATA_TOGGLE, Clipboard)Copy from your own code, for example after building a string:
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:
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
buttonwithtype="button", so it is reachable by keyboard and does not submit a form. - A button with only an icon needs an
aria-labelsaying what it copies, for examplearia-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.

