Add loading indicator to share button
This commit is contained in:
parent
f4e4a2f0a4
commit
2e3dc8a47e
@ -79,7 +79,7 @@ export default async function PhotoPage({
|
||||
key={photo.id}
|
||||
photo={photo}
|
||||
priority
|
||||
showShare
|
||||
prefetchShare
|
||||
/>]}
|
||||
/>
|
||||
<SiteGrid
|
||||
|
||||
@ -7,13 +7,19 @@ export default function IconButton({
|
||||
children,
|
||||
onClick,
|
||||
isLoading,
|
||||
className,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
onClick?: () => void
|
||||
isLoading?: boolean
|
||||
className?: string
|
||||
}) {
|
||||
return (
|
||||
<span className="min-w-[1.1rem]">
|
||||
<span className={cc(
|
||||
className,
|
||||
'relative inline-flex items-center justify-center',
|
||||
'min-w-[1.2rem] min-h-[1.3rem]',
|
||||
)}>
|
||||
{!isLoading
|
||||
? <span
|
||||
onClick={onClick}
|
||||
@ -25,7 +31,7 @@ export default function IconButton({
|
||||
{children}
|
||||
</span>
|
||||
: <span className={cc(
|
||||
'inline-block translate-x-[2px] translate-y-[1px]',
|
||||
'inline-block translate-y-[1.5px]',
|
||||
)}>
|
||||
<Spinner size={12} />
|
||||
</span>}
|
||||
|
||||
@ -3,17 +3,17 @@ import SiteGrid from '@/components/SiteGrid';
|
||||
import ImageLarge from '@/components/ImageLarge';
|
||||
import { cc } from '@/utility/css';
|
||||
import Link from 'next/link';
|
||||
import { TbPhotoShare } from 'react-icons/tb';
|
||||
import { routeForPhoto } from '@/site/routes';
|
||||
import SharePhotoButton from './SharePhotoButton';
|
||||
|
||||
export default function PhotoLarge({
|
||||
photo,
|
||||
priority,
|
||||
showShare,
|
||||
prefetchShare,
|
||||
}: {
|
||||
photo: Photo
|
||||
priority?: boolean
|
||||
showShare?: boolean
|
||||
prefetchShare?: boolean
|
||||
}) {
|
||||
const renderMiniGrid = (children: JSX.Element) =>
|
||||
<div className={cc(
|
||||
@ -83,21 +83,12 @@ export default function PhotoLarge({
|
||||
)}>
|
||||
{photo.takenAtNaiveFormatted}
|
||||
</div>
|
||||
{showShare &&
|
||||
<Link
|
||||
href={routeForPhoto(photo, true)}
|
||||
className={cc(
|
||||
'active:translate-y-[1px]',
|
||||
'text-gray-500 active:text-gray-600',
|
||||
'dark:text-gray-400 dark:active:text-gray-300',
|
||||
)}
|
||||
prefetch
|
||||
>
|
||||
<TbPhotoShare
|
||||
className="translate-x-[-1.5px]"
|
||||
size={17}
|
||||
/>
|
||||
</Link>}
|
||||
<div className="-translate-x-1">
|
||||
<SharePhotoButton
|
||||
photo={photo}
|
||||
prefetch={prefetchShare}
|
||||
/>
|
||||
</div>
|
||||
</>)}
|
||||
</div>}
|
||||
/>
|
||||
|
||||
44
src/photo/SharePhotoButton.tsx
Normal file
44
src/photo/SharePhotoButton.tsx
Normal file
@ -0,0 +1,44 @@
|
||||
'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';
|
||||
|
||||
export default function SharePhotoButton({
|
||||
photo,
|
||||
prefetch,
|
||||
}: {
|
||||
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 (
|
||||
<IconButton
|
||||
onClick={() => startTransition(() =>
|
||||
router.push(shareRoute))}
|
||||
isLoading={isPending}
|
||||
className={cc(
|
||||
'active:translate-y-[1px]',
|
||||
'text-gray-500 active:text-gray-600',
|
||||
'dark:text-gray-400 dark:active:text-gray-300',
|
||||
)}
|
||||
>
|
||||
<TbPhotoShare size={17} />
|
||||
</IconButton>
|
||||
);
|
||||
}
|
||||
@ -136,7 +136,7 @@ export default function SiteChecklistClient({
|
||||
<InfoBlock className="my-1.5" padding="tight">
|
||||
<div className="flex items-center gap-4">
|
||||
<span>{secret}</span>
|
||||
<div className="flex items-center gap-1">
|
||||
<div className="flex items-center gap-0.5">
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(secret);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user