1 CopyButton
L4stIdi0t edited this page 2026-10-01 17:34:52 +02:00

CopyButton

Copies text to the clipboard and says whether it worked: the copy icon turns away, a check springs in and draws its own stroke (a cross draws and shakes), a tint blooms across the button, and after resetAfter it all settles back.

Icon-only by default; showLabel adds the text, which rolls up to the new word while the button eases to its width. The result is also announced through a polite live region, because an icon swap is silent. Uses the async Clipboard API, and falls back to execCommand('copy') where that is missing — a plain-http page on a LAN address is not a secure context, and there navigator.clipboard is undefined.

Actions · two-way: bind:status · keyboard contract

<script lang="ts">
	import { CopyButton } from '@l4st/driftwood';
</script>
Light Dark
copy-button copy-button in dark mode

Props

Prop Type Default What it does
value required string | (() => string | Promise<string>) — The text to copy, or a function that returns it at click time.
label string 'Copy' Accessible name, and the visible text with showLabel.
copiedLabel string 'Copied' Shown and announced after a successful copy.
failedLabel string 'Copy failed' Shown and announced when the clipboard refused.
showLabel boolean false Render the label next to the icon instead of an icon-only button.
resetAfter number 2000 Milliseconds before the icon returns to idle.
variant 'default' | 'secondary' | 'outline' | 'ghost' | 'destructive' 'ghost' Same variants as Button.
size 'default' | 'sm' | 'lg' | 'icon' — Same sizes as Button. Defaults to icon, or sm with showLabel.
status bind: CopyStatus 'idle' The current state, readable with bind:status.
onCopy (text: string) => void — Fires with the copied text after a successful copy.
onError (error: unknown) => void — Fires when the copy failed (permission denied, no clipboard, a throwing value).
class string — Merged with the component's own classes, last — so yours win.

Everything not listed above is spread onto the underlying element (HTMLButtonAttributes): aria-*, data-*, event handlers, and the rest of the native attributes.

Types

export type CopyStatus = 'idle' | 'copied' | 'failed';

Keyboard

Key Does
Enter / Space copy

Example

The markup behind the screenshot above, lifted from src/routes/shots/ — so it compiles, and it is exactly what produced the image.

<CopyButton value="nas-01.local" label="Copy hostname" />
<CopyButton value="nas-01.local" label="Copy hostname" status="copied" />
<CopyButton value="nas-01.local" label="Copy hostname" status="failed" />
<CopyButton value="nas-01.local" variant="outline" showLabel />
<CopyButton value="nas-01.local" variant="outline" showLabel status="copied" />

Notes

  • Insecure contexts. navigator.clipboard only exists on https and localhost. On a plain-http LAN address the button falls back to document.execCommand('copy'), which still works from a click.
  • Async value. A function returning a promise is awaited before the write. Safari ties clipboard access to the click, so a slow promise can be refused there and the button shows the failed state. Pass a string when you have one.
  • Name and status are separate. The accessible name stays label the whole time; "Copied" / "Copy failed" go to a polite live region next to the button. Read the state with bind:status or data-status.
  • It is type="button", so it never submits the form it sits in.

Actions · Button · ButtonGroup · Toggle · Menu · ContextMenu


← All components · Getting started · Theming · source