From a055783c26ae4a8f94bf76393ed2d85a2f9da908 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Fri, 23 Feb 2024 12:06:02 -0600 Subject: [PATCH] Fade placeholder blurs --- src/components/ImageBlurFallback.tsx | 84 +++++++++++++++++++++++----- src/photo/PhotoGrid.tsx | 7 +-- src/photo/PhotoSmall.tsx | 17 +----- src/site/index.ts | 2 +- 4 files changed, 75 insertions(+), 35 deletions(-) diff --git a/src/components/ImageBlurFallback.tsx b/src/components/ImageBlurFallback.tsx index 1b1162e8..118d2643 100644 --- a/src/components/ImageBlurFallback.tsx +++ b/src/components/ImageBlurFallback.tsx @@ -1,22 +1,80 @@ +'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 [hideBluePlaceholder, setHideBluePlaceholder] = 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(() => { + setHideBluePlaceholder(true); + }, 1000); + return () => clearTimeout(timeout); + } + }, [isLoading, didError]); + + const showPlaceholder = + BLUR_ENABLED && + props.blurDataURL && + !wasCached && + !hideBluePlaceholder; + return ( - // eslint-disable-next-line jsx-a11y/alt-text - + {showPlaceholder && + } + + onLoad: () => setIsLoading(false), + onError: () => setDidError(true), + }} /> + ); } 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 && - } -