Copy Button
The CopyButton component provides a button that copies text to the clipboard when clicked. It includes visual feedback to indicate when the text has been copied successfully. The name prop can be a string or a function that returns a string, allowing for dynamic text generation.
Copy Button with Function Callback
Below are examples showing how to use a function callback for dynamic text generation, including both success and error cases:
Installation
Basic Usage
import { CopyButton } from '@harnessio/ui/components'
return ( <CopyButton name="Text to copy" />)Using Function Callback (Success Case)
You can pass a function to name that returns the text to copy. This is useful when the text needs to be computed dynamically:
import { CopyButton } from '@harnessio/ui/components'
const getTextToCopy = () => { // Compute or retrieve the text dynamically return `Current timestamp: ${Date.now()}`}
return ( <CopyButton name={getTextToCopy} />)Using Function Callback (Error Handling)
If the function throws an error, a toast notification will be displayed to the user:
import { CopyButton } from '@harnessio/ui/components'
const getTextToCopy = () => { // This might throw an error in some cases if (someCondition) { throw new Error('Failed to retrieve text') } return 'Text to copy'}
return ( <CopyButton name={getTextToCopy} />)When an error occurs, a toast with the title “Failed to copy” and the error message will be shown to the user.
Anatomy
CopyButton is the Button rendered iconOnly, wired to the clipboard. It’s composed of:
- Container — the button itself, styled for a single icon via
iconOnly. Its look comes frombuttonVariant(outlineby default) andsize(sm). - Icon — one
IconV2that carries the state: thecopyglyph at rest, swapping to acheckin the success color for about a second right after a copy. - Tooltip — a “Copy” label surfaced on hover and focus, since there’s no visible text.
- Toast (on error) — if resolving the text to copy throws, a danger toast titled “Failed to copy” appears with the error message.
The text to copy comes from name, which is either a string or a function evaluated on click — use the function form when the value is dynamic.
Best practices
Do
- Place a
CopyButtonright next to the value it copies — a token, ID, URL, or code snippet — so it’s clear what will be copied. - Use the function form of
namewhen the value changes or is computed at click time, so the latest value is always what lands on the clipboard. - Rely on the built-in success feedback (the check icon) rather than adding your own “Copied!” messaging next to it.
- Keep it for copy actions only; if the action does more than copy, use a regular Button with a clear label.
Don’t
- Don’t use a
CopyButtonon its own with no nearby context — the icon and its fixed “Copy” label don’t say what gets copied. - Don’t stack several
CopyButtons together without labels beside each one; they’re indistinguishable to sight and to assistive tech. - Don’t lean on it to copy large or complex payloads where the user should see a preview first.
Content
CopyButtonhas no visible text of its own — its tooltip and accessible name are both fixed to “Copy”.- Provide the context in the surrounding UI instead: label the value beside it (“API key”, “Commit SHA”) so the copy target is named on screen.
- Keep any adjacent helper text short and specific to what’s being copied.
Accessibility
CopyButton builds on the icon-only Button, and unlike a bare icon button it sets both a tooltip and an aria-label for you — but both are the fixed word “Copy”.
Keyboard
- It’s a native
<button>: a tab stop that activates with Enter and Space. - The tooltip opens on focus as well as hover, so keyboard users see the “Copy” label when they reach it.
Labeling
- The component always sets
aria-label="Copy"and a “Copy” tooltip, so it has a reliable accessible name out of the box — no extra props needed for a name to exist. - Because that name is just “Copy”, the surrounding UI has to convey what is being copied; name the adjacent value on screen.
Focus & states
- The standard keyboard focus ring (
:focus-visible) shows via the--cn-focustoken. - After a successful copy the icon changes to a check for about a second — this is a purely visual cue.
Known limitations
- The accessible name is always “Copy”. Both the tooltip and
aria-labelare hardcoded, with no prop to customize them, so a screen reader announces only “Copy” with no indication of the target. When the target isn’t obvious from context, name it in nearby visible text. - The success state isn’t announced. The icon swaps to a check for about a second, but there’s no
aria-liveregion or status text, so screen-reader users aren’t told the copy succeeded. - Errors surface only as a toast. If the
namefunction throws, the feedback is a “Failed to copy” toast; whether that reaches assistive tech depends on the toast implementation, and there’s no inline error on the button itself.
Properties
Prop | Required | Default | Type |
|---|---|---|---|
| name | true | string | (() => string) | |
| className | false | string | |
| buttonVariant | false | 'custom' | ButtonProps['variant'] |
| iconSize | false | 'sm' | 'md' | 'xs' | 'sm' | '2xs' | 'lg' | 'xl' |
| onClick | false | (e: MouseEvent) => void | |
| color | false | 'white' | 'gray' | 'white' | 'success' |