General · astro-ui · Clipboard

ClipboardJS

Icon-first copy-to-clipboard trigger with copied-state check.

Clipboard renders an icon-first trigger button carrying its value in data-aui-clipboard. On success the copy icon swaps to a green check and a polite live region confirms. Ships zero JS by default — wire it app-side, or set auto to opt into a ~10-line built-in handler using the async Clipboard API. onlyIcon renders a square icon-only trigger for code blocks.

Features

  • Copy icon swaps to a green check when copied
  • onlyIcon square trigger for code blocks and toolbars
  • Zero-JS core: value travels in data-aui-clipboard
  • auto mode adds a tiny built-in handler (no hydration)
  • Polite live-region copy feedback
  • 3 trigger styles, 2 sizes, disabled state

Usage

---
import { Clipboard } from "astro-ui";
---

<Clipboard value="npm install astro-ui" auto />

<!-- or wire it yourself -->
<Clipboard value="npx astro add" />
<script>
  // read data-aui-clipboard and call the async clipboard API
</script>

Demos

Icon trigger

Click either — the copy icon swaps to a green check for 1.5s.

<Clipboard value="npm install astro-ui" auto />

<!-- icon=false falls back to a text-only trigger -->
<Clipboard value="npm install astro-ui" auto icon={false} />

Icon only

The accessible name derives from the value: aria-label="Copy npx astro add".

<Clipboard value="npx astro add" auto onlyIcon />
<Clipboard value="npx astro add" auto onlyIcon variant="soft" />
<Clipboard value="npx astro add" auto onlyIcon variant="ghost" />

<!-- accessible name derives from the value: aria-label="Copy npx astro add" -->

Variants

<Clipboard value="outline" auto variant="outline" label="Outline" />
<Clipboard value="ghost" auto variant="ghost" label="Ghost" />
<Clipboard value="soft" auto variant="soft" label="Soft" />

Sizes

<Clipboard value="small command" auto size="sm" />
<Clipboard value="regular command" auto size="md" />

Custom feedback

feedback= skips the text entirely — the check icon alone confirms.

<Clipboard
  value="pnpm add astro-ui"
  auto
  feedback="Install command copied"
/>

<!-- feedback={null} hides the live-region text entirely —
     the icon swap alone carries the confirmation -->
<Clipboard value="pnpm add astro-ui" auto feedback={null} />

Disabled

<Clipboard value="locked" auto disabled label="Copy" />
<Clipboard value="locked" auto disabled onlyIcon />

Manual wiring (zero JS)

This instance ships no script — the docs page wires data-aui-clipboard globally, exactly as the copy source shows.

<Clipboard value="npx astro add" />

<script>
  document.addEventListener("click", (event) => {
    const btn = event.target.closest("[data-aui-clipboard]");
    if (!btn) return;
    navigator.clipboard?.writeText(btn.dataset.auiClipboard);
  });
</script>

In a code block

npm install astro-ui
<div class="aui-code-pill">
  <code>npm install astro-ui</code>
  <Clipboard value="npm install astro-ui" auto onlyIcon variant="ghost" size="sm" />
</div>

<style>
  .aui-code-pill {
    display: inline-flex; align-items: center; gap: 0.5rem;
    padding: 0.375rem 0.375rem 0.375rem 0.75rem;
    background: var(--ui-muted); border-radius: var(--ui-radius-md);
    font-family: var(--ui-font-mono); font-size: var(--ui-text-sm);
  }
</style>

API

Props

PropTypeDefaultDescription
valuestringrequiredText placed on the clipboard.
labelstring"Copy"Trigger label (hidden when onlyIcon).
iconbooleantrueLead with the copy icon; swaps to a check when copied.
onlyIconbooleanfalseSquare icon-only trigger; aria-label derives from value.
autobooleanfalseOpt into the built-in clipboard handler.
feedbackstring"Copied!"Live-region success message.
variant"outline" | "ghost" | "soft""outline"Trigger style.
size"sm" | "md""md"Trigger scale.
classstring—Merged via cn(); Tailwind classes welcome.
idstring—Element id.
ariaLabelstring—Accessible name.

Accessibility

Implemented accessibility features — semantics, ARIA wiring, and keyboard behavior that ship with the component.

  • Copied confirmation is announced via role="status" with aria-live="polite"
  • Real button with an aria-label; icons aria-hidden

FAQ

Why is JS optional here?

The web platform has no script-free clipboard write, so the component keeps its core markup zero-JS and makes the (tiny) script opt-in via auto.

How does the copied state work?

The success handler toggles an is-copied class on the root for 1.5s; CSS swaps the copy icon for a green check. With manual wiring, toggle the class yourself.

Is the icon-only trigger accessible?

Yes — it renders a real button whose aria-label defaults to Copy <value> (override with ariaLabel), and copy success is announced via the live region.

Changelog

Version history mentioning Clipboard.

v0.1.0 — 2026-11-11
added
  • General (7): Button, ButtonGroup, Command, Carousel, Clipboard, Kbd, Link.