Actionsui
Copy button
Copies a value to the clipboard and confirms success or failure.
https://acme-web-8f2ac91d.particular.app
Installation
npx shadcn@latest add @particular/copy-buttonnpm dependencies
- cn@^0.4.0
- lucide-react@^1.51.0
Installs these registry items
Source
"use client"
import * as React from "react"
import { CheckIcon, CopyIcon, XIcon } from "lucide-react"
import { cn } from "cn"
import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard"
import { Button } from "@/components/ui/button"
const statusText = {
idle: "",
copied: "Copied to clipboard",
error: "Copy failed",
} as const
function CopyButton({
value,
label = "Copy",
onCopied,
className,
variant = "ghost",
size = "icon-sm",
children,
...props
}: Omit<React.ComponentProps<typeof Button>, "value" | "onClick" | "onCopy"> & {
value: string
/** Accessible name of the button. */
label?: string
onCopied?: (value: string) => void
}) {
const { status, copy } = useCopyToClipboard()
const Icon = status === "copied" ? CheckIcon : status === "error" ? XIcon : CopyIcon
return (
<Button
data-slot="copy-button"
data-status={status}
variant={variant}
size={size}
aria-label={children ? undefined : label}
className={cn(
"text-muted-foreground hover:text-foreground data-[status=copied]:text-success data-[status=error]:text-destructive",
className
)}
onClick={async () => {
if (await copy(value)) onCopied?.(value)
}}
{...props}
>
<Icon data-icon={children ? "inline-start" : undefined} />
{children}
<span aria-live="polite" className="sr-only">
{statusText[status]}
</span>
</Button>
)
}
export { CopyButton }