Delay loader icon when opening share modal
This commit is contained in:
parent
0c8ed7f39c
commit
45a37c9421
58
src/components/IconPathButton.tsx
Normal file
58
src/components/IconPathButton.tsx
Normal file
@ -0,0 +1,58 @@
|
||||
'use client';
|
||||
|
||||
import { useRouter } from 'next/navigation';
|
||||
import IconButton from './IconButton';
|
||||
import { useEffect, useState, useTransition } from 'react';
|
||||
import { cc } from '@/utility/css';
|
||||
|
||||
export default function IconPathButton({
|
||||
path,
|
||||
prefetch,
|
||||
loaderDelay = 250,
|
||||
children,
|
||||
}: {
|
||||
path: string
|
||||
prefetch?: boolean
|
||||
loaderDelay?: number
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
const router = useRouter();
|
||||
|
||||
const [isPending, startTransition] = useTransition();
|
||||
|
||||
const [shouldShowLoader, setShouldShowLoader] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (isPending) {
|
||||
const timeout = setTimeout(() => {
|
||||
setShouldShowLoader(true);
|
||||
}, loaderDelay);
|
||||
return () => clearTimeout(timeout);
|
||||
} else {
|
||||
setShouldShowLoader(false);
|
||||
}
|
||||
}, [isPending, loaderDelay]);
|
||||
|
||||
useEffect(() => {
|
||||
if (prefetch) {
|
||||
router.prefetch(path);
|
||||
}
|
||||
}, [prefetch, router, path]);
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
onClick={() => startTransition(() =>
|
||||
router.push(path))}
|
||||
isLoading={shouldShowLoader}
|
||||
className={cc(
|
||||
'min-h-[1.75rem]',
|
||||
'active:translate-y-[1px]',
|
||||
'text-gray-500 active:text-gray-600',
|
||||
'dark:text-gray-400 dark:active:text-gray-300',
|
||||
)}
|
||||
spinnerColor="text"
|
||||
>
|
||||
{children}
|
||||
</IconButton>
|
||||
);
|
||||
}
|
||||
@ -1,12 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useEffect, useTransition } from 'react';
|
||||
import { Photo } from '.';
|
||||
import { routeForPhoto } from '@/site/routes';
|
||||
import IconButton from '@/components/IconButton';
|
||||
import { TbPhotoShare } from 'react-icons/tb';
|
||||
import { cc } from '@/utility/css';
|
||||
import IconPathButton from '@/components/IconPathButton';
|
||||
|
||||
export default function SharePhotoButton({
|
||||
photo,
|
||||
@ -15,32 +10,12 @@ export default function SharePhotoButton({
|
||||
photo: Photo
|
||||
prefetch?: boolean
|
||||
}) {
|
||||
const router = useRouter();
|
||||
|
||||
const shareRoute = routeForPhoto(photo, true);
|
||||
|
||||
const [isPending, startTransition] = useTransition();
|
||||
|
||||
useEffect(() => {
|
||||
if (prefetch) {
|
||||
router.prefetch(shareRoute);
|
||||
}
|
||||
}, [prefetch, router, shareRoute]);
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
onClick={() => startTransition(() =>
|
||||
router.push(shareRoute))}
|
||||
isLoading={isPending}
|
||||
className={cc(
|
||||
'min-h-[1.75rem]',
|
||||
'active:translate-y-[1px]',
|
||||
'text-gray-500 active:text-gray-600',
|
||||
'dark:text-gray-400 dark:active:text-gray-300',
|
||||
)}
|
||||
spinnerColor="text"
|
||||
<IconPathButton
|
||||
path={routeForPhoto(photo, true)}
|
||||
prefetch={prefetch}
|
||||
>
|
||||
<TbPhotoShare size={17} />
|
||||
</IconButton>
|
||||
</IconPathButton>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user