Vercel/src/components/LinkWithStatus.tsx
2025-04-12 13:15:34 -05:00

46 lines
1.3 KiB
TypeScript

'use client';
import { ComponentProps, ReactNode, useState } from 'react';
import Link from 'next/link';
import LinkWithStatusChild from './primitives/LinkWithStatusChild';
import clsx from 'clsx/lite';
export default function LinkWithStatus({
children,
className,
loadingClassName,
isLoading: isLoadingProp = false,
setIsLoading: setIsLoadingProp,
...props
}: Omit<ComponentProps<typeof Link>, 'children'> & {
children: ReactNode | ((props: { isLoading: boolean }) => ReactNode)
loadingClassName?: string
// For hoisting state to a parent component, e.g., <EntityLink />
isLoading?: boolean
setIsLoading?: (isLoading: boolean) => void
}) {
const [_isLoading, _setIsLoading] = useState(false);
const isLoading = isLoadingProp || _isLoading;
const setIsLoading = setIsLoadingProp || _setIsLoading;
const isControlled = typeof children === 'function';
return <Link
{...props}
className={clsx(
'transition-[colors,opacity]',
(loadingClassName || isControlled)
? 'opacity-100'
: isLoading ? 'opacity-50' : 'opacity-100',
className,
isLoading && loadingClassName,
)}
>
<LinkWithStatusChild {...{ setIsLoading }}>
{typeof children === 'function'
? children({ isLoading })
: children}
</LinkWithStatusChild>
</Link>;
}