KTUIKTUI
KTUIKTUI
ComponentsDocsStudio

Getting Started

IntroductionInstallationApproachThemingJavaScriptTypeScriptDark modeRTLReferencesChangelog - v1.2.5Metronic TemplatePopular

Components

AccordionAvatarAlertBadgeBreadcrumbButtonCardCarouselNewClipboardNewCheckboxCollapseDatatableUpdateContext MenuNewDismissDrawerDropdownImage InputInputInput numberNewKbdLinkModalPaginationPin inputNewProgressRadio GroupRange SliderNewRatingNewReparentRepeaterNewScrollableScrollspyScrolltoSelectSeparatorSkeletonStepperStickySwitchTabsTextareaTheme SwitchToastTooltipToggleToggle GroupToggle PasswordTooltip
©2026 KtUI. All rights reserved.
A project by Keenthemes
Docs
Tailwind Clipboard

Tailwind Clipboard

The Clipboard component provides declarative copy/cut-to-clipboard behavior (native Clipboard API + fallback) using `data-kt-clipboard*` attributes.

Examples

Copy value (input)

<div class="max-w-md w-full flex flex-col gap-3">
  <input
    id="ktui-clipboard-copy-value-input"
    type="text"
    class="kt-input"
    value="Hello from input"
  />
  <p class="text-end">
    <button
      id="ktui-clipboard-btn-copy-value"
      type="button"
      class="kt-btn kt-btn-primary kt-btn-sm"
      data-kt-clipboard="true"
      data-kt-clipboard-target="#ktui-clipboard-copy-value-input"
      data-kt-clipboard-action="copy"
    >
      Copy value
    </button>
  </p>
  <script>
    (function () {
      var btn = document.getElementById("ktui-clipboard-btn-copy-value");
      if (!btn) return;

      if (!btn.dataset.originalText) {
        btn.dataset.originalText = btn.textContent || "Copy value";
      }

      btn.addEventListener(
        "click",
        function () {
          btn.textContent = btn.dataset.originalText || "Copy value";
        },
        { capture: true },
      );

      btn.addEventListener("kt.clipboard.success", function () {
        btn.textContent = "Copied";
      });

      btn.addEventListener("kt.clipboard.error", function () {
        btn.textContent = "Error";
      });
    })();
  </script>
</div>

Copy value (inline)

<div class="inline-flex items-center gap-3">
  <input
    id="ktui-clipboard-inline-input"
    type="text"
    class="kt-input shrink-0"
    style="width: 22rem; min-width: 22rem"
    value="npm i @keenthemes/ktui"
  /><button
    id="ktui-clipboard-btn-inline"
    type="button"
    class="kt-btn kt-btn-outline kt-btn-sm"
    data-kt-clipboard="true"
    data-kt-clipboard-target="#ktui-clipboard-inline-input"
    data-kt-clipboard-action="copy"
  >
    Copy
  </button>
  <script>
    (function () {
      var btn = document.getElementById("ktui-clipboard-btn-inline");
      if (!btn) return;

      if (!btn.dataset.originalText) {
        btn.dataset.originalText = btn.textContent || "Copy";
      }

      btn.addEventListener(
        "click",
        function () {
          btn.textContent = btn.dataset.originalText || "Copy";
        },
        { capture: true },
      );

      btn.addEventListener("kt.clipboard.success", function () {
        btn.textContent = "Copied";
      });

      btn.addEventListener("kt.clipboard.error", function () {
        btn.textContent = "Error";
      });
    })();
  </script>
</div>

Predefined text (text wins over target)

