Source: https://monarchui.dev/components/copy-field/

Components · Actions

# CopyField

A read-only value with a copy button: links, records, keys and snippets.

@rookcom/monarch-react

Component

## One-line values

## Usage examples

### In a Field, multi-line

## Purpose

Shows a value the user needs to take elsewhere (a webhook URL, a DNS record, an embed snippet, a calendar feed) in a read-only text box with a CopyButton beside it.

### Use when

- The user should see the value and copy it, for example while configuring another service.
- The value is long or structured: `multiline` shows it in a text area.

### Avoid when

- The value is a secret: use SecretField, which masks it.
- Only the button is needed and the value is shown elsewhere: use CopyButton.
- The user should edit the value: use Input.

## Design principles

- The value is always selectable by hand: focus selects all of it, and a failed copy focuses and selects it.
- One label names both parts: the text box ("Webhook URL") and the button ("Copy Webhook URL").
- Works inside a Field, so a visible label, help text and errors are wired the usual way.
- Monospace by default, because most copied values are codes, hosts or URLs.

## API reference

```tsx
import { CopyField } from '@rookcom/monarch-react';
```

| Export | Kind | Rendering | Root class |
| --- | --- | --- | --- |
| `CopyField` | component | client | `.mn-copy-field` |

Renders `<div class="mn-copy-field">` (the ref) holding a read-only Input or Textarea and a CopyButton.

Inside a Field the control takes the Field id, description and error wiring from `useFieldControl`.

Generated from the TypeScript declarations of `packages/react/src/components/actions/copy-field`.

## Properties

`copyButtonProps` passes extra props (for example `variant`) to the CopyButton.

### `CopyField`

A read-only value with a copy button: webhook URLs, DNS records, embed snippets, calendar feed links. If copying fails, the value is focused and selected so the user can copy it by hand.

| Prop | Type | Description |
| --- | --- | --- |
| `label` required | `string` | What the value is ("Webhook URL"). Names the text box outside a Field (inside one, the FieldLabel does) and completes the copy button's name: "Copy webhook URL". |
| `value` required | `string` | The read-only value shown and copied. |
| `children` | `ReactNode` |  |
| `className` | `string` |  |
| `copiedLabel` | `string` | Visible text of the copy button after copying. Default "Copied". |
| `copyButtonProps` | `Omit<CopyButtonProps, "size" \| "value" \| "onCopy" \| "label" \| "target" \| "copiedLabel" \| "iconOnly" \| "resetAfter" \| "onCopyError">` | Extra props for the copy button, for example `variant`. |
| `copyLabel` | `string` | Visible text of the copy button. Default "Copy". |
| `disabled` | `boolean` |  |
| `iconOnly` | `boolean` | Show only the copy icon. The button is still named "Copy {label}". Default false. |
| `id` | `string` |  |
| `mono` | `boolean` | Monospace text for codes, keys, hostnames and DNS records. Default true. |
| `multiline` | `boolean` | Show the value in a multi-line text area (certificates, JSON, snippets). |
| `onCopy` | `((text: string) => void)` | Called with the copied text after a successful copy. |
| `onCopyError` | `((error: Error) => void)` | Called when copying fails. The value is selected first, so the user can copy it by hand; show a toast here if the product uses them. |
| `resetAfter` | `number` | Milliseconds before the button returns to its idle look. Default 2000. |
| `rows` | `number` | Visible rows when `multiline`. Default 3. |
| `selectOnFocus` | `boolean` | Select the whole value when the text box gets focus. Default true. |
| `size` | `ControlSize` |  |

## Variants

| Prop | Values | Description |
| --- | --- | --- |
| `multiline` | `'true'``'false'` | Text area (`rows`, default 3) instead of a one-line input (`data-multiline`). |
| `mono` | `'true'``'false'` | Monospace value (`data-mono`). Default true. |
| `size` | `'sm'``'md'``'lg'` | Input and button size. Default `md`. |
| `iconOnly` | `'true'``'false'` | Icon-only copy button for narrow layouts. |

