You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by gs...@apache.org on 2026/10/12 03:33:33 UTC

(tooling-llmao) 02/08: models: copy the model id from an icon, not a "Copy" link

This is an automated email from the ASF dual-hosted git repository.

gstein pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-llmao.git

commit 28a84862410b8be50d9da5c350e020664287b97d
Author: Greg Stein <gs...@gmail.com>
AuthorDate: Sun Oct 11 21:33:35 2026 -0500

    models: copy the model id from an icon, not a "Copy" link
    
    The word sat on the card's heading line beside the name and the id and
    read as a third piece of text. It is now a clipboard icon with a title
    and a matching aria-label, and turns into a check mark for a moment
    when the copy succeeds.
    
    Co-authored-by: Claude Opus 5.5 <no...@anthropic.com>
---
 static/css/llmao.css       | 12 ++++++++++++
 static/js/llmao.js         | 12 ++++++++++--
 templates/models.ezt       |  7 ++++---
 tests/test_pages_models.py | 14 ++++++++++++++
 4 files changed, 40 insertions(+), 5 deletions(-)

diff --git a/static/css/llmao.css b/static/css/llmao.css
index 543f02b..d092263 100644
--- a/static/css/llmao.css
+++ b/static/css/llmao.css
@@ -28,6 +28,18 @@ body {
 .models-page .model-id {
   font-size: 0.85rem;
 }
+/* An icon, not a link: muted until it is pointed at. */
+.models-page .model-copy {
+  color: var(--bs-secondary-color);
+  line-height: 1;
+}
+.models-page .model-copy:hover,
+.models-page .model-copy:focus-visible {
+  color: var(--bs-body-color);
+}
+.models-page .model-copy.model-copy-done {
+  color: var(--bs-success);
+}
 /* Privacy is a full sentence in its own block. Color only reinforces it. */
 .models-page .model-privacy {
   display: flex;
diff --git a/static/js/llmao.js b/static/js/llmao.js
index b5d01c1..e627319 100644
--- a/static/js/llmao.js
+++ b/static/js/llmao.js
@@ -66,10 +66,18 @@ document.addEventListener("DOMContentLoaded", function () {
     btn.addEventListener("click", function () {
       var text = btn.getAttribute("data-copy") || "";
       if (!text || !navigator.clipboard) return;
+      var icon = btn.querySelector(".bi");
+      var label = btn.getAttribute("title") || "";
       navigator.clipboard.writeText(text).then(function () {
-        btn.textContent = "Copied";
+        if (icon) icon.className = "bi bi-check-lg";
+        btn.classList.add("model-copy-done");
+        btn.setAttribute("title", "Copied");
+        btn.setAttribute("aria-label", "Copied");
         setTimeout(function () {
-          btn.textContent = "Copy";
+          if (icon) icon.className = "bi bi-clipboard";
+          btn.classList.remove("model-copy-done");
+          btn.setAttribute("title", label);
+          btn.setAttribute("aria-label", label);
         }, 1500);
       });
     });
diff --git a/templates/models.ezt b/templates/models.ezt
index fb749cb..50ea739 100644
--- a/templates/models.ezt
+++ b/templates/models.ezt
@@ -72,9 +72,10 @@
             <div class="d-flex align-items-baseline flex-wrap gap-2">
               <h2 class="h5 mb-0">[models.display_name]</h2>
               <code class="model-id">[models.model_name]</code>
-              <button type="button" class="btn btn-link btn-sm p-0 js-copy-model"
-                      aria-label="Copy the ID [models.model_name]"
-                      data-copy="[models.model_name]">Copy</button>
+              <button type="button" class="btn btn-link btn-sm p-0 model-copy js-copy-model"
+                      title="Copy [models.model_name] to the clipboard"
+                      aria-label="Copy [models.model_name] to the clipboard"
+                      data-copy="[models.model_name]"><i class="bi bi-clipboard" aria-hidden="true"></i></button>
             </div>
             [if-any models.privacy]
             <div class="model-privacy model-privacy-[models.privacy_key] mt-2">
diff --git a/tests/test_pages_models.py b/tests/test_pages_models.py
index 69e6b3f..b0fb0a5 100644
--- a/tests/test_pages_models.py
+++ b/tests/test_pages_models.py
@@ -515,6 +515,20 @@ def test_every_state_has_a_badge_class():
     assert pages._badge_class(HEALTHY, routed=False) == "text-bg-warning"
 
 
+def test_card_copies_the_model_id_from_an_icon():
+    pages = _app()
+    rows = pages.model_catalog_rows(_fleet(_server("gemma")), [_catalog("gemma")])
+    out = _render(rows)
+    button = out[out.index("js-copy-model") :]
+    button = button[: button.index("</button>")]
+    assert 'title="Copy gemma to the clipboard"' in button
+    assert 'aria-label="Copy gemma to the clipboard"' in button
+    assert 'data-copy="gemma"' in button
+    assert "bi-clipboard" in button
+    # The icon is the whole content; the name is in the attributes.
+    assert button.rstrip().endswith("</i>")
+
+
 def test_mixed_card_and_unavailable_card():
     pages = _app()
     box = _server("gemma")


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org