<div class="max-w-md w-full flex flex-col gap-3">
  <div id="ktui-clipboard-predefined-target" class="kt-alert kt-alert-info">
    This target exists, but the predefined text wins.
  </div>
  <p class="text-end">
    <button
      id="ktui-clipboard-btn-predefined"
      type="button"
      class="kt-btn kt-btn-primary kt-btn-sm"
      data-kt-clipboard="true"
      data-kt-clipboard-text="Predefined clipboard text"
      data-kt-clipboard-target="#ktui-clipboard-predefined-target"
      data-kt-clipboard-action="copy"
    >
      Copy predefined text
    </button>
  </p>
  <script>
    (function () {
      var btn = document.getElementById("ktui-clipboard-btn-predefined");
      if (!btn) return;

      if (!btn.dataset.originalText) {
        btn.dataset.originalText = btn.textContent || "Copy predefined text";
      }

      btn.addEventListener(
        "click",
        function () {
          btn.textContent = btn.dataset.originalText || "Copy predefined text";
        },
        { capture: true },
      );

      btn.addEventListener("kt.clipboard.success", function () {
        btn.textContent = "Copied";
      });

      btn.addEventListener("kt.clipboard.error", function () {
        btn.textContent = "Error";
      });
    })();
  </script>
</div>

Predefined text (icon swap)

<div class="flex items-center justify-between gap-3 max-w-md w-full">
  <div class="text-sm text-foreground" id="ktui-clipboard-icon-swap-text">
    npm install @keenthemes/ktui
  </div>
  <button
    id="ktui-clipboard-btn-icon-swap"
    type="button"
    class="kt-btn kt-btn-outline kt-btn-sm inline-flex items-center gap-2"
    data-kt-clipboard="true"
    data-kt-clipboard-text="npm install @keenthemes/ktui"
    data-kt-clipboard-action="copy"
  >
    <span data-role="icon-default" class="inline-flex"
      ><svg
        class="size-4"
        xmlns="http://www.w3.org/2000/svg"
        width="24"
        height="24"
        viewBox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        stroke-width="2"
        stroke-linecap="round"
        stroke-linejoin="round"
      >
        <rect width="8" height="4" x="8" y="2" rx="1" ry="1"></rect>
        <path
          d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"
        ></path></svg></span
    ><span data-role="icon-success" class="hidden text-primary inline-flex"
      ><svg
        class="size-4"
        xmlns="http://www.w3.org/2000/svg"
        width="24"
        height="24"
        viewBox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        stroke-width="2"
        stroke-linecap="round"
        stroke-linejoin="round"
      >
        <polyline points="20 6 9 17 4 12"></polyline></svg></span
    ><span data-role="text">Copy</span>
  </button>
  <script>
    (function () {
      var btn = document.getElementById("ktui-clipboard-btn-icon-swap");
      if (!btn) return;

      var defaultIcon = btn.querySelector('[data-role="icon-default"]');
      var successIcon = btn.querySelector('[data-role="icon-success"]');
      var textEl = btn.querySelector('[data-role="text"]');

      var reset = function () {
        if (defaultIcon) defaultIcon.classList.remove("hidden");
        if (successIcon) successIcon.classList.add("hidden");
        if (textEl) textEl.textContent = "Copy";
      };

      btn.addEventListener("click", reset, { capture: true });

      btn.addEventListener("kt.clipboard.success", function () {
        if (defaultIcon) defaultIcon.classList.add("hidden");
        if (successIcon) successIcon.classList.remove("hidden");
        if (textEl) textEl.textContent = "Copied";
      });

      btn.addEventListener("kt.clipboard.error", function () {
        if (textEl) textEl.textContent = "Error";
      });
    })();
  </script>
</div>

Cut value (input/textarea only)

<div class="max-w-md w-full flex flex-col gap-3">
  <input
    id="ktui-clipboard-cut-input"
    type="text"
    class="kt-input"
    value="Cut me"
  />
  <p class="text-end">
    <button
      id="ktui-clipboard-btn-cut"
      type="button"
      class="kt-btn kt-btn-danger kt-btn-sm"
      data-kt-clipboard="true"
      data-kt-clipboard-target="#ktui-clipboard-cut-input"
      data-kt-clipboard-action="cut"
    >
      Cut value
    </button>
  </p>
  <script>
    (function () {
      var btn = document.getElementById("ktui-clipboard-btn-cut");
      if (!btn) return;

      if (!btn.dataset.originalText) {
        btn.dataset.originalText = btn.textContent || "Cut value";
      }

      btn.addEventListener(
        "click",
        function () {
          btn.textContent = btn.dataset.originalText || "Cut value";
        },
        { capture: true },
      );

      btn.addEventListener("kt.clipboard.success", function () {
        btn.textContent = "Copied";
      });

      btn.addEventListener("kt.clipboard.error", function () {
        btn.textContent = "Error";
      });
    })();
  </script>
