Monet
@etched/monet 0.0.1

Inline copy text

Ported

A copy button after a short value, such as an ID in a table cell or a heading. It uses the text's own font and color. The button shows on hover and focus, on the hover of a table row, and always on touch screens. After a copy, the icon turns into a check and screen readers hear "Copied". Native <span> attributes and ref pass through.

Kumo source
run_7f3a91c2
import { InlineCopyText } from "@etched/monet/inline-copy-text";

export function Preview() {
  return <InlineCopyText copyLabel="Copy run ID">run_7f3a91c2</InlineCopyText>;
}

Installation

import { InlineCopyText } from "@etched/monet/inline-copy-text";

Examples

Value

A copy button after a short value. It shows on hover and focus, and always on touch screens; the text stays selectable. Name the button with copyLabel; the text is its description.

Run ID: run_7f3a91c2

import { InlineCopyText } from "@etched/monet/inline-copy-text";

export function Value() {
  return (
    <p>
      Run ID: <InlineCopyText copyLabel="Copy run ID">run_7f3a91c2</InlineCopyText>
    </p>
  );
}

In a table

The button shows while the pointer is on the row. A long value ends in an ellipsis; the copy is always the whole value.

RunChipStatus
run_7f3a91c2Chip 14Passed
run_2b80e4d7Chip 15Failed
run_9c4d2e1f-0a7b-4c3e-9f12-6b8a5d3e7c01Chip 16Queued
import { Table } from "@etched/monet/table";
import { InlineCopyText } from "@etched/monet/inline-copy-text";

const runs = [
  { id: "run_7f3a91c2", chip: "Chip 14", status: "Passed" },
  { id: "run_2b80e4d7", chip: "Chip 15", status: "Failed" },
];

export function InATable() {
  return (
    <div className="card">
      <Table aria-label="Runs" style={{ tableLayout: "fixed" }}>
        <thead>
          <tr>
            <th>Run</th>
            <th>Chip</th>
            <th>Status</th>
          </tr>
        </thead>
        <tbody>
          {runs.map((run) => (
            <tr key={run.id}>
              <td>
                <InlineCopyText copyLabel="Copy run ID">{run.id}</InlineCopyText>
              </td>
              <td>{run.chip}</td>
              <td>{run.status}</td>
            </tr>
          ))}
          <tr>
            <td>
              <InlineCopyText copyLabel="Copy run ID">run_9c4d2e1f-0a7b-4c3e-9f12-6b8a5d3e7c01</InlineCopyText>
            </td>
            <td>Chip 16</td>
            <td>Queued</td>
          </tr>
        </tbody>
      </Table>
    </div>
  );
}

In a heading

It takes the heading's font, and the icon is the size of its text.

cand_2291a

import { Text } from "@etched/monet/text";
import { InlineCopyText } from "@etched/monet/inline-copy-text";

export function InAHeading() {
  return (
    <Text as="h2" variant="heading2">
      <InlineCopyText copyLabel="Copy candidate ID">cand_2291a</InlineCopyText>
    </Text>
  );
}

Copy another value

textToCopy is copied in place of the text shown. It is required when the children are not plain text.

Commit 9f86d08
import { InlineCopyText } from "@etched/monet/inline-copy-text";

export function CopyAnotherValue() {
  return (
    <InlineCopyText copyLabel="Copy commit" textToCopy="9f86d081884c7d659a2feaa0c55ad015a3bf4f1b">
      <span>
        Commit <strong>9f86d08</strong>
      </span>
    </InlineCopyText>
  );
}

Accessibility

  • The copy button is a native button: Enter and Space copy. If the clipboard fails, the value is selected and focused for Ctrl+C or ⌘C.
  • The button is named by copyLabel (default "Copy to clipboard") and described by the text. The text stays plain text, so a heading or cell keeps its name.
  • Screen readers hear "Copied" through the component's own polite live region, or "Press Ctrl+C to copy" ("⌘C" on a Mac) when the clipboard fails.
  • The button stays in the tab order while it is hidden, and shows on focus.
  • Set copyLabel to say what it copies, such as "Copy run ID", so many buttons in a table do not sound the same.

API reference

PropTypeDefaultDescription
childrenstring | Exclude<ReactNode, string>–The text shown. It is copied unless textToCopy is set.
textToCopystring–Copied in place of the text, as on ClipboardText.
onCopy() => void–Called after each copy.
copyLabelstring"Copy to clipboard"Names the copy button.
copiedLabelstring"Copied"What screen readers hear after a copy.
copyKeysLabel(keys: string) => string"Press ⌘C to copy"Shown when the clipboard fails, with this device's copy keys ("⌘C" or "Ctrl+C").
truncatebooleantrueEnds the text in an ellipsis when its box is too narrow.