build69
build69  /  Components  /  Buttons & Actions  /  CopyButton

CopyButton

v1.0.15Updated 19 Oct 2026

Button that copies a value to the clipboard — a plain string or a sync/async producer resolved at click time. Writes via navigator.clipboard with a hidden-textarea/execCommand fallback, flips to a check icon for a config

Preview

Live · 12 stories
DefaultOpen ↗
▸Why this is recommendedcopyclipboardbuttonsnippet+3

The default, out-of-the-box CopyButton.

Recommended for+14
  • ✓Copying invoice numbers, tax IDs, account numbers
  • ✓Copy-link / share-URL actions (minted async)
  • ✓Code or API-key snippets in settings pages
Tags+6
copyclipboardbuttonsnippetsharehookdefault
Features+4
  • String or async () => string value (resolved on click)
  • navigator.clipboard with textarea/execCommand fallback
  • Copied state with check icon, configurable timeout
  • Refused-write state: danger alert icon, failure tooltip, failure aria-label and live-region announcement (data-copy-failed hook)
  • Copy / Copied tooltip (hideable) + sr-only live region
  • Controlled or uncontrolled copied state
  • onCopied / onError / onCopiedChange callbacks
  • Full Button tone x emphasis x size inheritance
  • Headless useClipboard hook { copy, copied, error, reset }
  • Reduced-motion safe icon crossfade
Not recommended for−2
  • ✕Generic actions without clipboard semantics (use Button)
  • ✕Copying rich HTML content (plain text only)

Install

Ask your agent, or call the MCP tool directly. The resolved bundle is written into your project.

get_registry_item({ name: "CopyButton" })

Usage

import { CopyButton, useClipboard } from '@/components/actions/copy-button';

<CopyButton value="0105561234567" aria-label="Copy tax ID" />
<CopyButton value={async () => (await mintPayLink()).url} tone="primary" emphasis="soft">
  Copy payment link
</CopyButton>

Tick variants in the left menu — each adds a tab with that variant’s real story source, the same code the preview above renders.

Props

PropTypeRequired
value

Text to copy, or a sync/async producer of it

string | (() => string | Promise<string>)yes
timeout

How long the copied state persists in ms (default 2000)

number—
copied

Controlled copied state

boolean—
onCopiedChange

Mirrors internal copied-state changes

(copied: boolean) => void—
onCopied

Called with the resolved text on success

(text: string) => void—
onError

Called when resolving or writing fails

(error: Error) => void—
copyLabel

Idle tooltip / accessible label (default "Copy")

ReactNode—
copiedLabel

Copied tooltip / announced label (default "Copied")

ReactNode—
copyFailedLabel

Refused-write tooltip / announced label (default "Copy failed — press Ctrl+C")

ReactNode—
labels

Override the built-in UI strings (copy, copied, copyFailed) for i18n; English defaults exported as DEFAULT_COPY_BUTTON_LABELS

Partial<CopyButtonLabels>—
showTooltip

Hide the tooltip; live region remains (default true)

boolean—
tone

Semantic tone (default neutral)

'neutral' | 'primary' | 'success' | 'warning' | 'danger' | 'info'—
emphasis

Visual loudness (default ghost)

'solid' | 'soft' | 'outline' | 'ghost' | 'link'—
size

Button size

'xs' | 'sm' | 'md' | 'lg'—

Every tonal component shares the same tone × emphasis API, so the pair looks identical across Button, Badge, Alert and more.

Related