open-prompt / src /components /prompts /embed-code-generator.tsx
GitHub Action
Automated sync to Hugging Face
bcce530
"use client"
import { useState } from "react"
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { Label } from "@/components/ui/label"
import {
Code,
Copy,
Check,
ExternalLink,
Moon,
Sun
} from "lucide-react"
import { cn } from "@/lib/utils"
interface EmbedCodeGeneratorProps {
promptSlug: string
promptTitle: string
}
export function EmbedCodeGenerator({ promptSlug, promptTitle }: EmbedCodeGeneratorProps) {
const [theme, setTheme] = useState<"light" | "dark">("light")
const [minimal, setMinimal] = useState(false)
const [copied, setCopied] = useState(false)
const baseUrl = typeof window !== 'undefined'
? window.location.origin
: 'https://open-prompt.netlify.app'
const embedUrl = `${baseUrl}/embed/${promptSlug}?theme=${theme}${minimal ? '&minimal=true' : ''}`
const iframeCode = `<iframe
src="${embedUrl}"
width="100%"
height="600"
frameborder="0"
title="${promptTitle}"
style="border-radius: 12px; border: 1px solid #e5e7eb;"
></iframe>`
const copyCode = async () => {
await navigator.clipboard.writeText(iframeCode)
setCopied(true)
setTimeout(() => setCopied(false), 2000)
}
return (
<Card>
<CardHeader>
<CardTitle className="text-lg flex items-center gap-2">
<Code className="h-5 w-5" />
Embed This Prompt
</CardTitle>
<CardDescription>
Add this prompt to your website, blog, or documentation
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
{/* Options */}
<div className="flex flex-wrap gap-4">
<div className="space-y-2">
<Label className="text-sm">Theme</Label>
<div className="flex gap-2">
<Button
variant={theme === "light" ? "default" : "outline"}
size="sm"
onClick={() => setTheme("light")}
className="gap-1"
>
<Sun className="h-4 w-4" />
Light
</Button>
<Button
variant={theme === "dark" ? "default" : "outline"}
size="sm"
onClick={() => setTheme("dark")}
className="gap-1"
>
<Moon className="h-4 w-4" />
Dark
</Button>
</div>
</div>
<div className="space-y-2">
<Label className="text-sm">Style</Label>
<div className="flex gap-2">
<Button
variant={!minimal ? "default" : "outline"}
size="sm"
onClick={() => setMinimal(false)}
>
Full
</Button>
<Button
variant={minimal ? "default" : "outline"}
size="sm"
onClick={() => setMinimal(true)}
>
Minimal
</Button>
</div>
</div>
</div>
{/* Preview Info */}
<div className="p-4 bg-muted rounded-lg">
<p className="text-sm text-muted-foreground mb-2">Preview URL:</p>
<div className="flex items-center gap-2">
<code className="text-xs flex-1 truncate">{embedUrl}</code>
<a
href={embedUrl}
target="_blank"
rel="noopener noreferrer"
className="text-primary hover:underline"
>
<ExternalLink className="h-4 w-4" />
</a>
</div>
</div>
{/* Code Block */}
<div className="relative">
<pre className="p-4 bg-slate-900 text-slate-100 rounded-lg overflow-x-auto text-sm">
<code>{iframeCode}</code>
</pre>
<Button
size="sm"
variant="secondary"
className="absolute top-2 right-2 gap-1"
onClick={copyCode}
>
{copied ? (
<>
<Check className="h-3 w-3" />
Copied!
</>
) : (
<>
<Copy className="h-3 w-3" />
Copy
</>
)}
</Button>
</div>
{/* Footer Note */}
<p className="text-xs text-muted-foreground">
The embed includes a "Powered by OpenPrompt" footer that links back to your prompt.
</p>
</CardContent>
</Card>
)
}