Files
fancy-dns/web/src/components/ui/CopyButton.tsx
T
2026-09-27 11:20:34 +00:00

52 lines
1.3 KiB
TypeScript

import { useEffect, useRef, useState } from 'react'
import { Check, Copy } from 'lucide-react'
import { cn } from '../../lib/cn.ts'
import { IconButton } from './IconButton.tsx'
/** Copies a value (a rule, an address, a key) to the clipboard. */
export function CopyButton({
value,
label = 'Copy',
className,
}: {
value: string
label?: string
className?: string
}) {
const [copied, setCopied] = useState(false)
const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined)
useEffect(() => {
return () => {
if (timer.current !== undefined) clearTimeout(timer.current)
}
}, [])
const copy = (): void => {
const clipboard = navigator?.clipboard
if (!clipboard) return
void clipboard.writeText(value).then(
() => {
setCopied(true)
if (timer.current !== undefined) clearTimeout(timer.current)
timer.current = setTimeout(() => setCopied(false), 1500)
},
() => {
// A denied clipboard permission is not worth a toast; the button just
// does not flip.
},
)
}
return (
<IconButton
icon={copied ? Check : Copy}
label={copied ? 'Copied' : label}
variant="ghost"
size="sm"
onClick={copy}
className={cn(copied && 'text-ok', className)}
/>
)
}