ProxMenux/web/components/CopyableCode.tsx

52 lines
1.4 KiB
TypeScript
Raw Permalink Normal View History

2025-02-14 10:54:09 +01:00
"use client"
import type React from "react"
import { useState } from "react"
import { Copy, Check } from "lucide-react"
2025-02-18 11:08:04 +01:00
import { cn } from "@/lib/utils"
2025-02-14 10:54:09 +01:00
interface CopyableCodeProps {
code: string
2025-02-18 11:08:04 +01:00
language?: string
className?: string
2025-02-14 10:54:09 +01:00
}
2025-02-18 11:08:04 +01:00
const CopyableCode: React.FC<CopyableCodeProps> = ({ code, language, className }) => {
2025-02-14 10:54:09 +01:00
const [isCopied, setIsCopied] = useState(false)
const copyToClipboard = async () => {
try {
2025-02-18 11:08:04 +01:00
await navigator.clipboard.writeText(decodeURIComponent(code))
2025-02-14 10:54:09 +01:00
setIsCopied(true)
setTimeout(() => setIsCopied(false), 2000)
} catch (err) {
console.error("Failed to copy text: ", err)
}
}
return (
2025-02-18 11:08:04 +01:00
<div className={cn("relative w-full", className)}>
<pre
className={cn(
2025-02-18 11:16:10 +01:00
"bg-gray-100 p-2 rounded-md",
2025-02-18 11:08:04 +01:00
"text-base",
2025-02-18 11:16:10 +01:00
"w-full overflow-x-auto",
"flex items-center",
2025-02-18 11:08:04 +01:00
language ? `language-${language}` : "",
)}
>
2025-02-18 11:16:10 +01:00
<code className="whitespace-pre flex-1 min-w-0">{decodeURIComponent(code)}</code>
2025-02-18 00:11:52 +01:00
</pre>
2025-02-14 10:54:09 +01:00
<button
onClick={copyToClipboard}
2025-02-18 11:08:04 +01:00
className="absolute top-2 right-2 p-1 bg-white rounded-md shadow-sm hover:bg-gray-100 transition-colors"
aria-label="Copy code"
2025-02-14 10:54:09 +01:00
>
2025-02-18 11:08:04 +01:00
{isCopied ? <Check className="h-4 w-4 text-green-500" /> : <Copy className="h-4 w-4 text-gray-500" />}
2025-02-14 10:54:09 +01:00
</button>
</div>
)
}
export default CopyableCode