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"
+
-
+
);
}