feat: Add EnlargableImage component for ExtractionStage (#61)

- Created `EnlargableImage` component in `src/ui/components/EnlargableImage.tsx`.
- Updated `ExtractionStage` to use `EnlargableImage` for displaying extraction results.
- Supports full-screen image viewing with zoom-in/out cursors and click-to-close behavior.

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
This commit is contained in:
google-labs-jules[bot] authored and GitHub committed 2026-02-22 17:15:47 +08:00
1 parent a44ab5168d
commit 31771d0ffa
2 files changed
+62 -2

No files matched your search

+58
View File
@@ -0,0 +1,58 @@
import {
Dialog,
DialogContent,
DialogTitle,
DialogTrigger,
} from "@/ui/components/ui/dialog";
import { cn } from "@/ui/lib/utils";
import React, { useState } from "react";
interface EnlargableImageProps {
src: string;
alt: string;
className?: string;
imageClassName?: string;
}
export function EnlargableImage({
src,
alt,
className,
imageClassName,
}: EnlargableImageProps) {
const [open, setOpen] = useState(false);
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<div
className={cn(
"relative cursor-zoom-in group overflow-hidden rounded-lg border border-slate-200 bg-slate-50",
className,
)}
>
<img
src={src}
alt={alt}
className={cn("w-full h-full object-contain", imageClassName)}
/>
<div className="absolute inset-0 bg-black/0 group-hover:bg-black/5 transition-colors pointer-events-none" />
</div>
</DialogTrigger>
<DialogContent
className="!max-w-[70vw] p-0 bg-black/90 border-none flex items-center justify-center outline-none [&>button:first-of-type]:hidden cursor-zoom-out"
onClick={() => setOpen(false)}
showCloseButton={false}
>
<DialogTitle className="sr-only">{alt} Fullscreen</DialogTitle>
<div className="flex h-[80vh] w-[80vw] items-center justify-center">
<img
src={src}
alt={`${alt} Fullscreen`}
className="w-full h-full object-contain"
/>
</div>
</DialogContent>
</Dialog>
);
}
@@ -2,6 +2,7 @@ import { CheckCircle2, Loader2, RefreshCw, XCircle } from 'lucide-react'
import React, { useState } from 'react'
import { cn } from '../../lib/utils'
import { CandidateAsset, ExtractedAsset } from '../../types'
import { EnlargableImage } from '../EnlargableImage'
import { Button } from '../ui/button'
import { Checkbox } from '../ui/checkbox'
import {
@@ -105,10 +106,11 @@ export const ExtractionStage: React.FC<ExtractionStageProps> = ({
/>
{isDone && result?.imageUrl ? (
<img
<EnlargableImage
src={result.imageUrl}
alt={candidate.name}
className="w-full h-full object-contain p-1"
className="w-full h-full border-none bg-transparent rounded-none"
imageClassName="p-1"
/>
) : (
<div className="flex flex-col items-center gap-2 text-slate-400">