Refine LinkWithStatus behavior

This commit is contained in:
Sam Becker 2025-04-12 13:15:34 -05:00
parent 1eb6a97d24
commit 898d353055
3 changed files with 33 additions and 35 deletions

View File

@ -36,7 +36,7 @@ export default function LinkWithStatus({
isLoading && loadingClassName,
)}
>
<LinkWithStatusChild {...{ isLoading, setIsLoading }}>
<LinkWithStatusChild {...{ setIsLoading }}>
{typeof children === 'function'
? children({ isLoading })
: children}

View File

@ -7,11 +7,9 @@ const FLICKER_THRESHOLD = 400;
export default function LinkWithStatusChild({
children,
isLoading,
setIsLoading,
}: {
children: ReactNode
isLoading: boolean
setIsLoading: (isLoading: boolean) => void
}) {
const { pending } = useLinkStatus();
@ -20,25 +18,22 @@ export default function LinkWithStatusChild({
const stopLoadingTimeout = useRef<NodeJS.Timeout>(undefined);
const isLoadingStartTime = useRef<number>(undefined);
useEffect(() => {
if (isLoading) {
isLoadingStartTime.current = Date.now();
} else {
isLoadingStartTime.current = undefined;
}
}, [isLoading]);
useEffect(() => {
if (pending) {
clearTimeout(stopLoadingTimeout.current);
stopLoadingTimeout.current = undefined;
startLoadingTimeout.current = setTimeout(() => {
setIsLoading(true);
isLoadingStartTime.current = Date.now();
}, FLICKER_THRESHOLD);
} else if (isLoadingStartTime.current) {
} else if (startLoadingTimeout.current) {
clearTimeout(startLoadingTimeout.current);
const loadingDuration = Date.now() - isLoadingStartTime.current;
startLoadingTimeout.current = undefined;
const loadingDuration = Date.now() - (isLoadingStartTime.current ?? 0);
stopLoadingTimeout.current = setTimeout(() => {
setIsLoading(false);
isLoadingStartTime.current = undefined;
}, FLICKER_THRESHOLD - loadingDuration);
}
}, [pending, setIsLoading]);

View File

@ -17,9 +17,8 @@ import {
} from '.';
import { TbChecklist } from 'react-icons/tb';
import CopyButton from '@/components/CopyButton';
import { pathForRecipe } from '@/app/paths';
import LinkWithStatus from '@/components/LinkWithStatus';
import { labelForFilm } from '@/film';
import PhotoRecipe from './PhotoRecipe';
export default function PhotoRecipeOverlay({
ref,
@ -103,20 +102,23 @@ export default function PhotoRecipeOverlay({
'backdrop-blur-xl saturate-[300%]',
)}
>
<div className="flex items-center gap-2 text-black/90">
<div className="grow translate-y-[-0.5px]">
<div className={clsx(
'flex items-center gap-2 h-6',
'pl-1.5 pr-0.5',
)}>
<div className={clsx(
'grow translate-y-[-0.5px]',
'hover:opacity-50 active:opacity-75',
)}>
{title
? <LinkWithStatus
href={pathForRecipe(title ?? '')}
? <PhotoRecipe
recipe={title}
className={clsx(
'flex',
'hover:text-black/50 active:text-black',
'px-1 py-0.5 rounded-md',
'text-[15px]',
'[&>*>*>*]:text-black',
'tracking-wide',
)}
loadingClassName="bg-neutral-100/20"
>
{renderRecipeTitle}
</LinkWithStatus>
/>
: renderRecipeTitle}
</div>
<CopyButton
@ -126,22 +128,23 @@ export default function PhotoRecipeOverlay({
text={generateRecipeText({ title, data, film }).join('\n')}
iconSize={17}
className={clsx(
'translate-y-[0.5px]',
'translate-y-[1.5px]',
'text-black/40 active:text-black/75',
'hover:text-black/40',
)}
tooltip="Copy recipe text"
tooltipColor="frosted"
/>
<LoaderButton
icon={<IoCloseCircle size={20} />}
onClick={onClose}
className={clsx(
'link p-0 m-0 h-4!',
'text-black/40 active:text-black/75',
'translate-y-[2.5px]',
)}
/>
<span>
<LoaderButton
icon={<IoCloseCircle size={20} />}
onClick={onClose}
className={clsx(
'link p-0 m-0',
'text-black/40 active:text-black/75',
)}
/>
</span>
</div>
<div className="grid grid-cols-12 gap-2">
{/* ROW */}