diff --git a/src/components/ImageBlurFallback.tsx b/src/components/ImageBlurFallback.tsx index 1b1162e8..64d1c4ef 100644 --- a/src/components/ImageBlurFallback.tsx +++ b/src/components/ImageBlurFallback.tsx @@ -1,22 +1,87 @@ +'use client'; + +/* eslint-disable jsx-a11y/alt-text */ import { BLUR_ENABLED } from '@/site/config'; import { clsx} from 'clsx/lite'; import Image, { ImageProps } from 'next/image'; +import { useEffect, useRef, useState } from 'react'; export default function ImageBlurFallback(props: ImageProps) { + const { + className, + priority, + blurDataURL, + ...rest + } = props; + + const [wasCached, setWasCached] = useState(true); + const [isLoading, setIsLoading] = useState(true); + const [didError, setDidError] = useState(false); + + const [hideBlurPlaceholder, setHideBlurPlaceholder] = useState(false); + + const imageClassName = 'object-cover h-full'; + + const imgRef = useRef(null); + + useEffect(() => { + const timeout = setTimeout( + () => setWasCached(imgRef.current?.complete ?? false), + 100, + ); + return () => clearTimeout(timeout); + }, []); + + useEffect(() => { + if (!isLoading && !didError) { + const timeout = setTimeout(() => { + setHideBlurPlaceholder(true); + }, 1000); + return () => clearTimeout(timeout); + } + }, [isLoading, didError]); + + const showPlaceholder = + !wasCached && + !hideBlurPlaceholder; + return ( - // eslint-disable-next-line jsx-a11y/alt-text - +
+ {showPlaceholder && +
+ {(BLUR_ENABLED && props.blurDataURL) + ? + :
} +
} + setIsLoading(false), + onError: () => setDidError(true), + }} /> +
); } diff --git a/src/components/ImageSmall.tsx b/src/components/ImageSmall.tsx index 5c8cfec8..06e85ed2 100644 --- a/src/components/ImageSmall.tsx +++ b/src/components/ImageSmall.tsx @@ -20,7 +20,6 @@ export default function ImageSmall({ src, alt, blurDataURL: blurData, - placeholder: 'blur', width: IMAGE_SMALL_WIDTH, height: Math.round(IMAGE_SMALL_WIDTH / aspectRatio), }} /> diff --git a/src/components/ImageTiny.tsx b/src/components/ImageTiny.tsx index ac1cbff3..5e976775 100644 --- a/src/components/ImageTiny.tsx +++ b/src/components/ImageTiny.tsx @@ -19,10 +19,7 @@ export default function ImageTiny({ className, src, alt, - ...blurData && { - blurDataURL: blurData, - placeholder: 'blur', - }, + blurDataURL: blurData, width: IMAGE_TINY_WIDTH, height: Math.round(IMAGE_TINY_WIDTH / aspectRatio), }} /> diff --git a/src/photo/PhotoGrid.tsx b/src/photo/PhotoGrid.tsx index fefb0b4e..3927ed01 100644 --- a/src/photo/PhotoGrid.tsx +++ b/src/photo/PhotoGrid.tsx @@ -56,12 +56,7 @@ export default function PhotoGrid({
*]:flex [&>*]:w-full [&>*]:h-full', - '[&>*>*]:object-cover [&>*>*]:min-h-full', - ) + ? 'aspect-square overflow-hidden' : undefined} style={{ ...GRID_ASPECT_RATIO !== 0 && { diff --git a/src/photo/PhotoSmall.tsx b/src/photo/PhotoSmall.tsx index b560de25..c0408f72 100644 --- a/src/photo/PhotoSmall.tsx +++ b/src/photo/PhotoSmall.tsx @@ -5,8 +5,6 @@ import { clsx } from 'clsx/lite'; import { pathForPhoto } from '@/site/paths'; import { Camera } from '@/camera'; import { FilmSimulation } from '@/simulation'; -import AdminPhotoMenu from '@/admin/AdminPhotoMenu'; -import { Suspense } from 'react'; export default function PhotoSmall({ photo, @@ -14,34 +12,23 @@ export default function PhotoSmall({ camera, simulation, selected, - showAdminMenu, }: { photo: Photo tag?: string camera?: Camera simulation?: FilmSimulation selected?: boolean - showAdminMenu?: boolean }) { return ( - - {showAdminMenu && - } -