"use client";
import { useState } from "react";
import {
Copy,
Check,
Code,
Link,
FileText,
Braces,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/components/ui/tabs";
import { cn } from "@/lib/utils";
type ContentType = "text" | "code" | "url" | "json";
type CopyContent = {
id: ContentType;
label: string;
icon: React.ElementType;
content: string;
language?: string;
};
const copyContents: CopyContent[] = [
{
id: "text",
label: "Text",
icon: FileText,
content: "Welcome to our platform! Get started by creating your first project and inviting team members to collaborate.",
},
{
id: "code",
label: "Code",
icon: Code,
language: "typescript",
content: `import { useState } from "react";
export function useCounter(initial = 0) {
const [count, setCount] = useState(initial);
const increment = () => setCount(c => c + 1);
const decrement = () => setCount(c => c - 1);
const reset = () => setCount(initial);
return { count, increment, decrement, reset };
}`,
},
{
id: "url",
label: "URL",
icon: Link,
content: "https://example.com/share/abc123?ref=clipboard&utm_source=app",
},
{
id: "json",
label: "JSON",
icon: Braces,
content: JSON.stringify({
name: "Project Alpha",
version: "1.0.0",
description: "A sample project configuration",
settings: {
theme: "dark",
notifications: true,
autoSave: true
},
tags: ["react", "typescript", "tailwind"]
}, null, 2),
},
];
export const title = "React Dialog Block Copy To Clipboard";
export default function DialogCopyToClipboard() {
const [open, setOpen] = useState(false);
const [activeTab, setActiveTab] = useState<ContentType>("code");
const [copiedId, setCopiedId] = useState<ContentType | null>(null);
const handleCopy = async (content: CopyContent) => {
try {
await navigator.clipboard.writeText(content.content);
setCopiedId(content.id);
setTimeout(() => setCopiedId(null), 2000);
} catch (err) {
console.error("Failed to copy:", err);
}
};
const activeContent = copyContents.find((c) => c.id === activeTab);
return (
<Dialog open={open} onOpenChange={setOpen}>
<div className="flex min-h-[350px] items-center justify-center">
<DialogTrigger asChild>
<Button variant="outline">
<Copy className="mr-2 h-4 w-4" />
Copy to Clipboard
</Button>
</DialogTrigger>
</div>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>Copy to Clipboard</DialogTitle>
<DialogDescription>
Select content type and copy to your clipboard.
</DialogDescription>
</DialogHeader>
<Tabs value={activeTab} onValueChange={(v) => setActiveTab(v as ContentType)}>
<TabsList className="grid w-full grid-cols-4">
{copyContents.map((content) => {
const Icon = content.icon;
return (
<TabsTrigger key={content.id} value={content.id} className="text-xs">
<Icon className="mr-1.5 h-3.5 w-3.5" />
{content.label}
</TabsTrigger>
);
})}
</TabsList>
{copyContents.map((content) => (
<TabsContent key={content.id} value={content.id}>
<div
className={cn(
"h-[200px] overflow-auto rounded-lg border p-4 text-sm",
content.id === "code" || content.id === "json"
? "font-mono text-xs"
: ""
)}
>
<pre className={cn(
content.id === "url" || content.id === "text"
? "whitespace-pre-wrap break-all"
: ""
)}>
{content.content}
</pre>
</div>
</TabsContent>
))}
</Tabs>
<DialogFooter>
{activeContent && (
<Button onClick={() => handleCopy(activeContent)} className="w-full">
{copiedId === activeContent.id ? (
<>
<Check className="mr-2 h-4 w-4" />
Copied!
</>
) : (
<>
<Copy className="mr-2 h-4 w-4" />
Copy {activeContent.label}
</>
)}
</Button>
)}
</DialogFooter>
</DialogContent>
</Dialog>
);
}