Refactor button loader behavior
This commit is contained in:
parent
eae78d2194
commit
655f91b336
@ -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}
|
||||
|
||||
@ -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'}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ export default function ShareButton({
|
||||
prefetch,
|
||||
shouldScroll,
|
||||
shouldReplace: true,
|
||||
spinnerColor: 'dim',
|
||||
}} />
|
||||
);
|
||||
}
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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>}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user