|
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"; |
|
import { ScrollArea } from "@/components/ui/scroll-area"; |
|
import { ExternalLink } from "lucide-react"; |
|
import { motion, AnimatePresence } from "framer-motion"; |
|
|
|
interface Source { |
|
title: string; |
|
url: string; |
|
snippet: string; |
|
} |
|
|
|
interface SourcePreviewModalProps { |
|
source: Source | null; |
|
isOpen: boolean; |
|
onClose: () => void; |
|
} |
|
|
|
export function SourcePreviewModal({ source, isOpen, onClose }: SourcePreviewModalProps) { |
|
if (!source) return null; |
|
|
|
return ( |
|
<AnimatePresence> |
|
{isOpen && ( |
|
<Dialog open={isOpen} onOpenChange={onClose}> |
|
<DialogContent className="max-w-3xl h-[80vh] flex flex-col"> |
|
<DialogHeader> |
|
<motion.div |
|
initial={{ opacity: 0, y: -20 }} |
|
animate={{ opacity: 1, y: 0 }} |
|
transition={{ duration: 0.2 }} |
|
> |
|
<DialogTitle className="text-xl font-semibold mb-2"> |
|
{source.title} |
|
</DialogTitle> |
|
<a |
|
href={source.url} |
|
target="_blank" |
|
rel="noopener noreferrer" |
|
className="text-sm text-muted-foreground hover:text-primary flex items-center gap-2" |
|
> |
|
<span className="truncate">{source.url}</span> |
|
<ExternalLink className="h-4 w-4" /> |
|
</a> |
|
</motion.div> |
|
</DialogHeader> |
|
|
|
<ScrollArea className="flex-1 mt-4"> |
|
<motion.div |
|
initial={{ opacity: 0 }} |
|
animate={{ opacity: 1 }} |
|
transition={{ duration: 0.3, delay: 0.1 }} |
|
className="prose prose-slate dark:prose-invert max-w-none" |
|
> |
|
<div className="space-y-4"> |
|
<p className="text-base leading-relaxed"> |
|
{source.snippet} |
|
</p> |
|
{/* TODO: Add full content preview when available */} |
|
</div> |
|
</motion.div> |
|
</ScrollArea> |
|
</DialogContent> |
|
</Dialog> |
|
)} |
|
</AnimatePresence> |
|
); |
|
} |
|
|