Botão de copiar para a área de transferência (JavaScript e React)
Botão de copiar para a área de transferência
Botão de copiar para a área de transferência em JavaScript e React | We.Inc
Crie um botão de copiar com navigator.clipboard.writeText: demo funcional, um hook React, cópia de HTML formatado e imagens com ClipboardItem, aviso acessível de Copiado e tratamento de erros.
Chame navigator.clipboard.writeText(text) dentro de um handler de clique. Ele retorna uma promise, então use await, depois mostre uma mensagem curta de Copiado e trate o caso de erro. A API só funciona em HTTPS ou em localhost e precisa de uma ação real do usuário, como um clique, então não a chame no carregamento da página.
Formas de colocar dados na área de transferência
Método
Copia
Status
navigator.clipboard.writeText()
Texto simples
Baseline, amplamente disponível desde março de 2020
Um botão de copiar parece trivial, mas os trechos de código mais bem posicionados costumam pular as partes que dão errado: a promise pode ser rejeitada, frames incorporados podem ser bloqueados e usuários de leitor de tela nunca ficam sabendo que algo aconteceu. A demo abaixo copia de verdade no seu navegador, e o código cobre cada um desses casos.
Aperte um botão Copiar na demo. O rótulo muda para Copiado por dois segundos, e uma mensagem de status oculta anuncia isso.
Cole na caixa de teste para conferir exatamente o que foi para a sua área de transferência.
Teste o botão de cópia formatada e depois cole em um e-mail ou editor de documentos para ver a versão HTML manter a formatação.
Copie abaixo o JavaScript puro, o hook React ou o código de cópia formatada.
Sempre trate a rejeição. Mostre algo como Pressione Ctrl+C para copiar e selecione o texto, para que a pessoa termine manualmente.
Anuncie o sucesso com uma região role="status". Mudar só um ícone não diz nada a usuários de leitor de tela.
Mantenha a largura do rótulo do botão estável quando ele mudar para Copiado, para que nada ao redor pule.
Copie o valor a partir dos seus dados, não do innerText de um elemento estilizado, que pode pegar espaços em branco ocultos ou a mais.
Dentro de um iframe, o Chromium precisa que a página pai permita clipboard-write pela Permissions Policy, por exemplo allow="clipboard-write".
Perguntas frequentes
Por que navigator.clipboard está undefined?
A página não está em um contexto seguro. A Clipboard API só fica disponível em páginas HTTPS e em localhost, então um site servido por HTTP simples ou a partir de um endereço de rede local não vai tê-la.
Por que writeText lança NotAllowedError?
O navegador recusou a escrita, geralmente porque não houve uma ação recente do usuário, a página não estava em foco ou um frame foi bloqueado pela Permissions Policy. Chame-o diretamente dentro de um handler de clique e evite awaits longos antes dele.
Preciso de uma biblioteca para copiar para a área de transferência no React?
Não. Um hook de dez linhas em volta de navigator.clipboard.writeText resolve. As bibliotecas basicamente adicionam um fallback com execCommand para navegadores muito antigos, do qual os navegadores atuais não precisam.
Dá para copiar uma imagem para a área de transferência?
Sim, com navigator.clipboard.write e um ClipboardItem cuja chave é image/png e cujo valor é um Blob PNG. Use ClipboardItem.supports() para verificar um tipo antes; PNG é o formato que os navegadores aceitam com mais confiabilidade.
document.execCommand('copy') ainda serve?
Ele está obsoleto. Ainda funciona em muitos navegadores, em condições variadas, mas código novo deve usar a Clipboard API assíncrona e, como fallback, pedir que a pessoa copie manualmente.
As três regras que o navegador impõe
Escrever na área de transferência é uma ação privilegiada, então os navegadores exigem uma página segura, um documento em foco e, no Firefox e no Safari, um gesto novo do usuário para cada escrita. O Chromium também pode conceder uma permissão clipboard-write persistente.
Na prática, dispare a cópia a partir de um clique ou de uma tecla, faça a escrita logo no início do handler e trate a falha como algo normal, não excepcional.
Um retorno que as pessoas percebam
Troque o rótulo para Copiado por uns dois segundos e depois restaure. Uma dica que aparece só ao passar o mouse é invisível em telas de toque e para quem usa teclado.
Coloque a mesma mensagem em uma live region educada. role="status" a anuncia sem interromper o que o leitor de tela estava lendo.
Cópias formatadas e eventos copy personalizados
Um ClipboardItem pode guardar ao mesmo tempo uma versão text/plain e uma text/html. Apps que entendem HTML colam a formatada, e campos de texto simples ficam com a outra.
Para mudar o que um Ctrl+C normal copia, como adicionar uma linha de fonte, escute o evento copy, chame event.preventDefault() e defina os seus próprios dados com event.clipboardData.setData().
JavaScript puro
Botão de copiar com retorno e fallback
O elemento de status fica visualmente oculto, mas é lido em voz alta. Em caso de falha, o texto é selecionado para que a pessoa possa apertar Ctrl+C ou Cmd+C.
Hook React
useCopyToClipboard
Retorna o estado e uma função de cópia. O timer é limpo na desmontagem, então nunca atualiza um componente removido.
Texto formatado, imagens e o evento copy
Copiar HTML com fallback em texto simples
Cada tipo MIME é um Blob. O destino da colagem escolhe o formato mais rico que entende.
Adicionar uma linha de fonte às cópias normais
Use com moderação. Mudar o que as pessoas copiam pode irritá-las, então limite isso a citações ou código, onde uma fonte ajuda.
Erros e suas causas
Quando a cópia falha
O que você vê
Causa provável
Solução
navigator.clipboard é undefined
Página servida por HTTP simples
Sirva por HTTPS, ou teste em localhost
NotAllowedError
Sem gesto do usuário, ou a aba não está em foco
Chame dentro do handler de clique
NotAllowedError dentro de um iframe
A Permissions Policy bloqueia clipboard-write
Adicione allow="clipboard-write" no iframe
Cópia de imagem rejeitada
Tipo MIME não suportado
Converta para PNG e verifique ClipboardItem.supports()
Copiado
Falhou
Copiar
Copiar texto formatado
Copiado para a área de transferência
A cópia falhou. Selecione o texto e pressione Ctrl+C ou Cmd+C.
Experimente
Botões de copiar para texto simples e HTML formatado, com uma caixa de colagem para conferir o resultado.