</div>

Copy from arbitrary target

<div class="max-w-md w-full flex flex-col gap-3">
  <div id="ktui-clipboard-copy-target" class="kt-alert kt-alert-light">
    Copy target text content
  </div>
  <p class="text-end">
    <button
      id="ktui-clipboard-btn-copy-target"
      type="button"
      class="kt-btn kt-btn-primary kt-btn-sm"
      data-kt-clipboard="true"
      data-kt-clipboard-target="#ktui-clipboard-copy-target"
      data-kt-clipboard-action="copy"
    >
      Copy from target
    </button>
  </p>
  <script>
    (function () {
      var btn = document.getElementById("ktui-clipboard-btn-copy-target");
      if (!btn) return;

      if (!btn.dataset.originalText) {
        btn.dataset.originalText = btn.textContent || "Copy from target";
      }

      btn.addEventListener(
        "click",
        function () {
          btn.textContent = btn.dataset.originalText || "Copy from target";
        },
        { capture: true },
      );

      btn.addEventListener("kt.clipboard.success", function () {
        btn.textContent = "Copied";
      });

      btn.addEventListener("kt.clipboard.error", function () {
        btn.textContent = "Error";
      });
    })();
  </script>
</div>

Code block

<div class="max-w-xl w-full">
  <div class="relative">
    <pre
      id="ktui-clipboard-code-block"
      class="kt-code-block overflow-auto rounded-lg p-4 bg-base-200"
    ><code>// Click to copy this block (plain text)
const answer = 42;
console.log(answer);</code></pre>
    <p class="text-end mt-3">
      <button
        id="ktui-clipboard-btn-code"
        type="button"
        class="kt-btn kt-btn-primary kt-btn-sm"
        data-kt-clipboard="true"
        data-kt-clipboard-target="#ktui-clipboard-code-block"
        data-kt-clipboard-action="copy"
      >
        Copy code
      </button>
    </p>
    <script>
      (function () {
        var btn = document.getElementById("ktui-clipboard-btn-code");
        if (!btn) return;

        if (!btn.dataset.originalText) {
          btn.dataset.originalText = btn.textContent || "Copy code";
        }

        btn.addEventListener(
          "click",
          function () {
            btn.textContent = btn.dataset.originalText || "Copy code";
          },
          { capture: true },
        );

        btn.addEventListener("kt.clipboard.success", function () {
          btn.textContent = "Copied";
        });

        btn.addEventListener("kt.clipboard.error", function () {
          btn.textContent = "Error";
        });
      })();
    </script>
  </div>
</div>

Tooltip feedback

<div class="max-w-md w-full">
  <div class="flex items-center gap-2">
    <input
      type="hidden"
      id="ktui-clipboard-tooltip-input"
      value="npm install @keenthemes/ktui"
    /><button
      id="ktui-clipboard-btn-tooltip"
      type="button"
      class="kt-btn kt-btn-primary kt-btn-sm"
      data-kt-clipboard="true"
      data-kt-clipboard-target="#ktui-clipboard-tooltip-input"
      data-kt-clipboard-action="copy"
      data-kt-tooltip="true"
      data-kt-tooltip-placement="top"
    >
      <span>Copy command</span
      ><span
        data-role="tooltip"
        data-kt-tooltip-content="true"
        class="kt-tooltip"
        >Copy</span
      ></button
    ><span class="text-sm text-muted-foreground"
      ><span class="font-mono">npm install @keenthemes/ktui</span></span
    >
    <script>
      (function () {
        var btn = document.getElementById("ktui-clipboard-btn-tooltip");
        if (!btn) return;
        var tooltip = btn.querySelector('[data-role="tooltip"]');
        var setText = function (text) {
          if (!tooltip) return;
          tooltip.textContent = text;
          clearTimeout(setText._t);
          setText._t = setTimeout(function () {
            tooltip.textContent = "Copy";
          }, 1200);
        };

        btn.addEventListener("kt.clipboard.success", function () {
          setText("Copied");
        });
        btn.addEventListener("kt.clipboard.error", function () {
          setText("Error");
        });
      })();
    </script>
  </div>
