← All Pull Requests

Copy button: use the conventional double-square icon instead of the word #6

Closed opened by Ray 2026-09-02

John: "usually there's a nice copy to clipboard button used out there in the wild of the double square".

Swaps the word copy on the ref/handle strip for the conventional two-overlapping-squares glyph, and the confirmation from the word copied to a checkmark.

Why an inline SVG and not ⧉

A unicode glyph would be one character, but the existing ⛶ in card-fill-btn already renders as a tofu box in some headless captures on this container, and this button has to read at 13px in a slim panel. card-fill-btn is inline SVG for the same reason, so this matches it: viewBox="0 0 24 24", stroke="currentColor", stroke-width="2".

Icons are hoisted to two consts next to legacyCopy rather than rebuilt per card.

Unchanged

Still copies the whole reference (#158 hero-final), still hover-revealed, still stopPropagation so it never opens the shot, still falls back to legacyCopy in a sandboxed frame.

Verified

  • node --check on the main script block: OK
  • cargo build --release: clean, 7 warnings, identical to baseline
  • Rendered in a real headless browser against a scratch broker: #1 hero-footprint ⧉ lays out correctly at 3x DPR

Based on 0.28.4. Not merging this myself, adom-shotlog is yours.

Diff Skip to comments (1)

--- a/src/html/index.html+++ b/src/html/index.html@@ -1,2125 +1,2141 @@⋯ 257 unchanged lines ⋯   font: 600 10.5px/1.3 'JetBrains Mono', monospace; color: var(--text3); } .card-refbar .rb-ref { letter-spacing: .2px; } /* copy button (Ray, PR #5): hover-revealed like ⛶, never on the thumbnail */-.card-refbar .rb-copy { margin-left: 4px; padding: 0 5px; border-radius: 5px; cursor: pointer;+.card-refbar .rb-copy svg { width: 13px; height: 13px; display: block; }+.card-refbar .rb-copy { margin-left: 4px; padding: 2px 4px; border-radius: 5px; cursor: pointer;+  display: inline-flex; align-items: center; justify-content: center;   font: inherit; line-height: 1.5; color: var(--text3); background: transparent;   border: 1px solid var(--border-muted); opacity: 0; transition: opacity .12s, color .12s, border-color .12s; } .shot-card:hover .card-refbar .rb-copy, .card-refbar .rb-copy:focus-visible { opacity: 1; }⋯ 713 unchanged lines ⋯   // sandboxed frame with no clipboard permission, which is where this viewer   // sometimes lives. Used only when navigator.clipboard is missing or rejects.   // (Ray, PR #5)+  // The two-overlapping-squares copy glyph everyone recognises (John: "usually+  // there's a nice copy to clipboard button used out there in the wild of the+  // double square"). Inline SVG rather than a unicode glyph like ⧉ on purpose:+  // the ⛶ in card-fill-btn already renders as tofu in some headless captures,+  // and this button has to read at 13px in a slim panel.+  const ICON_COPY = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" ' ++    'stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' ++    '<rect x="9" y="9" width="12" height="12" rx="2"/>' ++    '<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>';+  const ICON_DONE = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" ' ++    'stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' ++    '<polyline points="20 6 9 17 4 12"/></svg>';+   function legacyCopy(text, done) {     try {       const ta = document.createElement('textarea');⋯ 257 unchanged lines ⋯       // survives a handle being reused later. Untagged shots copy just "#158".       { const txt = '#' + e.id + (e.tag ? ' ' + e.tag : '');         const cp = document.createElement('button'); cp.className = 'rb-copy';-        cp.textContent = 'copy'; cp.setAttribute('aria-label', 'Copy ' + txt);+        cp.innerHTML = ICON_COPY; cp.setAttribute('aria-label', 'Copy ' + txt);         cp.setAttribute('data-tooltip', 'Copy "' + txt + '": paste it to your AI to mean exactly this shot.');         cp.addEventListener('click', function (ev) {           ev.stopPropagation();          // never let it open the shot           const done = function () {-            cp.textContent = 'copied'; cp.classList.add('done');-            setTimeout(function () { cp.textContent = 'copy'; cp.classList.remove('done'); }, 1200);+            cp.innerHTML = ICON_DONE; cp.classList.add('done');+            setTimeout(function () { cp.innerHTML = ICON_COPY; cp.classList.remove('done'); }, 1200);           };           if (navigator.clipboard && navigator.clipboard.writeText) {             navigator.clipboard.writeText(txt).then(done, function () { legacyCopy(txt, done); });⋯ 869 unchanged lines ⋯ </script> </body> </html>+

Comments

John Lauer · 1mo ago

Applied verbatim in 0.28.5 (adom-wiki pkg update adom/adom-shotlog): the double-square SVG at 13px, the checkmark on success, icons hoisted to consts beside legacyCopy. Verified in pup on a tagged shot: squares at rest, checkmark plus .done on click, back to squares after 1.2s, the click never opens the shot, aria-label intact. Closing now that it is shipped. Thanks.

Log in to comment.