Vercel/src/photo/PhotoLink.tsx
Sam Becker 646f32e642
Rich sort controls (#283)
* Generalize app switcher menus

* Organize sort module

* Build configuration for nav sort control

* Refine sort menu styles

* Upgrade next.js

* Reset custom sort when clicking grid/full a second time

* Light up sort button when overridden
2025-07-15 22:43:36 -05:00

82 lines
2.1 KiB
TypeScript

'use client';
import { ReactNode, ComponentProps, RefObject } from 'react';
import { Photo, titleForPhoto } from '@/photo';
import { PhotoSetCategory } from '@/category';
import { AnimationConfig } from '../components/AnimateItems';
import { useAppState } from '@/app/AppState';
import { pathForPhoto } from '@/app/path';
import { clsx } from 'clsx/lite';
import LinkWithStatus from '@/components/LinkWithStatus';
import Spinner from '@/components/Spinner';
import LinkWithLoaderBackground from '@/components/LinkWithLoaderBackground';
export default function PhotoLink({
ref,
photo,
scroll,
prefetch,
nextPhotoAnimation,
className,
children: _children,
loaderType = 'spinner',
...categories
}: {
ref?: RefObject<HTMLAnchorElement | null>
photo?: Photo
scroll?: boolean
prefetch?: boolean
nextPhotoAnimation?: AnimationConfig
className?: string
children?: ReactNode
loaderType?: 'spinner' | 'badge'
} & PhotoSetCategory) {
const { setNextPhotoAnimation } = useAppState();
const linkProps:
Omit<ComponentProps<typeof LinkWithStatus>, 'children'> |
undefined = photo
? {
ref,
className,
href: pathForPhoto({ photo, ...categories }),
onClick: () => {
if (nextPhotoAnimation) {
setNextPhotoAnimation?.(nextPhotoAnimation);
}
},
scroll,
prefetch,
}
: undefined;
const children = photo
? (_children ?? titleForPhoto(photo))
: _children;
return (
photo && linkProps
? loaderType === 'spinner'
? <LinkWithStatus {...linkProps}>
{({ isLoading }) => <>
{children}
{isLoading && <>
&nbsp;<Spinner className="translate-y-[0.5px]" />
</>}
</>}
</LinkWithStatus>
: <LinkWithLoaderBackground
{...linkProps}
offsetPadding
>
{children}
</LinkWithLoaderBackground>
: <span className={clsx(
'text-gray-300 dark:text-gray-700 cursor-default',
className,
)}>
{children}
</span>
);
};