Skip to content
LyEve UI v0.60.1

Feedback

CopyButton

Copy one value to the clipboard and say whether it landed. The button reverts on its own after a second and a half, and it reports a failure instead of pretending the write happened, which is the case a hand-rolled copy affordance almost always drops.

Basic

Press it. The icon becomes a check and the word appears beside it, then both go away.

https://api.lyeve.com/v1/content/articles

The accessible name stays "Copy" through the copied state. The result is announced by the live region beside the button, and renaming the button as well would say the same word twice and then leave a control called "Copied" that copies.

Naming what is being copied

A page with several of these needs each button to say which value it takes, or a screen reader hears "Copy" three times with nothing to tell them apart. copiedLabel is the confirmation, and it is what the live region announces.

Words beside the icon

text puts words beside the icon, such as "Copy all codes", for a button that is the main action of its block rather than a small affordance next to a value. The words name the button, so the name a voice-control user speaks is the one on screen. label is not used. The confirmation still arrives beside the button, so the words hold still while it shows.

  • 4f7k-29qd
  • h3m8-x6tn
  • p2rc-7vbw
  • k9ze-1jga
  • w5yd-8hcs
  • b6nt-3qmf

A tooltip

title shows a tooltip on hover and on keyboard focus, such as "Copy the signing key" on an icon in a dense row. Use it when the icon alone leaves a sighted reader guessing what the button takes. It never renames the button. The name stays text, or label on an icon alone. When the title says more than that name, a screen reader also hears it as the button's description. A title in the same words as the name is shown and not read twice.

lyeve_live_00000000000000

In a table

At rest the button is the width of its icon and carries no gap, so a column of them lines up. The gap opens only while a message is showing.

NameKey
Productionlyeve_live_00000000000000
Staginglyeve_test_41c8be07a25f93

When the write does not happen

The async clipboard is missing on an origin without TLS, and it refuses while the document is not focused. Either way the button falls back to the browser's older copy command inside the same click, so a console reached over a LAN address still copies. Only when that also refuses does the button show "Copy failed" in the danger color rather than a check, because a user who is told nothing has no way to know whether the value was taken.

Your own copy control

A control the kit does not ship copies through the same write and confirms on the same clock with CopyState. Create one while the component initializes, read its status in markup, and dispose of it when the component unmounts. status reads copied or failed for a second and a half after a copy and idle otherwise.

The button keeps its name through the copy and the status line beside it reports the result, the way CopyButton does. A copy with no control of its own, such as a keyboard shortcut, calls copyToClipboard, the write alone. It resolves to whether the copy worked and never throws.

import { copyToClipboard, toast } from '@lyeve-labs/ui-kit';

if (await copyToClipboard(entry.id)) toast.success('ID copied.');
else toast.error('Copy failed.');

API

PropTypeDefaultDescription
value requiredstring no defaultThe text written to the clipboard.
label string'Copy'The accessible name of a button that shows only its icon. It does not change on a successful copy.
text string no defaultWords beside the icon, such as "Copy all codes". They name the button in place of label.
title string no defaultA tooltip shown on hover and on keyboard focus. It never renames the button. When it says more than the name, it becomes the accessible description.
copiedLabel string'Copied'Shown and announced after a successful copy.
size number14Icon size in px.
class string no defaultExtra classes on the wrapper.

Copying from your own control

PropTypeDefaultDescription
new CopyState() CopyState no defaultA copy and its outcome. Create one per control while the component initializes.
copy.copy(value) (string) => Promise<void> no defaultWrites the value, then sets status to "copied" or "failed".
copy.status CopyStatus no defaultReads "copied" or "failed" for a second and a half after a copy, and "idle" otherwise. It is reactive, so markup that reads it updates.
copy.dispose() () => void no defaultStops the revert timer. Call it when the component unmounts.
copyToClipboard(value) (string) => Promise<boolean> no defaultThe write alone. Resolves to whether the copy worked and never throws.
CopyStatus 'idle' | 'copied' | 'failed' no defaultWhere the last copy stands.