From 81b629d9537d5b692d739c4f4b696dfe89f7030a Mon Sep 17 00:00:00 2001 From: Yash Kumar Saini Date: Sun, 12 Jul 2026 09:58:16 +0530 Subject: [PATCH] feat(docs): add copy button to code blocks Adds a hover-revealed Copy button to every
 block in the docs
content area. Clicking it copies to clipboard via the Clipboard API
and flashes a green "Copied!" confirmation for 2 s.

The script is loaded only on doc pages via the `scripts` template
block, so landing and other page types are unaffected. No new
dependencies.

Closes https://github.com/huggingface/tau/issues/343
---
 website/assets/css/main.css     |  9 +++++++++
 website/assets/js/copy-code.js  | 33 +++++++++++++++++++++++++++++++++
 website/layouts/doc/single.html |  8 ++++++++
 3 files changed, 50 insertions(+)
 create mode 100644 website/assets/js/copy-code.js

diff --git a/website/assets/css/main.css b/website/assets/css/main.css
index 761685bcf..e906c8bd6 100644
--- a/website/assets/css/main.css
+++ b/website/assets/css/main.css
@@ -642,6 +642,15 @@ section{ padding:88px 0; }
 .docs-content pre code{
   background:none; border:none; padding:0; font-size:14px; line-height:1.7; color:inherit;
 }
+.copy-btn{
+  position:absolute; top:50%; right:10px; transform:translateY(-50%);
+  display:flex; align-items:center; justify-content:center;
+  width:30px; height:30px; padding:0;
+  color:rgba(215,224,244,.55); background:rgba(255,255,255,.07);
+  border:1px solid rgba(255,255,255,.14); border-radius:5px;
+  cursor:pointer;
+}
+.copy-btn--copied{ color:var(--green); border-color:var(--green); }
 .docs-content blockquote{
   margin:0 0 18px; padding:2px 20px; border-left:2px solid var(--grid-strong); color:var(--ink-soft);
 }
diff --git a/website/assets/js/copy-code.js b/website/assets/js/copy-code.js
new file mode 100644
index 000000000..bd9397a85
--- /dev/null
+++ b/website/assets/js/copy-code.js
@@ -0,0 +1,33 @@
+var parser = new DOMParser();
+
+function makeSVG(str) {
+  return parser.parseFromString(str, "image/svg+xml").documentElement;
+}
+
+var COPY_SVG = '';
+var CHECK_SVG = '';
+
+document.addEventListener("DOMContentLoaded", function () {
+  document.querySelectorAll(".docs-content pre").forEach(function (pre) {
+    var btn = document.createElement("button");
+    btn.className = "copy-btn";
+    btn.setAttribute("aria-label", "Copy code to clipboard");
+    btn.appendChild(makeSVG(COPY_SVG));
+
+    pre.style.position = "relative";
+    pre.appendChild(btn);
+
+    btn.addEventListener("click", function () {
+      var code = pre.querySelector("code");
+      var text = code ? code.innerText : pre.innerText;
+      navigator.clipboard.writeText(text).then(function () {
+        btn.replaceChildren(makeSVG(CHECK_SVG));
+        btn.classList.add("copy-btn--copied");
+        setTimeout(function () {
+          btn.replaceChildren(makeSVG(COPY_SVG));
+          btn.classList.remove("copy-btn--copied");
+        }, 2000);
+      });
+    });
+  });
+});
diff --git a/website/layouts/doc/single.html b/website/layouts/doc/single.html
index c48e68465..0be84123d 100644
--- a/website/layouts/doc/single.html
+++ b/website/layouts/doc/single.html
@@ -15,3 +15,11 @@ 

{{ .Title }}

{{ end }} + +{{ define "scripts" }} +{{ $copyJs := resources.Get "js/copy-code.js" }} +{{ if hugo.IsProduction }} + {{ $copyJs = $copyJs | js.Build | minify | fingerprint }} +{{ end }} + +{{ end }}