Refactor button loader behavior

This commit is contained in:
Sam Becker 2023-10-21 16:27:07 -05:00
parent eae78d2194
commit 655f91b336
6 changed files with 43 additions and 53 deletions

View File

@ -21,21 +21,26 @@ export default function IconButton({
return (
<span className={cc(
className,
'relative inline-flex items-center justify-center',
'min-w-[1.2rem] min-h-[1.3rem]',
'relative inline-flex items-center',
'w-[1rem] h-[1.1rem]',
)}>
{!isLoading
? <span
? <button
onClick={onClick}
className={cc(
'inline-flex items-center justify-center',
'p-0 border-none shadow-none',
'active:bg-transparent bg-transparent',
'translate-x-[-1px]',
onClick !== undefined && 'cursor-pointer',
'active:opacity-50',
)}
>
{icon}
</span>
</button>
: <span className={cc(
'inline-block translate-y-[1.5px]',
'inline-flex items-center justify-center',
'h-full w-full',
)}>
<Spinner
color={spinnerColor}

View File

@ -4,6 +4,7 @@ import { useRouter } from 'next/navigation';
import IconButton from './IconButton';
import { useEffect, useState, useTransition } from 'react';
import { cc } from '@/utility/css';
import { SpinnerColor } from './Spinner';
export default function IconPathButton({
icon,
@ -12,6 +13,7 @@ export default function IconPathButton({
loaderDelay = 250,
shouldScroll = true,
shouldReplace,
spinnerColor,
}: {
icon: JSX.Element
path: string
@ -19,6 +21,7 @@ export default function IconPathButton({
loaderDelay?: number
shouldScroll?: boolean
shouldReplace?: boolean
spinnerColor?: SpinnerColor
}) {
const router = useRouter();
@ -60,7 +63,7 @@ export default function IconPathButton({
'text-gray-500 active:text-gray-600',
'dark:text-gray-400 dark:active:text-gray-300',
)}
spinnerColor="text"
spinnerColor={spinnerColor ?? 'text'}
/>
);
}

View File

@ -21,6 +21,7 @@ export default function ShareButton({
prefetch,
shouldScroll,
shouldReplace: true,
spinnerColor: 'dim',
}} />
);
}

View File

@ -1,25 +1,33 @@
import { cc } from '@/utility/css';
const SIZE_DEFAULT = 12;
export type SpinnerColor = 'text' | 'light-gray';
export type SpinnerColor = 'text' | 'dim' | 'light-gray';
export default function Spinner({
size = SIZE_DEFAULT,
color = 'light-gray',
className,
}: {
size?: number
color?: SpinnerColor
className?: string
}) {
return (
<span {...{
...color === 'light-gray' && {
className: 'text-gray-300 dark:text-gray-600',
},
style: {
<span
className={cc(
className,
color === 'light-gray' &&
'text-gray-300 dark:text-gray-600',
color === 'dim' &&
'text-dim',
)}
style={{
display: 'inline-flex',
width: size,
height: size,
},
}}>
}}
>
<svg
width={size}
height={size}

View File

@ -31,12 +31,12 @@ export default function PhotoLarge({
const camera = cameraFromPhoto(photo);
const renderMiniGrid = (children: JSX.Element) =>
const renderMiniGrid = (children: JSX.Element, rightPadding = true) =>
<div className={cc(
'flex gap-y-4',
'flex-col sm:flex-row md:flex-col',
'[&>*]:sm:flex-grow',
'pr-2',
rightPadding && 'pr-2',
)}>
{children}
</div>;
@ -114,19 +114,17 @@ export default function PhotoLarge({
)}>
{photo.takenAtNaiveFormatted}
</div>
<div className="-translate-x-0.5">
<ShareButton
path={pathForPhotoShare(
photo,
tag,
shareCamera ? camera : undefined,
)}
prefetch={prefetchShare}
shouldScroll={shouldScrollOnShare}
/>
</div>
<ShareButton
path={pathForPhotoShare(
photo,
tag,
shareCamera ? camera : undefined,
)}
prefetch={prefetchShare}
shouldScroll={shouldScrollOnShare}
/>
</div>
</>)}
</>, false)}
</div>}
/>
);

View File

@ -1,25 +0,0 @@
import { Photo } from '.';
import { pathForPhotoShare } from '@/site/paths';
import { TbPhotoShare } from 'react-icons/tb';
import IconPathButton from '@/components/IconPathButton';
export default function SharePhotoButton({
photo,
tag,
prefetch,
shouldScroll,
}: {
photo: Photo
tag?: string
prefetch?: boolean
shouldScroll?: boolean
}) {
return (
<IconPathButton
icon={<TbPhotoShare size={17} />}
path={pathForPhotoShare(photo, tag)}
prefetch={prefetch}
shouldScroll={shouldScroll}
/>
);
}