From 6ac797d5ac3c3b718dae12010daa5e5653d488d0 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Wed, 18 Jun 2025 09:23:20 -0500 Subject: [PATCH] Refine uploads layout --- src/admin/AddButton.tsx | 9 +- src/admin/AdminBatchUploadActions.tsx | 1 + src/admin/AdminUploadsTable.tsx | 10 +- src/admin/AdminUploadsTableRow.tsx | 126 ++++++++++-------- src/admin/DeleteUploadButton.tsx | 2 - src/admin/EditButton.tsx | 12 +- src/components/primitives/LoaderButton.tsx | 6 +- .../primitives/PathLoaderButton.tsx | 4 +- 8 files changed, 95 insertions(+), 75 deletions(-) diff --git a/src/admin/AddButton.tsx b/src/admin/AddButton.tsx index 07973c14..11f154f3 100644 --- a/src/admin/AddButton.tsx +++ b/src/admin/AddButton.tsx @@ -2,9 +2,10 @@ import { BiImageAdd } from 'react-icons/bi'; import PathLoaderButton from '@/components/primitives/PathLoaderButton'; import { ComponentProps } from 'react'; -export default function AddButton( - props: ComponentProps, -) { +export default function AddButton({ + children, + ...props +}: ComponentProps) { return ( } > - Add + {children || 'Add'} ); } diff --git a/src/admin/AdminBatchUploadActions.tsx b/src/admin/AdminBatchUploadActions.tsx index f0ea10d1..38ff6221 100644 --- a/src/admin/AdminBatchUploadActions.tsx +++ b/src/admin/AdminBatchUploadActions.tsx @@ -149,6 +149,7 @@ export default function AdminBatchUploadActions({ onChange={setTags} onError={setTagErrorMessage} readOnly={isAdding} + className="relative z-10" />
void + setUrlAddStatuses?: Dispatch> isDeleting?: boolean - setIsDeleting?: (isDeleting: boolean) => void + setIsDeleting?: Dispatch> }) { const isComplete = urlAddStatuses.every(({ status }) => status === 'added'); return (
- {urlAddStatuses.map(status => + {urlAddStatuses.map((status, index) => , diff --git a/src/admin/AdminUploadsTableRow.tsx b/src/admin/AdminUploadsTableRow.tsx index b9f3dd50..18e666c7 100644 --- a/src/admin/AdminUploadsTableRow.tsx +++ b/src/admin/AdminUploadsTableRow.tsx @@ -11,9 +11,10 @@ import { FaRegCircleCheck } from 'react-icons/fa6'; import AddButton from './AddButton'; import { pathForAdminUploadUrl } from '@/app/paths'; import DeleteBlobButton from './DeleteUploadButton'; -import { useEffect, useRef } from 'react'; +import { Dispatch, SetStateAction, useEffect, useRef } from 'react'; import { isElementEntirelyInViewport } from '@/utility/dom'; import FieldSetWithStatus from '@/components/FieldSetWithStatus'; +import EditButton from './EditButton'; export default function AdminUploadsTableRow({ url, @@ -22,19 +23,21 @@ export default function AdminUploadsTableRow({ draftTitle = '', uploadedAt, size, + tabIndex, + shouldRedirectToAdminPhotosOnDelete, isAdding, isDeleting, isComplete, setIsDeleting, - urlAddStatuses, setUrlAddStatuses, }: UrlAddStatus & { + tabIndex: number + shouldRedirectToAdminPhotosOnDelete: boolean isAdding?: boolean isDeleting?: boolean isComplete?: boolean - setIsDeleting?: (isDeleting: boolean) => void - urlAddStatuses: UrlAddStatus[] - setUrlAddStatuses?: (urlAddStatuses: UrlAddStatus[]) => void + setIsDeleting?: Dispatch> + setUrlAddStatuses?: Dispatch> }) { const ref = useRef(null); @@ -75,11 +78,67 @@ export default function AdminUploadsTableRow({ />
-
+
+
+ { + setUrlAddStatuses?.(statuses => statuses.map(status => ({ + ...status, + draftTitle: status.url === url + ? titleUpdated + : status.draftTitle, + }))); + }} + placeholder="Title (optional)" + tabIndex={tabIndex} + readOnly={isAdding || isDeleting || isComplete || Boolean(status)} + hideLabel + /> +
+ {isAdding || isComplete + ? <> + {status === 'added' + ? + : status === 'adding' && + } + + : <> + + + setIsDeleting?.(true)} + onDelete={() => { + setIsDeleting?.(false); + setUrlAddStatuses?.(statuses => statuses + .filter(({ url: urlToRemove }) => urlToRemove !== url)); + }} + isLoading={isDeleting} + tooltip="Delete upload" + /> + } +
+
{uploadedAt - ? + ? : '—'}
{size @@ -101,55 +163,7 @@ export default function AdminUploadsTableRow({
}
- { - setUrlAddStatuses?.(urlAddStatuses.map(status => ({ - ...status, - draftTitle: status.url === url - ? titleUpdated - : status.draftTitle, - }))); - }} - placeholder="Title (optional)" - tabIndex={urlAddStatuses - .findIndex(status => status.url === url) + 1} - hideLabel - />
- - {isAdding || isComplete - ? <> - {status === 'added' - ? - : status === 'adding' && - } - - : <> - - setIsDeleting?.(true)} - onDelete={() => { - setIsDeleting?.(false); - setUrlAddStatuses?.(urlAddStatuses - .filter(({ url: urlToRemove }) => - urlToRemove !== url)); - }} - isLoading={isDeleting} - /> - } -
); diff --git a/src/admin/DeleteUploadButton.tsx b/src/admin/DeleteUploadButton.tsx index 0480512f..80115375 100644 --- a/src/admin/DeleteUploadButton.tsx +++ b/src/admin/DeleteUploadButton.tsx @@ -12,7 +12,6 @@ export default function DeleteUploadButton({ shouldRedirectToAdminPhotos, onDeleteStart, onDelete, - hideTextOnMobile, children, isLoading, ...props @@ -50,7 +49,6 @@ export default function DeleteUploadButton({ }); }} isLoading={isLoading ?? isDeleting} - hideTextOnMobile={hideTextOnMobile} > {children} diff --git a/src/admin/EditButton.tsx b/src/admin/EditButton.tsx index d6779352..6074a1e3 100644 --- a/src/admin/EditButton.tsx +++ b/src/admin/EditButton.tsx @@ -1,17 +1,19 @@ import IconEdit from '@/components/icons/IconEdit'; import PathLoaderButton from '@/components/primitives/PathLoaderButton'; +import { ComponentProps } from 'react'; export default function EditButton ({ - path, + children, + ...props }: { - path: string, -}) { + hideText?: boolean +} & ComponentProps) { return ( } > - Edit + {children || 'Edit'} ); } diff --git a/src/components/primitives/LoaderButton.tsx b/src/components/primitives/LoaderButton.tsx index d8cb284e..c4b69f14 100644 --- a/src/components/primitives/LoaderButton.tsx +++ b/src/components/primitives/LoaderButton.tsx @@ -69,7 +69,7 @@ export default function LoaderButton({ ), styleAs === 'link' && 'hover:text-dim', styleAs === 'link-without-hover' && 'hover:text-main', - 'inline-flex items-center gap-2 self-start whitespace-nowrap', + 'inline-flex items-center gap-1.5 self-start whitespace-nowrap', primary && 'primary', hideFocusOutline && 'focus:outline-hidden', className, @@ -88,7 +88,7 @@ export default function LoaderButton({ size={14} color={spinnerColor} className={clsx( - 'translate-y-[1px]', + 'translate-y-[0.5px]', spinnerClassName, )} /> @@ -96,7 +96,7 @@ export default function LoaderButton({ } {children && {children} } diff --git a/src/components/primitives/PathLoaderButton.tsx b/src/components/primitives/PathLoaderButton.tsx index cd15085c..0851d3e0 100644 --- a/src/components/primitives/PathLoaderButton.tsx +++ b/src/components/primitives/PathLoaderButton.tsx @@ -11,6 +11,7 @@ export default function PathLoaderButton({ shouldScroll = true, shouldReplace, isLoading, + onClick, children, ...props }: { @@ -46,7 +47,8 @@ export default function PathLoaderButton({ return ( { + onClick={e => { + onClick?.(e); startTransition(() => { if (shouldReplace) { router.replace(path, { scroll: shouldScroll });