Copy Pill
One-click copy for a snippet, command or address
Running live from https://fun.whitneys.co,
cross-origin and sandboxed.
Put it on your site
<iframe
src="https://fun.whitneys.co/g/copy-pill"
width="420"
height="90"
title="Copy Pill"
sandbox="allow-scripts allow-popups-to-escape-sandbox"
allow="clipboard-write"
loading="lazy"
style="border:0"></iframe>
An iframe, not a script tag -- so this gadget cannot touch the page you paste it into, and neither can we. Your settings above are baked into the URL.
Optional: let it resize itself to fit
<script>
addEventListener('message', function (e) {
var d = e.data;
if (!d || d.type !== 'fwf:height') return;
if (typeof d.height !== 'number' || !isFinite(d.height)) return;
document.querySelectorAll('iframe').forEach(function (f) {
// Identity by source window, not by origin -- sandboxed frames report
// their origin as "null". Do not "fix" this into an origin check.
if (f.contentWindow !== e.source) return;
f.style.height = Math.max(40, Math.min(2000, Math.ceil(d.height))) + 'px';
});
});
</script>
The whole thing
Raw fileEvery gadget is one file, and this is it -- all 3.2 kB. Take it, change it, ship it. Just keep the credit.
Show source
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<script type="application/json" id="gadget-manifest">
{
"name": "Copy Pill",
"tagline": "One-click copy for a snippet, command or address",
"category": "tools",
"tags": ["clipboard", "code", "utility"],
"author": "rwhitney",
"background": "dark",
"size": { "w": 420, "h": 90, "resizable": true },
"config": {
"value": { "type": "text", "label": "Text to copy", "max": 80, "default": "npm create volt@latest" },
"accent": { "type": "color", "label": "Accent", "default": "#66D9EF" },
"mono": { "type": "bool", "label": "Monospace", "default": true }
},
"permissions": ["clipboard"]
}
</script>
<style>
html, body {
margin: 0; height: 100%;
display: grid; place-items: center;
background: transparent; color: #F8F8F2;
font: 15px/1.4 ui-sans-serif, system-ui, sans-serif;
overflow: hidden;
}
#pill {
display: flex; align-items: center; gap: 12px;
max-width: 92%;
padding: 12px 12px 12px 18px;
border: 1px solid rgb(248 248 242 / 0.18);
border-radius: 999px;
background: rgb(248 248 242 / 0.04);
}
#value {
flex: 1; min-width: 0;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
color: #F8F8F2;
}
#value.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
#btn {
flex: none; font: inherit; font-size: 13px; font-weight: 700;
padding: 7px 16px; border-radius: 999px; cursor: pointer;
border: 1px solid var(--accent, #66D9EF);
background: transparent; color: var(--accent, #66D9EF);
transition: background 120ms ease;
}
#btn:hover { background: rgb(255 255 255 / 0.07); }
#btn:focus-visible { outline: 2px solid var(--accent, #66D9EF); outline-offset: 2px; }
#btn.done { background: var(--accent, #66D9EF); color: #14150F; }
</style>
</head>
<body>
<div id="pill">
<span id="value"></span>
<button id="btn" type="button">Copy</button>
</div>
<script>
(function () {
var cfg = window.gadget ? window.gadget.config : {};
var text = cfg.value || 'npm create volt@latest';
var el = document.getElementById('value');
var btn = document.getElementById('btn');
el.textContent = text; // text, never markup
if (cfg.mono !== false) el.classList.add('mono');
document.documentElement.style.setProperty('--accent', cfg.accent || '#66D9EF');
btn.setAttribute('aria-label', 'Copy to clipboard');
btn.addEventListener('click', function () {
// Needs the "clipboard" permission, which this gadget declares. Both the
// sandbox Permissions-Policy and the embedding page's allow attribute
// have to grant clipboard-write or this fails -- and failing is fine.
var done = function () {
btn.textContent = 'Copied';
btn.classList.add('done');
setTimeout(function () {
btn.textContent = 'Copy';
btn.classList.remove('done');
}, 1400);
};
var fail = function () {
btn.textContent = 'Blocked';
setTimeout(function () { btn.textContent = 'Copy'; }, 1400);
};
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(text).then(done, fail);
} else {
fail();
}
});
})();
</script>
</body>
</html>