Copy Button

Copies a string and says so. Extracted after the same clipboard-plus-timer was written four times in this kit — CodeBlock, Terminal, EnvVars and Message all route through it now.

src/components/ui/copy-button.tsx

About

From the component's own source, where it was written.

Copies a string and says so.

The label changes rather than only the icon, because a tick replacing a clipboard is invisible to a screen reader unless the accessible name changes too — and aria-live on a button is the wrong tool for something the user just did deliberately.

value may be a function, for text that is expensive to build or that must be read at click time rather than at render time.

Install

npx astralyx-ui add copy-button

Usage

import { CopyButton } from '@/components/ui/copy-button'

<CopyButton value={snippet} />
<CopyButton value={() => buildExpensiveText()} showLabel />

Composer

Change the props and the source below follows.

Props
tsx
<CopyButton value="npm i astralyx-ui" showLabel={false} />

Examples

Icon and labelled

API

Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.

CopyButton

Copies a string and says so.

Extends Omit<ButtonProps, 'value' | 'children'>.

PropTypeDefaultDescription
color'neutral' | 'blue' | 'violet' | 'cyan' | 'green' | 'amber' | 'rose' | 'destructive'——
variant'link' | 'default' | 'colored' | 'secondary' | 'outline' | 'ghost''ghost'—
size'sm' | 'default' | 'xs' | 'lg' | 'xl' | 'icon-xs' | 'icon-sm' | 'icon' | 'icon-lg' | 'icon-xl'——
asChildboolean—Render the child element instead of a <button>, keeping the styles.
tintstring—Any CSS colour, used instead of a named color set. Fill, text, tint and border are all derived from it, and every variant keeps working.
valuestring | (() => string)requiredA function is read at click time — for text that is expensive to build or that changes after render.
labelstring'Copy'Wording for both states.
copiedLabelstring'Copied'Wording for both states.
showLabelbooleanfalseRender the label beside the icon. When off it is still the accessible name, which is what changes to "Copied" — a tick replacing a clipboard is invisible to a screen reader.
childrenReactNode——

Behaviour

TopicDetailDescription
useClipboardhookThe underlying hook: clears its timeout on unmount, restarts rather than stacks on a second copy, and reports error when the write is rejected instead of claiming success.