| 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> |
| ); |
| } |
|
|