demo · v133
Async screenshot copy — long render, user-gesture-bound copy
A user clicks "copy chart as image". Drawing the chart takes 700ms. Before 133, you had to await the Blob and then call clipboard.write — but by then the user gesture had expired and the call failed. Pass a promise for the Blob to new ClipboardItem: the user gesture is captured up front, the image is generated in the background.
the code
// Before 133:
button.addEventListener("click", async () => {
const blob = await renderBigChart(); // 700ms — user gesture lost
await navigator.clipboard.write([
new ClipboardItem({ "image/png": blob }),
]);
});
// After 133:
button.addEventListener("click", () => {
navigator.clipboard.write([
new ClipboardItem({
"image/png": renderBigChart(), // promise! user gesture preserved
}),
]);
});
Same change applies to text/plain: new ClipboardItem({ "text/plain": fetchAsyncText() }). The browser awaits the promise on the gesture's behalf, so the clipboard write is treated as user-initiated even when the data resolves seconds later. The 133 update also accepts a plain DOMString directly — new ClipboardItem({ "text/plain": "hi" }) — instead of forcing a Blob/Promise dance for simple text.