grain.social is a photo sharing platform built on atproto.
at main 56 lines 1.8 kB view raw
1import { GalleryView } from "$lexicon/types/social/grain/gallery/defs.ts"; 2import { PhotoView } from "$lexicon/types/social/grain/photo/defs.ts"; 3import { Un$Typed } from "$lexicon/util.ts"; 4import { AtUri } from "@atproto/syntax"; 5import { AltTextButton } from "./AltTextButton.tsx"; 6import { PhotoExifButton } from "./PhotoExifButton.tsx"; 7import { RemovePhotoDialogButton } from "./RemovePhotoDialog.tsx"; 8 9export function PhotoPreview({ 10 photo, 11 selectedGallery, 12}: Readonly<{ 13 photo: Un$Typed<PhotoView>; 14 selectedGallery?: GalleryView; 15}>) { 16 const atUri = new AtUri(photo.uri); 17 const did = atUri.hostname; 18 const rkey = atUri.rkey; 19 return ( 20 <div 21 class="relative aspect-square bg-zinc-200 dark:bg-zinc-900" 22 id={`photo-${rkey}`} 23 > 24 {photo.uri ? <AltTextButton photoUri={photo.uri} /> : null} 25 {photo.exif ? <PhotoExifButton photoUri={photo.uri} /> : null} 26 {photo.uri 27 ? ( 28 <RemovePhotoDialogButton 29 selectedGallery={selectedGallery} 30 photoUri={photo.uri} 31 /> 32 ) 33 : null} 34 {photo.uri 35 ? ( 36 <button 37 type="button" 38 hx-get={`/dialogs/gallery/${did}/select?photoUri=${photo.uri}`} 39 hx-trigger="click" 40 hx-target="#layout" 41 hx-swap="afterbegin" 42 class="bg-zinc-950/50 z-10 absolute bottom-2 right-2 cursor-pointer size-4 flex items-center justify-center" 43 > 44 <i class="fas fa-plus text-white"></i> 45 </button> 46 ) 47 : null} 48 <img 49 src={photo.thumb} 50 alt="" 51 data-state={photo.uri ? "complete" : "pending"} 52 class="absolute inset-0 w-full h-full object-contain data-[state=pending]:opacity-50" 53 /> 54 </div> 55 ); 56}