Software Engineering :: Web :: Development :: API :: Web Components :: Example :: Copy To Clipboard Button
⪼ Made with 💜 by Polyglot.
import IconCheck from '@icon/icon-check.svg'
import IconCopy from '@icon/icon-copy.svg'
import IconCopyError from '@icon/icon-copy-error.svg'
import { copyToUserClipboard } from '@core/clipboard'
const ICON_HIDE_DURATION_IN_MILLISECONDS = 2000;
const TEMPLATE = `
<span data-state="closed">
<button class="rounded-lg text-token-text-secondary hover:bg-token-main-surface-secondary tooltip-button" style="position: relative;">
<span class="flex h-[30px] w-[30px] items-center justify-center">${IconCopy}</span>
<tool-tip text="${chrome.i18n.getMessage('copy_tooltip_text')}" event-target-selector=".tooltip-button" />
</button>
</span>
`;
export class CopyButton extends HTMLElement {
private readonly conversationTitle: string;
constructor() {
super()
this.conversationTitle = this.getAttribute('conversationTitle') as string
}
connectedCallback(): void {
this.render()
this.addEventListeners()
}
disconnectedCallback(): void {
this.removeEventListeners()
}
private addEventListeners(): void {
const button = this.querySelector('button') as HTMLButtonElement
if (!(button instanceof HTMLButtonElement)) return
button.addEventListener('click', this.copyTitleToClipboard)
}
private removeEventListeners(): void {
const button = this.querySelector('button') as HTMLButtonElement
if (!(button instanceof HTMLButtonElement)) return
button.removeEventListener('click', this.copyTitleToClipboard)
}
private setIcon = (icon: string): void => {
const element = this.querySelector('svg')
if (!element) return
element.outerHTML = icon
}
private flashIcon = (icon: string): void => {
this.setIcon(icon)
setTimeout(() => this.setIcon(IconCopy), ICON_HIDE_DURATION_IN_MILLISECONDS)
}
private copyTitleToClipboard = (): void => {
copyToUserClipboard({
clipboardText: this.conversationTitle,
onSuccess: () => this.flashIcon(IconCheck),
onFailure: (error: Error) => {
console.error('Failed to copy text:', error)
this.flashIcon(IconCopyError)
},
})
}
private render(): void {
this.innerHTML = TEMPLATE;
}
}