Refactor button loader behavior
This commit is contained in:
parent
eae78d2194
commit
655f91b336
@ -21,21 +21,26 @@ export default function IconButton({
|
|||||||
return (
|
return (
|
||||||
<span className={cc(
|
<span className={cc(
|
||||||
className,
|
className,
|
||||||
'relative inline-flex items-center justify-center',
|
'relative inline-flex items-center',
|
||||||
'min-w-[1.2rem] min-h-[1.3rem]',
|
'w-[1rem] h-[1.1rem]',
|
||||||
)}>
|
)}>
|
||||||
{!isLoading
|
{!isLoading
|
||||||
? <span
|
? <button
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
className={cc(
|
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',
|
onClick !== undefined && 'cursor-pointer',
|
||||||
'active:opacity-50',
|
'active:opacity-50',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{icon}
|
{icon}
|
||||||
</span>
|
</button>
|
||||||
: <span className={cc(
|
: <span className={cc(
|
||||||
'inline-block translate-y-[1.5px]',
|
'inline-flex items-center justify-center',
|
||||||
|
'h-full w-full',
|
||||||
)}>
|
)}>
|
||||||
<Spinner
|
<Spinner
|
||||||
color={spinnerColor}
|
color={spinnerColor}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { useRouter } from 'next/navigation';
|
|||||||
import IconButton from './IconButton';
|
import IconButton from './IconButton';
|
||||||
import { useEffect, useState, useTransition } from 'react';
|
import { useEffect, useState, useTransition } from 'react';
|
||||||
import { cc } from '@/utility/css';
|
import { cc } from '@/utility/css';
|
||||||
|
import { SpinnerColor } from './Spinner';
|
||||||
|
|
||||||
export default function IconPathButton({
|
export default function IconPathButton({
|
||||||
icon,
|
icon,
|
||||||
@ -12,6 +13,7 @@ export default function IconPathButton({
|
|||||||
loaderDelay = 250,
|
loaderDelay = 250,
|
||||||
shouldScroll = true,
|
shouldScroll = true,
|
||||||
shouldReplace,
|
shouldReplace,
|
||||||
|
spinnerColor,
|
||||||
}: {
|
}: {
|
||||||
icon: JSX.Element
|
icon: JSX.Element
|
||||||
path: string
|
path: string
|
||||||
@ -19,6 +21,7 @@ export default function IconPathButton({
|
|||||||
loaderDelay?: number
|
loaderDelay?: number
|
||||||
shouldScroll?: boolean
|
shouldScroll?: boolean
|
||||||
shouldReplace?: boolean
|
shouldReplace?: boolean
|
||||||
|
spinnerColor?: SpinnerColor
|
||||||
}) {
|
}) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
@ -60,7 +63,7 @@ export default function IconPathButton({
|
|||||||
'text-gray-500 active:text-gray-600',
|
'text-gray-500 active:text-gray-600',
|
||||||
'dark:text-gray-400 dark:active:text-gray-300',
|
'dark:text-gray-400 dark:active:text-gray-300',
|
||||||
)}
|
)}
|
||||||
spinnerColor="text"
|
spinnerColor={spinnerColor ?? 'text'}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,7 @@ export default function ShareButton({
|
|||||||
prefetch,
|
prefetch,
|
||||||
shouldScroll,
|
shouldScroll,
|
||||||
shouldReplace: true,
|
shouldReplace: true,
|
||||||
|
spinnerColor: 'dim',
|
||||||
}} />
|
}} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,25 +1,33 @@
|
|||||||
|
import { cc } from '@/utility/css';
|
||||||
|
|
||||||
const SIZE_DEFAULT = 12;
|
const SIZE_DEFAULT = 12;
|
||||||
|
|
||||||
export type SpinnerColor = 'text' | 'light-gray';
|
export type SpinnerColor = 'text' | 'dim' | 'light-gray';
|
||||||
|
|
||||||
export default function Spinner({
|
export default function Spinner({
|
||||||
size = SIZE_DEFAULT,
|
size = SIZE_DEFAULT,
|
||||||
color = 'light-gray',
|
color = 'light-gray',
|
||||||
|
className,
|
||||||
}: {
|
}: {
|
||||||
size?: number
|
size?: number
|
||||||
color?: SpinnerColor
|
color?: SpinnerColor
|
||||||
|
className?: string
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<span {...{
|
<span
|
||||||
...color === 'light-gray' && {
|
className={cc(
|
||||||
className: 'text-gray-300 dark:text-gray-600',
|
className,
|
||||||
},
|
color === 'light-gray' &&
|
||||||
style: {
|
'text-gray-300 dark:text-gray-600',
|
||||||
|
color === 'dim' &&
|
||||||
|
'text-dim',
|
||||||
|
)}
|
||||||
|
style={{
|
||||||
display: 'inline-flex',
|
display: 'inline-flex',
|
||||||
width: size,
|
width: size,
|
||||||
height: size,
|
height: size,
|
||||||
},
|
}}
|
||||||
}}>
|
>
|
||||||
<svg
|
<svg
|
||||||
width={size}
|
width={size}
|
||||||
height={size}
|
height={size}
|
||||||
|
|||||||
@ -31,12 +31,12 @@ export default function PhotoLarge({
|
|||||||
|
|
||||||
const camera = cameraFromPhoto(photo);
|
const camera = cameraFromPhoto(photo);
|
||||||
|
|
||||||
const renderMiniGrid = (children: JSX.Element) =>
|
const renderMiniGrid = (children: JSX.Element, rightPadding = true) =>
|
||||||
<div className={cc(
|
<div className={cc(
|
||||||
'flex gap-y-4',
|
'flex gap-y-4',
|
||||||
'flex-col sm:flex-row md:flex-col',
|
'flex-col sm:flex-row md:flex-col',
|
||||||
'[&>*]:sm:flex-grow',
|
'[&>*]:sm:flex-grow',
|
||||||
'pr-2',
|
rightPadding && 'pr-2',
|
||||||
)}>
|
)}>
|
||||||
{children}
|
{children}
|
||||||
</div>;
|
</div>;
|
||||||
@ -114,19 +114,17 @@ export default function PhotoLarge({
|
|||||||
)}>
|
)}>
|
||||||
{photo.takenAtNaiveFormatted}
|
{photo.takenAtNaiveFormatted}
|
||||||
</div>
|
</div>
|
||||||
<div className="-translate-x-0.5">
|
<ShareButton
|
||||||
<ShareButton
|
path={pathForPhotoShare(
|
||||||
path={pathForPhotoShare(
|
photo,
|
||||||
photo,
|
tag,
|
||||||
tag,
|
shareCamera ? camera : undefined,
|
||||||
shareCamera ? camera : undefined,
|
)}
|
||||||
)}
|
prefetch={prefetchShare}
|
||||||
prefetch={prefetchShare}
|
shouldScroll={shouldScrollOnShare}
|
||||||
shouldScroll={shouldScrollOnShare}
|
/>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</>)}
|
</>, false)}
|
||||||
</div>}
|
</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