Component Library

← Back to gallery

Copy button

Category: Buttons · Tags: copy, clipboard, api-key, status, code

Test API key

demo_key_7Hq2Lx9Pv4RtW8nB

How to use it

Use beside a value people need to paste elsewhere, such as an API key, invite link or command. Show the value itself so it can still be read or selected by hand, and say what was copied. Don't use it for secrets that should stay masked until revealed; pair it with a reveal step instead. Replace the demo key with your real value and give each copy its own value id (the button's aria-controls points at it) when you place more than one on a page.

Accessibility

A native <button> named "Copy API key" (its visible word "Copy" is part of that name) writes the shown value with the Clipboard API; where that is unavailable or refused, it selects the text and tries the legacy copy command, and if that also fails it leaves the text selected and asks the user to press Ctrl+C or Cmd+C. The outcome is written into a role="status" line so screen reader users hear "API key copied." and focus never moves. The value is plain text under a visible caption, so it can also be read and selected by hand, and it wraps on narrow screens. Text is #0f172a on #f1f5f9 (16.30:1) for the value, #ffffff on #1d4ed8 (6.70:1) and #1e40af hover (8.72:1) for the button, and #166534 on #ffffff (7.13:1) for the status.

Source (copy-ready)

<div class="dcl-copybtn">
  <p class="dcl-copybtn__caption" id="dcl-copybtn-caption">Test API key</p>
  <div class="dcl-copybtn__row">
    <code class="dcl-copybtn__value" id="dcl-copybtn-value">demo_key_7Hq2Lx9Pv4RtW8nB</code>
    <button type="button" class="dcl-copybtn__button" aria-label="Copy API key" aria-controls="dcl-copybtn-value">Copy</button>
  </div>
  <p class="dcl-copybtn__status" role="status"></p>
</div>
<style>
.dcl-copybtn { max-width: 100%; font: inherit; color: #0f172a; background-color: #ffffff; }
.dcl-copybtn__caption { margin: 0 0 0.35rem; font-weight: 600; color: #0f172a; background-color: #ffffff; }
.dcl-copybtn__row { display: flex; flex-wrap: wrap; align-items: stretch; gap: 0.5rem; }
.dcl-copybtn__value { flex: 1 1 12rem; min-width: 0; padding: 0.6rem 0.75rem; border: 1px solid #94a3b8; border-radius: 0.5rem; overflow-wrap: anywhere; font-family: ui-monospace, Menlo, Consolas, monospace; color: #0f172a; background-color: #f1f5f9; }
.dcl-copybtn__button { min-height: 2.75rem; padding: 0 1.1rem; border: none; border-radius: 0.5rem; cursor: pointer; font: inherit; font-weight: 600; color: #ffffff; background-color: #1d4ed8; }
.dcl-copybtn__button:hover { color: #ffffff; background-color: #1e40af; }
.dcl-copybtn__button:focus-visible { outline: 2px solid #0f172a; outline-offset: 2px; }
.dcl-copybtn__status { min-height: 1.5em; margin: 0.4rem 0 0; color: #166534; background-color: #ffffff; }
</style>
<script>
(function () {
  document.querySelectorAll(".dcl-copybtn").forEach(function (root) {
    if (root.dataset.dclBound) { return; }
    root.dataset.dclBound = "true";
    var button = root.querySelector(".dcl-copybtn__button");
    var value = root.querySelector(".dcl-copybtn__value");
    var status = root.querySelector(".dcl-copybtn__status");
    if (!button || !value) { return; }
    function say(text) { if (status) { status.textContent = text; } }
    function fallback() {
      var copied = false;
      try {
        var range = document.createRange();
        range.selectNodeContents(value);
        var selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);
        copied = document.execCommand && document.execCommand("copy");
      } catch (error) {
        copied = false;
      }
      say(copied ? "API key copied." : "Key selected. Press Ctrl+C or Cmd+C to copy it.");
    }
    button.addEventListener("click", function () {
      var text = value.textContent.trim();
      say("");
      if (navigator.clipboard && window.isSecureContext) {
        navigator.clipboard.writeText(text).then(function () { say("API key copied."); }, fallback);
      } else {
        fallback();
      }
    });
  });
})();
</script>

Was this useful? Send feedback.