# Clipboard

URL: https://ark-ui.com/docs/components/clipboard
Source: https://raw.githubusercontent.com/chakra-ui/ark/refs/heads/main/website/src/content/pages/components/clipboard.mdx

A component to copy text to the clipboard

---

<ComponentPreview id="Clipboard" />

## Anatomy

<Anatomy id="clipboard" />

```tsx
<Clipboard.Root>
  <Clipboard.Label />
  <Clipboard.Control>
    <Clipboard.Input />
    <Clipboard.Trigger>
      <Clipboard.Indicator />
    </Clipboard.Trigger>
  </Clipboard.Control>
</Clipboard.Root>
```

## Examples

**Example: basic**

```ripple
import { Clipboard } from 'ark-ripple/clipboard';
import { Check, Copy } from 'lucide-ripple';
import styles from 'styles/clipboard.module.css';

export component Basic() {
  <Clipboard.Root class={styles.Root} value="https://ark-ui.rip">
    <Clipboard.Label class={styles.Label}>{'Copy this link'}</Clipboard.Label>
    <Clipboard.Control class={styles.Control}>
      <Clipboard.Input class={styles.Input} />
      <Clipboard.Trigger class={styles.Trigger}>
        <Clipboard.Indicator class={styles.Indicator} copied={Check}>
          <Copy />
        </Clipboard.Indicator>
      </Clipboard.Trigger>
    </Clipboard.Control>
  </Clipboard.Root>
}

```

### Controlled

Control the clipboard value externally by managing the state yourself and using `onValueChange` to handle updates.

**Example: controlled**

```ripple
import { Clipboard } from 'ark-ripple/clipboard';
import { track } from 'ripple';
import styles from 'styles/clipboard.module.css';
import button from 'styles/button.module.css';
import { Check, Copy } from 'lucide-ripple';

export component Controlled() {
  const url = track('https://ark-ui.rip');

  <div class="stack">
    <Clipboard.Root
      class={styles.Root}
      value={@url}
      onValueChange={(details) => {
        @url = details.value;
      }}
    >
      <Clipboard.Label class={styles.Label}>{'Copy this link'}</Clipboard.Label>
      <Clipboard.Control class={styles.Control}>
        <Clipboard.Input class={styles.Input} />
        <Clipboard.Trigger class={styles.Trigger}>
          <Clipboard.Indicator class={styles.Indicator} copied={Check}>
            <Copy />
          </Clipboard.Indicator>
        </Clipboard.Trigger>
      </Clipboard.Control>
    </Clipboard.Root>
    <button
      class={button.Root}
      onClick={() => {
        @url = 'https://chakra-ui.com';
      }}
    >
      {'Change Url'}
    </button>
  </div>
}

```

### Root Provider

An alternative way to control the clipboard is to use the `RootProvider` component and the `useClipboard` hook. This way
you can access the state and methods from outside the component.

**Example: root-provider**

```ripple
import { Clipboard, useClipboard } from 'ark-ripple/clipboard';
import styles from 'styles/clipboard.module.css';
import { Check, Copy } from 'lucide-ripple';

export component RootProvider() {
  const clipboard = useClipboard({ value: 'https://ark-ui.rip' });

  <div class="stack">
    <output>
      {'value: '}
      {@clipboard.value}
      {', copied: '}
      {String(@clipboard.copied)}
    </output>
    <Clipboard.RootProvider class={styles.Root} value={clipboard}>
      <Clipboard.Label class={styles.Label}>{'Copy this link'}</Clipboard.Label>
      <Clipboard.Control class={styles.Control}>
        <Clipboard.Input class={styles.Input} />
        <Clipboard.Trigger class={styles.Trigger}>
          <Clipboard.Indicator class={styles.Indicator} copied={Check}>
            <Copy />
          </Clipboard.Indicator>
        </Clipboard.Trigger>
      </Clipboard.Control>
    </Clipboard.RootProvider>
  </div>
}

```

### Context

Access the clipboard's state with `Clipboard.Context` or the `useClipboardContext` hook. You get properties like
`copied`, `value`, and `setValue`.

> Alternatively, you can use the `useClipboardContext` hook to access the clipboard context.

**Example: context**

```ripple
import { Clipboard } from 'ark-ripple/clipboard';
import { Check, Copy } from 'lucide-ripple';
import styles from 'styles/clipboard.module.css';
import button from 'styles/button.module.css';

export component Context() {
  <Clipboard.Root class={styles.Root} value="https://ark-ui.rip">
    <Clipboard.Label class={styles.Label}>{'Copy this link'}</Clipboard.Label>
    <Clipboard.Context>
      component children({ context }) {
        <button class={button.Root} onClick={() => @context.copy()}>
          if (@context.copied) {
            <Check />
          } else {
            <Copy />
          }
          {@context.copied ? 'Copied!' : 'Copy'}
        </button>
      }
    </Clipboard.Context>
  </Clipboard.Root>
}

```