</div>

Component API

Options

These data attributes configure Clipboard triggers during auto-initialization.

NameTypeDefaultDescription
data-kt-clipboardbooleanfalsePresence enables auto-initialization on the trigger element.
data-kt-clipboard-textstring

Selectors

NameDescription
data-kt-clipboardUsed to auto-initialize KTClipboard on the trigger element.
data-kt-clipboard-targetUsed to resolve the element whose content should be copied/cut.

Methods

Use the KTClipboard API methods to control clipboard instances.

MethodDescription
KTClipboard.init()Initializes all elements with data-kt-clipboard.
KTClipboard.createInstances()Initializes Clipboard triggers that were added to the DOM after load.
KTClipboard.getInstance(element)Returns the instance for a trigger element, or null.
import {
  KTClipboard,
  type KTClipboardConfigInterface,
  type KTClipboardInterface,
} from '@keenthemes/ktui';
 
const el = document.querySelector<HTMLElement>('[data-kt-clipboard]');
if (!el) throw new Error('Missing clipboard trigger');
 
// Get existing instance
const instance: KTClipboardInterface | null = KTClipboard.getInstance(el);
 
// Or create one with typed config
const options: KTClipboardConfigInterface = {
  target: '#my_input',
  text: 'Fallback (if configured via attributes)'


Events

Clipboard dispatches DOM events on the trigger element.

EventDescription
kt.clipboard.successFired when a copy/cut succeeds. event.detail.payload includes action, text, and target.
kt.clipboard.errorFired when an error occurs (missing selector, invalid cut target, empty text, or clipboard write failure). event.detail.payload includes error.
const el = document.querySelector('[data-kt-clipboard]');
const clipboard = KTClipboard.getInstance(el);
 
el?.addEventListener('kt.clipboard.success', (e) => {
  console.log('Clipboard success:', e.detail.payload);
});
 
el?.addEventListener('kt.clipboard.error', (e) => {
  console.error('Clipboard error:', e.detail.payload);
});

TypeScript

Import KTClipboard and its types from @keenthemes/ktui:

import { KTClipboard, type KTClipboardInterface } from '@keenthemes/ktui';
 
const el = document.querySelector<HTMLElement>('[data-kt-clipboard]');
if (!el) return;
 
const instance: KTClipboardInterface | null = KTClipboard.getInstance(el);
if (instance) {
  // Usually you interact via the UI trigger click.
  instance.on('kt.clipboard.success', (payload) => {
    console.log('Copied!', payload);
  });
}
PreviouseCarouselNextCheckbox

On This Page

  • Examples
    • Copy value (input)
    • Copy value (inline)
    • Predefined text (text wins over target)
    • Predefined text (icon swap)
    • Cut value (input/textarea only)
    • Copy from arbitrary target
    • Code block
    • Tooltip feedback
  • Component API
    • Options
    • Selectors
    • Methods
    • Events
  • TypeScript
""
Static text to copy. If the attribute is present, it takes precedence over data-kt-clipboard-target.
data-kt-clipboard-targetstring""CSS selector for the source element. For input/textarea it copies .value; otherwise it copies .textContent.
data-kt-clipboard-action"copy" | "cut""copy"The clipboard action. cut is only supported when the target resolves to an input/textarea.
data-kt-clipboard-copied-classstring""Optional class toggled on the trigger after success.
data-kt-clipboard-success-eventstring"kt.clipboard.success"Custom success event name (dispatched on the trigger).
data-kt-clipboard-error-eventstring"kt.clipboard.error"Custom error event name (dispatched on the trigger).
KTClipboard.getOrCreateInstance(element, config)Returns an existing instance or creates one with config.
dispose()Removes the instance from the trigger and cleans up listeners.
on(eventName, handler) / off(eventName, eventId)Registers/unregisters custom events.
getOption(name)Returns the instance option value.
getElement()Returns the trigger element.
,
action: 'copy',
};
const clipboard = KTClipboard.getOrCreateInstance(el, options);