## States

| State | Exposed as | Behaviour |
| --- | --- | --- |
| Read-only | `readonly` | The value can be selected but not changed. |
| Copied / error | `data-state on .mn-copy-field__button` | From CopyButton. On error the value is also focused and selected. |
| Disabled | `disabled` | Both the text box and the button are disabled. |

## Interaction behaviour

- Focusing the text box selects the whole value (`selectOnFocus`, default true).
- The copy button copies `value` and confirms like CopyButton.
- If copying fails, the value is focused and selected, then `onCopyError` is called.

## Keyboard support

| Keys | Action |
| --- | --- |
| Tab | Focuses the text box (selecting the value), then the copy button. |
| Ctrl/⌘ + C | Copies the selected value by hand. |
| Enter / Space | On the button: copies the value. |

## Accessibility

Role

textbox (read-only) and button

Accessible name

Outside a Field,

label

is the text box

aria-label

; inside one, the FieldLabel. The button is named "Copy {label}".

- The copy result is announced by CopyButton’s polite live region.
- Read-only rather than disabled, so the value stays focusable and readable by screen readers.
- Spell-check and autocomplete are off for the value.

## Responsive behaviour

- The text box shrinks to fit (`min-width: 0`); the button keeps its size, so it works at 320px.
- Long one-line values are truncated visually but remain complete for selection and copying.
- Multi-line values scroll inside the text area instead of wrapping.

## Theme support

- The read-only background is `--mn-color-bg-subtle`, so it reads as "not editable" in every theme.
- All colours are Monarch tokens; more-contrast themes apply automatically.

## Do and don't

### Do

- Give each field a specific label ("Calendar feed URL"), so its button is distinguishable.
- Use `mono={false}` for prose, such as a message template.
- Report `onCopyError` the way the product reports other errors.

### Don't

- Do not use CopyField for secrets.
- Do not use it for values the user edits; it is read-only by design.

## Related components

- [CopyButton](https://monarchui.dev/components/copy-button/): The button on its own.
- [SecretField](https://monarchui.dev/components/secret-field/): For keys and tokens that must be masked.
- [Input](https://monarchui.dev/components/text-field/): The Input and Textarea it renders.
- [Field](https://monarchui.dev/components/form-field/): Adds a visible label, help text and errors.

## Dependencies

| Kind | Depends on |
| --- | --- |
| npm packages | `react` |
| Monarch components | [CopyButton](https://monarchui.dev/components/copy-button/), [Field](https://monarchui.dev/components/form-field/), [Input](https://monarchui.dev/components/text-field/) |

## Testing coverage

- Shows the value read-only and names the text box and button from `label`.
- Copies the value with the button and announces it.
- Selects the whole value on focus; Tab order is text box, then button.
- On failure, focuses and selects the value and calls `onCopyError`.
- Inside a Field, the FieldLabel names the text area.
- Icon-only keeps a full accessible name; `disabled` disables both parts.

| Check | Covered |
| --- | --- |
| Axe in jsdom | Yes |
| Server rendering | Yes |
| Browser suites | Visual baselines: /__gallery; Cross-browser axe: /components/copy-field |

Tests: `packages/react/src/components/actions/copy-field`

## All example code

### One-line values

```tsx
import { CopyField } from '@rookcom/monarch-react';

<CopyField label="Webhook URL" value="https://example.com/hooks/inbound/7f3a2c" />
<CopyField label="TXT record" value="verify=c41e9b20d7" size="sm" iconOnly />
```

### In a Field, multi-line

```tsx
import { CopyField, Field, FieldDescription, FieldLabel } from '@rookcom/monarch-react';

const embed = `<script src="https://example.com/widget.js"
  data-workspace="ws_01HZX4" async></script>`;

<Field style={{ width: '100%', maxWidth: '36rem' }}>
  <FieldLabel>Embed code</FieldLabel>
  <CopyField label="Embed code" value={embed} multiline />
  <FieldDescription>Paste before the closing body tag.</FieldDescription>
</Field>
```
