Add clipboard copy functionality that works over HTTP (#4446)

This commit is contained in:
Shuchang Zheng
2026-01-14 11:53:12 -08:00
committed by GitHub
parent e617ef9924
commit fed12acfc9
6 changed files with 73 additions and 39 deletions

View File

@@ -1,25 +1,39 @@
/**
* Progressively enhanced text copying
* Progressively enhanced text copying with HTTP fallback
* https://web.dev/patterns/clipboard/copy-text
*
* Uses navigator.clipboard when in a secure context (HTTPS),
* falls back to textarea + execCommand for HTTP contexts.
*/
async function copyText(text: string): Promise<void> {
if ("clipboard" in navigator) {
return navigator.clipboard.writeText(text);
} else {
const textArea = document.createElement("textarea");
textArea.value = text;
textArea.style.opacity = "0";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
const success = document.execCommand("copy");
document.body.removeChild(textArea);
if (success) {
return Promise.resolve();
} else {
return Promise.reject();
async function copyText(text: string): Promise<boolean> {
// Prefer navigator.clipboard when in a secure context
if (window.isSecureContext && navigator.clipboard?.writeText) {
try {
await navigator.clipboard.writeText(text);
return true;
} catch (err) {
// Fall through to fallback
}
}
// Fallback for HTTP or when clipboard API fails
const textArea = document.createElement("textarea");
textArea.value = text;
textArea.style.position = "fixed";
textArea.style.opacity = "0";
textArea.style.left = "-9999px";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
// execCommand is deprecated but remains the only option for HTTP contexts
// where navigator.clipboard is unavailable. Browser support remains strong.
const success = document.execCommand("copy");
return success;
} finally {
document.body.removeChild(textArea);
}
}
export { copyText };