Copy Button
The one copy affordance: a quiet icon button that writes value to the
clipboard, swaps its glyph to a check for a moment, and says Copied to
assistive tech through a polite live region. Ghost at rest so a mono value
stays the loudest thing on its line. LogList, DescriptionList, and
CodeBlock use it; put it after any id or key a user will paste somewhere.
Import
import { CopyButton } from "@photon-ai/pho-ui/components/copy-button";
Sizes
Three square sizes: xs (14px icon, 24px hover wash that overflows the
line) inline after a value, sm (28px, the default) in a row cell or a
panel header, md (32px) in a toolbar.
<CopyButton value={project.id} label="project id" size="xs" />
Props
- value —
string— what goes to the clipboard - label —
string(defaultto clipboard) — what is being copied; read asCopy {label}, then{label} copied - size —
xs/sm/md(defaultsm) - onCopied —
(value: string) => void— after the write lands - …plus any
<button>attribute
The state behind it is useCopy() from @photon-ai/pho-ui/utils: copy(text)
resolves to whether the write landed, and copied holds for
COPY_FEEDBACK_MS (1.5 s) so a control of your own can swap its glyph.
Accessibility
- Named for the thing.
Copy request id, neverCopy; the label is the only thing a screen reader hears. - Feedback in two channels. The glyph turns to a check, and a polite
live region says
Copied. - Refusal is quiet. When the clipboard refuses (no permission, an
insecure page), nothing changes;
onCopiedis not called.
Best practices
- One per value, right after it. A row with three copy buttons is a table.
- Copy the whole value even when the display is masked or truncated; that is what the button is for.