Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Components

Free

Clipboard for Ark UI

Copy a share link, a token, or an install command, and show a copied state. For React with Ark UI, when people shouldn't have to retype the value.

Framework
UI library

It copies a string and shows a check once the write succeeds.

Use it for a link, a token, or a command someone would otherwise retype. A plain Button is enough if you would rather call the clipboard yourself and design the feedback. In React, Ark UI holds the copied state for a few seconds after a successful write.

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.

Anatomy

Clipboard anatomy: root, label, input, trigger, indicator
Clipboard
├── ClipboardControl
├── ClipboardTrigger
├── ClipboardIndicator
├── ClipboardInput
└── ClipboardLabel

Usage

import {
  Clipboard, ClipboardIndicator, ClipboardInput, ClipboardTrigger,
} from "@/components/ui/clipboard";
import {
  InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput,
} from "@/components/ui/input-group";
<div className="w-full max-w-sm">
  <Clipboard value="https://example.com">
    <InputGroup>
      <ClipboardInput asChild>
        <InputGroupInput />
      </ClipboardInput>
      <InputGroupAddon align="inline-end">
        <ClipboardTrigger asChild>
          <InputGroupButton size="icon-xs">
            <ClipboardIndicator />
          </InputGroupButton>
        </ClipboardTrigger>
      </InputGroupAddon>
    </InputGroup>
  </Clipboard>
</div>

Accessibility

Enter
Activate the focused control.
Space
Activate the focused control.

Demos

Context

ClipboardContext lets the button read copied and call copy without the stock trigger. The label can say Copy and switch to Copied on its own, which is what you want when an icon swap is the wrong feedback. The string still lives on the root as value. Skip the input when people do not need to see or edit the text before it is copied.

Preview width

Controlled

Keep value in your own state when something outside the field changes the string that will be copied. A secondary button here rewrites the URL to a docs path, and the input follows because the root is controlled. Wire the value-change handler if the field itself stays editable. A constant value is enough when the text never changes.

Preview width

Copy Status

The status callback fires once the copy has landed, which is the moment for a toast or a counter rather than another icon. This button increments a count beside ClipboardValue, and the indicator still swaps to a check on its own. Use the callback when the product has to record the copy or name what was copied. Do not use it to rebuild the icon swap.

Preview width

Custom Timeout

timeout is the copied-state duration in milliseconds, and the default is three seconds. This field sets 5000 so the check lingers on a URL someone might glance away from. Lengthen it when the confirmation is a small icon at the end of a long field. Shorten it when people copy several values in a row, or a leftover check will point at the wrong one.

Preview width

Different Icon

ClipboardIndicator shows one icon at rest and another after the copy. The resting icon is its content, and copied supplies the sparkles that replace a single sparkle once the write succeeds. Bring your own pair when a clipboard glyph clashes with the product, or when a check already means something else. Hide both from assistive tech if the button has a name, and leave the timing to timeout.

Preview width

Icon Only

An icon button is the right trigger when the string is already visible, or when the row has no room for the word Copy. ClipboardIndicator draws the clipboard glyph and swaps in a check while the copied state lasts. Give the button an accessible name, because the icon is not text. Use the icon in a toolbar, and a labeled button when the control sits by itself.

Preview width

Root Provider

useClipboard owns the state, and ClipboardRootProvider shares it with the input and the in-field trigger. A second button outside that tree calls copy, and a line on the page prints whether copied is set. Use the provider when the control that copies cannot live inside Clipboard, such as a toolbar far from the field. If the button can sit inside the root, skip the hook.

Preview width

Value Text

ClipboardValue prints the string with no field chrome, and the icon button beside it copies that same value. Use the plain text in a docs line, a token list, or anywhere a bordered input would be too heavy. Use ClipboardInput when someone should select the text or edit it before copying. The indicator still swaps to a check, so you do not add a second confirmation.

Preview width

With Label

ClipboardLabel names the control, here Copy this link, and sits above the grouped input. That name is what assistive tech gets, instead of an unlabeled icon at the end of the field. Add it when the clipboard is not already inside a labeled field, and when the placeholder is a poor name. Skip it when a heading directly above already says what will be copied.

Preview width

FAQ

How do I add a copy to clipboard button in React?

Put a ClipboardTrigger inside Clipboard and pass the text as value: clicking the trigger copies it. A ClipboardIndicator inside the trigger swaps the clipboard icon for a check while the copied state lasts, as in the Icon Only demo.

How do I put the copy button inside the input?

Compose the Clipboard with an Input Group: render the clipboard input as the group's input and put the trigger in an InputGroupAddon at the end. The first demo on this page shows the full pattern.

How long does the Clipboard stay in the copied state?

Three seconds by default. Set timeout, in milliseconds, on Clipboard to change it, as in the Custom Timeout demo.

How do I know when the Clipboard copied the text?

Use onStatusChange: it's called with { copied: true } once the text is copied, which is where you show a toast or log the event. The Copy Status demo counts each copy.

How do I copy from a button outside the Clipboard?

Create the state with useClipboard and pass it to ClipboardRootProvider, then call its copy() from anywhere on the page, as the Root Provider demo shows.

