---
name: aircall-blocks/migrate-dashboard/copy-button
description: >
  Migrate @dashboard/library CopyToClipboardButton and CopyToClipboardText to
  @aircall/blocks CopyButton compound. Load when a file imports
  CopyToClipboardButton or CopyToClipboardText from @dashboard/library.
type: sub-skill
library: aircall-blocks
requires:
  - aircall-blocks/setup
  - aircall-blocks/migrate-dashboard
sources:
  - "aircall/hydra:packages/blocks/src/index.ts"
---

This skill builds on aircall-blocks/migrate-dashboard.

## 1. Component mapping

| `@dashboard/library` | `@aircall/blocks` |
| --- | --- |
| `CopyToClipboardButton` | `CopyButton` (outline variant, icon + label) |
| `CopyToClipboardText` | `CopyButton` (ghost variant, inline text + icon) |

Both map to the same `CopyButton` compound from `@aircall/blocks`. The visual
difference (button vs. inline text) is controlled by the `variant` prop.

## 2. Verified blocks exports

```
CopyButton, CopyButtonIcon, CopyButtonLabel
```

Import from `@aircall/blocks`, not `@aircall/ds`.

## 3. Imports

```tsx
import { CopyButton, CopyButtonIcon, CopyButtonLabel } from '@aircall/blocks';
```

## 4. Prop mapping

### `CopyToClipboardButton`

| `CopyToClipboardButton` prop | `CopyButton` equivalent |
| --- | --- |
| `content` | `value` prop on `<CopyButton>` |
| `texts.copy` | `label` on `<CopyButtonLabel>` |
| `texts.copied` | `copiedLabel` on `<CopyButtonLabel>` |
| `variant` (button variant) | `variant` on `<CopyButton>` (default: `"outline"`) |

### `CopyToClipboardText`

| `CopyToClipboardText` prop | `CopyButton` equivalent |
| --- | --- |
| `children` (the text to display) | text node child inside `<CopyButton>` |
| `tooltipTexts.copy` | _(tooltip not used — CopyButton has no built-in tooltip)_ |
| content to copy | `value` prop on `<CopyButton>` |
| inline text appearance | `variant="ghost"` on `<CopyButton>` |

## 5. Before / After examples

### 5a. CopyToClipboardButton → CopyButton (outline)

**Before:**
```tsx
import { CopyToClipboardButton } from '@dashboard/library';

<CopyToClipboardButton
  content="+33 6 12 34 56 78"
  texts={{ copy: 'Copy number', copied: 'Copied!' }}
/>
```

**After:**
```tsx
import { CopyButton, CopyButtonIcon, CopyButtonLabel } from '@aircall/blocks';

<CopyButton value="+33 6 12 34 56 78">
  <CopyButtonIcon />
  <CopyButtonLabel label="Copy number" copiedLabel="Copied!" />
</CopyButton>
```

### 5b. CopyToClipboardText → CopyButton (ghost, inline)

**Before:**
```tsx
import { CopyToClipboardText } from '@dashboard/library';

<CopyToClipboardText tooltipTexts={{ copy: 'Copy', copied: 'Copied' }}>
  +33 6 12 34 56 78
</CopyToClipboardText>
```

**After:**
```tsx
import { CopyButton, CopyButtonIcon } from '@aircall/blocks';

<CopyButton value="+33 6 12 34 56 78" variant="ghost">
  +33 6 12 34 56 78
  <CopyButtonIcon />
</CopyButton>
```

> The `tooltipTexts` prop had no functional role in `CopyToClipboardText` beyond
> tooltip copy — `CopyButton` has no built-in tooltip, so drop it.

## 6. Common mistakes

### Mistake 1: Importing from `@aircall/ds`

```tsx
// WRONG — CopyButton lives in @aircall/blocks, not @aircall/ds
import { CopyButton } from '@aircall/ds';
```

```tsx
// CORRECT
import { CopyButton, CopyButtonIcon, CopyButtonLabel } from '@aircall/blocks';
```

### Mistake 2: Passing text content directly without CopyButtonLabel

```tsx
// WRONG — plain text as children won't update to "Copied!" state
<CopyButton value="…">Copy number</CopyButton>
```

```tsx
// CORRECT — CopyButtonLabel handles the copy/copied toggle
<CopyButton value="…">
  <CopyButtonIcon />
  <CopyButtonLabel label="Copy number" copiedLabel="Copied!" />
</CopyButton>
```