### Copy Status

Use the `onStatusChange` prop to listen for copy operations. It exposes a `copied` property that you can use to display
a success message.

**Example: copy-status**

```ripple
import { Clipboard } from 'ark-ripple/clipboard';
import { track } from 'ripple';
import { Check, Copy } from 'lucide-ripple';
import styles from 'styles/clipboard.module.css';

export component CopyStatus() {
  const copyCount = track(0);

  <Clipboard.Root
    class={styles.Root}
    value="https://ark-ui.rip"
    onStatusChange={(details) => {
      if (details.copied) {
        @copyCount = @copyCount + 1;
      }
    }}
  >
    <Clipboard.Control class={styles.Control}>
      <Clipboard.Trigger class={styles.Trigger}>
        <Clipboard.Indicator class={styles.Indicator} copied={Check}>
          <Copy />
        </Clipboard.Indicator>
        <Clipboard.ValueText />
      </Clipboard.Trigger>
    </Clipboard.Control>
    <p>
      {'Copied '}
      {@copyCount}
      {' times'}
    </p>
  </Clipboard.Root>
}

```

### Timeout

Configure the copy status timeout duration using the `timeout` prop. Default is 3000ms (3 seconds).

**Example: timeout**

```ripple
import { Clipboard } from 'ark-ripple/clipboard';
import { Check, Copy } from 'lucide-ripple';
import styles from 'styles/clipboard.module.css';

export component Timeout() {
  <Clipboard.Root class={styles.Root} value="https://ark-ui.rip" timeout={5000}>
    <Clipboard.Label class={styles.Label}>{'Copy this link (5 second timeout)'}</Clipboard.Label>
    <Clipboard.Control class={styles.Control}>
      <Clipboard.Input class={styles.Input} />
      <Clipboard.Trigger class={styles.Trigger}>
        <Clipboard.Indicator class={styles.Indicator} copied={Check}>
          <Copy />
        </Clipboard.Indicator>
      </Clipboard.Trigger>
    </Clipboard.Control>
  </Clipboard.Root>
}

```

### Value Text

Use `Clipboard.ValueText` to display the current clipboard value.

**Example: value-text**

```ripple
import { Clipboard } from 'ark-ripple/clipboard';
import { Check, Copy } from 'lucide-ripple';
import styles from 'styles/clipboard.module.css';

export component ValueText() {
  <Clipboard.Root class={styles.Root} value="https://ark-ui.rip">
    <Clipboard.Control class={styles.Control}>
      <Clipboard.ValueText class={styles.ValueText} />
      <Clipboard.Trigger class={styles.Trigger}>
        <Clipboard.Indicator class={styles.Indicator} copied={Check}>
          <Copy />
        </Clipboard.Indicator>
      </Clipboard.Trigger>
    </Clipboard.Control>
  </Clipboard.Root>
}

```

## API Reference

### Props

**Component API Reference**

**Root Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `defaultValue` | `string` | No | The initial value to be copied to the clipboard when rendered.
Use when you don't need to control the value of the clipboard. |
| `id` | `string` | No | The unique identifier of the machine. |
| `ids` | `Partial<{ root: string; input: string; label: string }>` | No | The ids of the elements in the clipboard. Useful for composition. |
| `onStatusChange` | `(details: CopyStatusDetails) => void` | No | The function to be called when the value is copied to the clipboard |
| `onValueChange` | `(details: ValueChangeDetails) => void` | No | The function to be called when the value changes |
| `timeout` | `number` | No | The timeout for the copy operation |
| `value` | `string` | No | The controlled value of the clipboard |


**Root Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | clipboard |
| `[data-part]` | root |
| `[data-copied]` | Present when copied state is true |


**Control Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Control Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | clipboard |
| `[data-part]` | control |
| `[data-copied]` | Present when copied state is true |


**Indicator Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `copied` | `string | number | bigint | boolean | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | Promise<...>` | No |  |


**Input Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Input Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | clipboard |
| `[data-part]` | input |
| `[data-copied]` | Present when copied state is true |
| `[data-readonly]` | Present when read-only |


**Label Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Label Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | clipboard |
| `[data-part]` | label |
| `[data-copied]` | Present when copied state is true |


**RootProvider Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `UseClipboardReturn` | Yes |  |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Trigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Trigger Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | clipboard |
| `[data-part]` | trigger |
| `[data-copied]` | Present when copied state is true |


**ValueText Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


### Context

**API:**

| Property | Type | Description |
|----------|------|-------------|
| `copied` | `boolean` | Whether the value has been copied to the clipboard |
| `value` | `string` | The value to be copied to the clipboard |
| `setValue` | `(value: string) => void` | Set the value to be copied to the clipboard |
| `copy` | `VoidFunction` | Copy the value to the clipboard |
