Introduce loading status to thumbnails
This commit is contained in:
parent
e1055e0c79
commit
c7576b43ac
@ -17,10 +17,15 @@ const FLICKER_THRESHOLD = 400;
|
||||
// Clear loading status after long duration
|
||||
const MAX_LOADING_DURATION = 15_000;
|
||||
|
||||
export type LinkWithStatusProps = ComponentProps<typeof Link> & {
|
||||
export type LinkWithStatusProps = Omit<
|
||||
ComponentProps<typeof Link>, 'children'
|
||||
> & {
|
||||
loadingElement?: ReactNode
|
||||
loadingClassName?: string
|
||||
contentClassName?: string
|
||||
children: ReactNode | ((props: {
|
||||
isLoading: boolean
|
||||
}) => ReactNode)
|
||||
}
|
||||
|
||||
export default function LinkWithStatus({
|
||||
@ -44,6 +49,8 @@ export default function LinkWithStatus({
|
||||
const stopLoadingTimeout = useRef<NodeJS.Timeout | undefined>(undefined);
|
||||
const maxLoadingTimeout = useRef<NodeJS.Timeout | undefined>(undefined);
|
||||
|
||||
const isControlled = typeof children === 'function';
|
||||
|
||||
const clearTimeouts = useCallback(() => {
|
||||
[startLoadingTimeout, stopLoadingTimeout, maxLoadingTimeout]
|
||||
.forEach(timeout => {
|
||||
@ -114,11 +121,13 @@ export default function LinkWithStatus({
|
||||
contentClassName,
|
||||
loadingElement
|
||||
? isLoading ? 'opacity-0' : 'opacity-100'
|
||||
: loadingClassName
|
||||
: (loadingClassName || isControlled)
|
||||
? 'opacity-100'
|
||||
: isLoading ? 'opacity-50' : 'opacity-100',
|
||||
)}>
|
||||
{children}
|
||||
{typeof children === 'function'
|
||||
? children({ isLoading })
|
||||
: children}
|
||||
</span>
|
||||
{isLoading && loadingElement && <span className={clsx(
|
||||
'absolute inset-0',
|
||||
|
||||
@ -7,12 +7,12 @@ import {
|
||||
doesPhotoNeedBlurCompatibility,
|
||||
} from '.';
|
||||
import ImageMedium from '@/components/image/ImageMedium';
|
||||
import Link from 'next/link';
|
||||
import { clsx } from 'clsx/lite';
|
||||
import { pathForPhoto } from '@/site/paths';
|
||||
import { SHOULD_PREFETCH_ALL_LINKS } from '@/site/config';
|
||||
import { useRef } from 'react';
|
||||
import useOnVisible from '@/utility/useOnVisible';
|
||||
import LinkWithStatus from '@/components/LinkWithStatus';
|
||||
|
||||
export default function PhotoMedium({
|
||||
photo,
|
||||
@ -38,7 +38,7 @@ export default function PhotoMedium({
|
||||
useOnVisible(ref, onVisible);
|
||||
|
||||
return (
|
||||
<Link
|
||||
<LinkWithStatus
|
||||
ref={ref}
|
||||
href={pathForPhoto({ photo, tag, camera, simulation, focal })}
|
||||
className={clsx(
|
||||
@ -58,6 +58,6 @@ export default function PhotoMedium({
|
||||
alt={altTextForPhoto(photo)}
|
||||
priority={priority}
|
||||
/>
|
||||
</Link>
|
||||
</LinkWithStatus>
|
||||
);
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user