How do I change the Clipboard copy icon?

Pass the icon to show before copying as the children of ClipboardIndicator, and the one to show after as its copied prop. The Different Icon demo uses sparkles.

Does the Clipboard work without HTTPS?

Yes, with a fallback. It copies with the browser's Clipboard API, which needs a secure page (HTTPS or localhost), and falls back to the older execCommand copy when that API isn't available.

API Reference

Clipboard

<div> data-slot="clipboard"

PropType
value?string

The controlled value of the clipboard.

defaultValue?string

The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard.

onValueChange?(details: ValueChangeDetails) → void

The function to be called when the value changes.

Type
(details: ValueChangeDetails) → void
Parameters

details – { value: string }

Returns
void
id?string

The unique identifier of the machine.

ids?object

The ids of the elements in the clipboard. Useful for composition.

Type
{ root?: string; input?: string; label?: string }
onStatusChange?(details: CopyStatusDetails) → void

The function to be called when the value is copied to the clipboard.

Type
(details: CopyStatusDetails) → void
Parameters

details – { copied: boolean }

Returns
void
rootClassName?string

Class names on the root. className is applied to the baked control.

timeout?number

The timeout for the copy operation.

Default
3000
translations?object

Specifies the localized strings that identifies the accessibility elements and their states.

Type
{ triggerLabel?: (copied: boolean) → string }
asChild?boolean

Use the provided child element as the default rendered element, combining their props and behavior.

className?string

Merged with the part's classes.

AttributeType
data-copied?string

Present when copied state is true.

ClipboardControl

<div> data-slot="clipboard-control"

PropType
asChild?boolean

Use the provided child element as the default rendered element, combining their props and behavior.

AttributeType
data-copied?string

Present when copied state is true.

ClipboardTrigger

<button> data-slot="clipboard-trigger"

PropType
asChild?boolean

Use the provided child element as the default rendered element, combining their props and behavior.

AttributeType
data-copied?string

Present when copied state is true.

ClipboardIndicator

<div> data-slot="clipboard-indicator"

PropType
copied?ReactNode

What it shows once the value is copied; its children show before.

Default
<CheckIcon aria-hidden="true" />
asChild?boolean

Use the provided child element as the default rendered element, combining their props and behavior.

className?string

Merged with the part's classes.

ClipboardInput

<input>

PropType
asChild?boolean

Use the provided child element as the default rendered element, combining their props and behavior.

className?string

Merged with the part's classes.

AttributeType
data-copied?string

Present when copied state is true.

data-readonly"true"

Present when read-only.

Default
"true"

ClipboardLabel

<label> data-slot="clipboard-label"

PropType
asChild?boolean

Use the provided child element as the default rendered element, combining their props and behavior.

className?string

Merged with the part's classes.

AttributeType
data-copied?string

Present when copied state is true.

ClipboardValue

<span> data-slot="clipboard-value"

PropType
size?"xs" | "sm" | "md" | "lg" | "xl"

The size.

Type
"xs" | "sm" | "md" | "lg" | "xl"
Default
"md"
asChild?boolean

Use the provided child element as the default rendered element, combining their props and behavior.

className?string

Merged with the part's classes.

ClipboardRootProvider

<div> data-slot="clipboard"

PropType
valueUseClipboardReturn

What useClipboard() returns: the state and API, made outside the component to control it.

rootClassName?string

Class names on the root. className is applied to the baked control.

asChild?boolean

Use the provided child element as the default rendered element, combining their props and behavior.

className?string

Merged with the part's classes.

AttributeType
data-copied?string

Present when copied is true.

useClipboard

PropType
value?string

The controlled value of the clipboard.

defaultValue?string

The initial value to be copied to the clipboard when rendered. Use when you don't need to control the value of the clipboard.

onValueChange?(details: ValueChangeDetails) → void

The function to be called when the value changes.

Type
(details: ValueChangeDetails) → void
Parameters

details – { value: string }

Returns
void
id?string

The unique identifier of the machine.

ids?object

The ids of the elements in the clipboard. Useful for composition.

Type
{ root?: string; input?: string; label?: string }
onStatusChange?(details: CopyStatusDetails) → void

The function to be called when the value is copied to the clipboard.

Type
(details: CopyStatusDetails) → void
Parameters

details – { copied: boolean }

Returns
void
timeout?number

The timeout for the copy operation.

Default
3000
translations?object

Specifies the localized strings that identifies the accessibility elements and their states.

Type
{ triggerLabel?: (copied: boolean) → string }

ClipboardContext

PropType
copiedboolean

Whether the value has been copied to the clipboard.

copyVoidFunction

Copy the value to the clipboard.

setValue(value: string) → void

Set the value to be copied to the clipboard.

Parameters

value – string

Returns
void
valuestring

The value to be copied to the clipboard.

With other components

  • Button

    Buttons

    The copy control

  • Input

    Inputs

    The text to copy

  • Tooltip

    Overlays

    Copied, or copy

  • Kbd

    Typography

    The shortcut

  • The field and the button

  • Toast

    Feedback

    Confirm it landed