Vercel/src/components/IconPathButton.tsx

70 lines
1.6 KiB
TypeScript

'use client';
import { useRouter } from 'next/navigation';
import IconButton from './IconButton';
import { useEffect, useState, useTransition } from 'react';
import { clsx } from 'clsx/lite';
import { SpinnerColor } from './Spinner';
export default function IconPathButton({
icon,
path,
prefetch,
loaderDelay = 250,
shouldScroll = true,
shouldReplace,
spinnerColor,
}: {
icon: JSX.Element
path: string
prefetch?: boolean
loaderDelay?: number
shouldScroll?: boolean
shouldReplace?: boolean
spinnerColor?: SpinnerColor
}) {
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
icon={icon}
onClick={() => startTransition(() => {
if (shouldReplace) {
router.replace(path, { scroll: shouldScroll });
} else {
router.push(path, { scroll: shouldScroll });
}
})}
isLoading={shouldShowLoader}
className={clsx(
'translate-y-[-0.5px]',
'active:translate-y-[1px]',
'text-medium',
'active:text-gray-600 dark:active:text-gray-300',
)}
spinnerColor={spinnerColor ?? 'text'}
/>
);
}