Skip to content
shadcn.io
shadcn.io is not affiliated with official shadcn/ui

Shadcn Clipboard for React and Tailwind

Copy text to the clipboard.

Installation

bunx --bun shadcn@latest add https://kit.dev/r/clipboard.json

Anatomy

Clipboard
├── ClipboardLabel
├── Control (baked in)
│   ├── ClipboardInput
│   ├── ClipboardValue
│   └── ClipboardTrigger
│       └── ClipboardIndicator

Clipboard wraps children in Clipboard.Control. className is applied to that control. Use rootClassName for the root. useClipboard is the machine hook for ClipboardRootProvider; useClipboardContext / ClipboardContext is in-tree.

Usage

import { Button } from "@/components/ui/button";
import {
  Clipboard,
  ClipboardIndicator,
  ClipboardInput,
  ClipboardTrigger,
} from "@/components/ui/clipboard";
<Clipboard value="https://shadcn.io">
  <ClipboardInput />
  <ClipboardTrigger asChild>
    <Button size="icon-md">
      <ClipboardIndicator />
    </Button>
  </ClipboardTrigger>
</Clipboard>

Triggers that should look like Button use asChild with a single child. The trigger already sets aria-label to "Copy to clipboard" / "Copied to clipboard".

Controlled

Use value and onValueChange to control the string that will be copied. { value } is a string.

Root Provider

Use useClipboard with ClipboardRootProvider when you need copied, value, setValue, or copy() outside the tree. Pass value / timeout / onStatusChange to useClipboard(), not to the provider.

Context

ClipboardContext / useClipboardContext expose copied, value, setValue, and copy() inside the tree.

Examples

Label

ClipboardLabel associates with the input (htmlFor).

Icon only

Different icons

Pass copied and children to ClipboardIndicator.

Value text

ClipboardValue shows the string as text instead of an input. size matches Input heights (xs–xl).

Timeout

timeout is how long copied stays true. Ark default is 3000 ms.

Copy status

onStatusChange fires when copy starts and when the timeout clears. { copied: boolean }.

API Reference

shadcn.io wraps Ark UI Clipboard. Control is baked into Clipboard / ClipboardRootProvider. Default timeout is 3000 (not 2000). value is optional if you pass defaultValue.

asChild merges props onto a single child element.

Clipboard

Root. Renders a div. Children are wrapped in the control (flex row).

PropTypeDefaultDescription
asChildbooleanfalseRender the child element instead of a div.
classNamestring-Class names on the control, not the root.
defaultValuestring-Uncontrolled string to copy.
idstring-Unique id for the machine.
idsPartial<{ root: string; input: string; label: string }>-Element ids for composition.
onStatusChange(details: CopyStatusDetails) => void-Copy status changed. { copied: boolean }.
onValueChange(details: ValueChangeDetails) => void-Value changed. { value: string }.
rootClassNamestring-Class names on the root.
timeoutnumber3000How long copied stays true, in ms.
translations{ triggerLabel?: (copied: boolean) => string }see belowAccessible name of the trigger.
valuestring-Controlled string to copy.

Default translations.triggerLabel: "Copy to clipboard" / "Copied to clipboard".

AttributeDescription
data-slotclipboard
data-scopeclipboard
data-partroot
data-copiedPresent while the copied state is active

Control: data-slot="clipboard-control", data-part="control", data-copied as above.

ClipboardRootProvider

Takes the API from useClipboard. Same baked control as Clipboard.

PropTypeDefaultDescription
valueUseClipboardReturnrequiredReturn value of useClipboard().
asChildbooleanfalseRender the child element instead of a div.
classNamestring-Class names on the control.
rootClassNamestring-Class names on the root.

Pass value, timeout, onStatusChange, and other machine options to useClipboard(), not to the provider.

ClipboardLabel

Visible label for the input. Renders a label. Takes a full row in the control (w-full).

PropTypeDefaultDescription
asChildbooleanfalseMerge onto a single child.
classNamestring-Class names on the label.
AttributeDescription
data-slotclipboard-label
data-scopeclipboard
data-partlabel
data-copiedPresent while copied

ClipboardInput

Read-only input showing the value. Focus selects the contents. Native copy on the input also sets copied. Renders an input.

PropTypeDefaultDescription
asChildbooleanfalseMerge onto a single child.
classNamestring-Class names on the input. Uses Input inputVariants.
AttributeDescription
data-slotclipboard-input
data-scopeclipboard
data-partinput
data-copiedPresent while copied
data-readonlyAlways "true"

ClipboardValue

Text display of the value (ValueText). Renders a span (styled as a field).

PropTypeDefaultDescription
size"xs" | "sm" | "md" | "lg" | "xl""md"Height tokens matching Input (h-6 … h-10).
asChildbooleanfalseMerge onto a single child.
classNamestring-Class names on the text.
AttributeDescription
data-slotclipboard-value
data-scopeclipboard
data-partvalue-text

ClipboardTrigger

Copies value on click. Renders a button. Use asChild with Button.

PropTypeDefaultDescription
asChildbooleanfalseMerge onto a single child.
classNamestring-Class names on the trigger.
AttributeDescription
data-slotclipboard-trigger
data-scopeclipboard
data-parttrigger
data-copiedPresent while copied

ClipboardIndicator

Shows copied content while copied, otherwise children. Defaults to ClipboardIcon / CheckIcon (both aria-hidden). Renders a div.

PropTypeDefaultDescription
copiedReactNodeCheckIconContent while copied.
asChildbooleanfalseMerge onto a single child.
classNamestring-Class names on the indicator.
AttributeDescription
data-slotclipboard-indicator
data-scopeclipboard
data-partindicator

useClipboard

Creates the clipboard API for ClipboardRootProvider.

const clipboard = useClipboard({ value: "https://shadcn.io", timeout: 5000 });
clipboard.copy();

ClipboardContext / useClipboardContext

Render-prop or hook access. Use inside Clipboard or ClipboardRootProvider.

PropertyTypeDescription
copiedbooleanWhether the copied timeout is active.
valuestringString that will be copied.
setValue(value: string) => voidSet the string.
copy() => voidCopy value to the system clipboard.

ClipboardContext children: (context) => ReactNode.

Accessibility

The trigger is a button with aria-label "Copy to clipboard" or "Copied to clipboard". Pair ClipboardInput with ClipboardLabel when the field is visible. Icon-only triggers should keep that accessible name (do not replace it with an unlabeled icon button). Decorative icons are aria-hidden.

Keyboard support

KeyDescription
TabMove to the input or the trigger.
Shift + TabMove to the previous control.
Enter / SpaceOn the trigger, copy the value.
Ctrl / Cmd + COn the focused input, copy (also sets copied).