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 Copy the production signing key 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.
| Name | Key | |
|---|---|---|
| Production | lyeve_live_00000000000000 | |
| Staging | lyeve_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
| Prop | Type | Default | Description |
|---|---|---|---|
value required | string | no default | The 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 default | Words beside the icon, such as "Copy all codes". They name the button in place of label. |
title | string | no default | A 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 | number | 14 | Icon size in px. |
class | string | no default | Extra classes on the wrapper. |
Copying from your own control
| Prop | Type | Default | Description |
|---|---|---|---|
new CopyState() | CopyState | no default | A copy and its outcome. Create one per control while the component initializes. |
copy.copy(value) | (string) => Promise<void> | no default | Writes the value, then sets status to "copied" or "failed". |
copy.status | CopyStatus | no default | Reads "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 default | Stops the revert timer. Call it when the component unmounts. |
copyToClipboard(value) | (string) => Promise<boolean> | no default | The write alone. Resolves to whether the copy worked and never throws. |
CopyStatus | 'idle' | 'copied' | 'failed' | no default | Where the last copy stands. |