Skip to content

Instantly share code, notes, and snippets.

@breadthe
Last active April 11, 2022 12:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save breadthe/51d1629cf40fc40baa4a197ff4bda8fb to your computer and use it in GitHub Desktop.
Save breadthe/51d1629cf40fc40baa4a197ff4bda8fb to your computer and use it in GitHub Desktop.
Alpine.js + Blade copy to clipboard button
<!--
resources/js/app.js
Put this code at the bottom of `app.js`
OR
Put it in a `clipboard.js` file and import it in `app.js` with:
require('./clipboard');
-->
window.initClipboard = () => {
return {
copying: false,
async copyToClipboard(text) {
if (!navigator.clipboard || this.copying) {
return;
}
try {
this.copying = true;
await navigator.clipboard.writeText(text);
const iconElement = document.getElementById('icon-copy-to-clipboard')
const icon = iconElement.cloneNode(true);
const button = document.getElementById('button-copy-to-clipboard');
iconElement.remove();
button.append('✓');
setTimeout(() => {
this.copying = false;
button.innerText = '';
button.append(icon);
}, 2000);
} catch (error) {
this.copying = false;
console.error("failed copying to clipboard", error);
}
},
}
}
<!-- resources/views/components/buttons/copy-to-clipboard.blade.php -->
<button
id="button-copy-to-clipboard"
title="Copy to clipboard"
class="flex items-center justify-center border rounded w-10 h-10 text-xl"
:class="{ 'border-white text-green-600 font-bold' : copying, 'border-gray-400 hover:bg-gray-100' : !copying }"
x-data="initClipboard"
@click="copyToClipboard('{{ $text }}')"
>
<!-- Tabler icons `copy` -->
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" id="icon-copy-to-clipboard" class="">
<path stroke="none" d="M0 0h24v24H0z"></path>
<rect x="8" y="8" width="12" height="12" rx="2"></rect>
<path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path>
</svg>
</button>
<!-- Livewire component -->
<label class="flex flex-col">
<span class="uppercase tracking-tight font-medium">* Activity Title</span>
<div class="flex gap-2">
<input type="text"
wire:model="activity.name"
class="flex-1 px-2 py-1 border @error('activity.name') border-red-600 @else border-gray-400 @enderror text-lg text-black rounded shadow-inner"
placeholder="Activity title (2-255 characters)"
>
<x-buttons.copy-to-clipboard text="{{ $activity->name }}" />
</div>
@error('activity.name') <span class="text-red-600 font-medium">{{ $message }}</span> @enderror
</label>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment