Files
buzz/desktop/src/shared/ui/SimpleImageLightbox.tsx
T

75 lines
2.5 KiB
TypeScript

import type * as React from "react";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { cn } from "@/shared/lib/cn";
import { MODAL_BACKDROP_BLUR_CLASS } from "@/shared/ui/modalBackdrop";
export function SimpleImageLightbox({
alt,
children,
onOpenChange,
open,
src,
}: {
alt: string;
children?: React.ReactNode;
onOpenChange: (open: boolean) => void;
open: boolean;
src: string;
}) {
return (
<DialogPrimitive.Root open={open} onOpenChange={onOpenChange}>
<DialogPrimitive.Portal>
<DialogPrimitive.Overlay
className={cn(
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
MODAL_BACKDROP_BLUR_CLASS,
)}
/>
<DialogPrimitive.Content
className="fixed inset-0 z-50 flex items-center justify-center p-8"
onInteractOutside={(event) => event.preventDefault()}
onPointerDownOutside={(event) => event.preventDefault()}
>
<DialogPrimitive.Title className="sr-only">
{alt}
</DialogPrimitive.Title>
<DialogPrimitive.Description className="sr-only">
Full-size image preview. Press Escape or click outside the image to
close.
</DialogPrimitive.Description>
<DialogPrimitive.Close
aria-label="Close lightbox"
className="absolute inset-0 cursor-default"
/>
{children ?? (
<img
alt={alt}
className="relative max-h-[90vh] max-w-[90vw] rounded-lg object-contain"
src={src}
/>
)}
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white focus:outline-hidden focus:ring-2 focus:ring-white/30">
<svg
aria-hidden="true"
fill="none"
height="20"
viewBox="0 0 24 24"
width="20"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M18 6L6 18M6 6l12 12"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
/>
</svg>
</DialogPrimitive.Close>
</DialogPrimitive.Content>
</DialogPrimitive.Portal>
</DialogPrimitive.Root>
);
}