diff --git a/src/components/IconPathButton.tsx b/src/components/IconPathButton.tsx new file mode 100644 index 00000000..01dba9de --- /dev/null +++ b/src/components/IconPathButton.tsx @@ -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 ( + 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} + + ); +} diff --git a/src/photo/SharePhotoButton.tsx b/src/photo/SharePhotoButton.tsx index 7e276d20..3a006683 100644 --- a/src/photo/SharePhotoButton.tsx +++ b/src/photo/SharePhotoButton.tsx @@ -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 ( - 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" + - + ); }