Skip to content
WANCRAFT

A.36Buttons & Controls

Copy Button

A copy-to-clipboard button whose icon morphs into a drawn check, with a tooltip, live announcement and fallback.

NewReactMotionSVGTailwindbasic

Overview

Copy Button handles the small moment after “copy” properly. The clipboard glyph rotates away as a check mark draws itself in, a tooltip flips to “Copied” and a polite live region tells screen-reader users the same thing. It uses the Clipboard API, falls back to a hidden textarea and execCommand in insecure contexts, and shows a clear error state if both fail. Pass a static value or a (possibly async) getValue, and choose an icon button, an inline chip that shows the value, or a pill with a morphing label.

01Installation

Method 01 · Registry

CLI verified

Uses the shadcn CLI in a project initialised with shadcn init. Installs the file to components/ui/copy-button.tsx and adds its dependencies.

npx shadcn@latest add https://wancraft.my/r/copy-button.json

Method 02 · Copy and paste

  1. 1. Install the dependencies below.
  2. 2. Copy the source from the Code tab into components/ui/copy-button.tsx.
  3. 3. Import it and adjust props.
npm install motion
Dependencies
motion
Peer
react ≥ 18, tailwindcss ≥ 4
Added
13 Oct 2026
Updated
—

02Usage

The default configuration. Change properties above to generate a tailored example in the Usage tab.

example.tsx
import { CopyButton } from "@/components/ui/copy-button";

export function CopyButtonExample() {
  return (
    <CopyButton value="pnpm dlx shadcn@latest add wancraft/copy-button" />
  );
}

03Props

PropTypeDefaultDescription
valuestring—Text to copy.
getValue() => string | Promise<string>—Resolves the text at click time; takes precedence over value. Rejecting shows the error state.
timeoutnumber1600How long the copied / error state stays, in ms.
labelstring"Copy"Accessible name of the icon variant, text of the pill, idle tooltip.
copiedLabelstring"Copied"Shown and announced after copying.
errorLabelstring"Copy failed"Shown and announced when copying fails.
variant"icon" | "inline" | "pill""icon"Icon-only, inline chip showing the value, or pill with a label.
tooltipbooleantrueTooltip above the icon and inline variants (the pill morphs its own label).
accentstring"#FF7448"Check mark, border highlight and focus ring colour.
childrenReactNode—Inline variant: display content instead of value.
onCopy / onCopyError(text: string) => void / (error: unknown) => void—Result callbacks.
...propsButtonHTMLAttributes—Forwarded to the <button>. The ref points to the <button>.

04Features

  • 01Clipboard glyph rotates out while a check (or cross) draws itself in
  • 02Clipboard API with an execCommand fallback, plus a real error state
  • 03Static value or async getValue
  • 04Tooltip that flips to “Copied”; the pill variant morphs its label instead
  • 05Icon, inline chip and pill variants
motion · tweeninput · clickinput · hoverinput · focusinput · keyboard

05Accessibility

  • Native <button>; the icon variant is named by label via aria-label.
  • The inline variant's name includes the label (screen-reader text) followed by the visible value.
  • A polite role="status" region announces the copied or error label; the tooltip itself is aria-hidden.
  • Tooltips appear on hover and on keyboard focus (focus-visible); focus is restored after the fallback copy.
  • With prefers-reduced-motion icons swap and labels change without drawing or sliding.