From 34a8f2f362e7a7f41e5d4fead920d6345179aec3 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Mon, 17 Mar 2025 20:43:57 -0500 Subject: [PATCH] Make batch edits more discoverable --- src/admin/AdminAppMenu.tsx | 15 ++-- src/admin/AdminBatchEditPanelClient.tsx | 69 ++++++++++--------- src/admin/DeleteButton.tsx | 5 +- src/components/SelectTileOverlay.tsx | 4 +- src/components/icons/IconSelectMultiple.tsx | 28 -------- .../{Checkbox.tsx => SimpleCheckbox.tsx} | 2 +- 6 files changed, 51 insertions(+), 72 deletions(-) delete mode 100644 src/components/icons/IconSelectMultiple.tsx rename src/components/primitives/{Checkbox.tsx => SimpleCheckbox.tsx} (95%) diff --git a/src/admin/AdminAppMenu.tsx b/src/admin/AdminAppMenu.tsx index 68bc42aa..d9b3f119 100644 --- a/src/admin/AdminAppMenu.tsx +++ b/src/admin/AdminAppMenu.tsx @@ -11,13 +11,12 @@ import { PATH_GRID_INFERRED, } from '@/app/paths'; import { useAppState } from '@/state/AppState'; -import { IoArrowDown, IoArrowUp } from 'react-icons/io5'; +import { IoArrowDown, IoArrowUp, IoCloseSharp } from 'react-icons/io5'; import { clsx } from 'clsx/lite'; import AdminAppInfoIcon from './AdminAppInfoIcon'; import { signOutAction } from '@/auth/actions'; import { ComponentProps } from 'react'; import useIsKeyBeingPressed from '@/utility/useIsKeyBeingPressed'; -import IconSelectMultiple from '@/components/icons/IconSelectMultiple'; import IconPhoto from '@/components/icons/IconPhoto'; import IconUpload from '@/components/icons/IconUpload'; import IconRecipe from '@/components/icons/IconRecipe'; @@ -25,6 +24,7 @@ import IconTag from '@/components/icons/IconTag'; import IconFolder from '@/components/icons/IconFolder'; import IconSignOut from '@/components/icons/IconSignOut'; import IconLock from '@/components/icons/IconLock'; +import { IoMdCheckboxOutline } from 'react-icons/io'; export default function AdminAppMenu({ active, @@ -121,9 +121,14 @@ export default function AdminAppMenu({ if (photosCountTotal) { items.push({ label: isSelecting - ? 'Exit Select' - : 'Edit Multiple', - icon: , + ? 'Exit Batch Edit' + : 'Batch Edit ...', + icon: isSelecting + ? + : , href: PATH_GRID_INFERRED, action: () => { if (isSelecting) { diff --git a/src/admin/AdminBatchEditPanelClient.tsx b/src/admin/AdminBatchEditPanelClient.tsx index 0933a397..df29063e 100644 --- a/src/admin/AdminBatchEditPanelClient.tsx +++ b/src/admin/AdminBatchEditPanelClient.tsx @@ -51,6 +51,10 @@ export default function AdminBatchEditPanelClient({ false, ); + const isFormDisabled = + isPerformingSelectEdit || + selectedPhotoIds?.length === 0; + const renderPhotoCTA = () => selectedPhotoIds?.length === 0 ? <> @@ -105,40 +109,37 @@ export default function AdminBatchEditPanelClient({ : <> - {(selectedPhotoIds?.length ?? 0) > 0 && - <> - setIsPerformingSelectEdit?.(true)} - onDelete={resetForm} - onFinish={() => setIsPerformingSelectEdit?.(false)} - /> - } - disabled={isPerformingSelectEdit} - confirmText={`Are you sure you want to favorite ${photosText}?`} - onClick={() => { - setIsPerformingSelectEdit?.(true); - tagMultiplePhotosAction( - TAG_FAVS, - selectedPhotoIds ?? [], - ) - .then(() => { - toastSuccess(`${photosText} favorited`); - resetForm(); - }) - .finally(() => setIsPerformingSelectEdit?.(false)); - }} - /> - setTags('')} - disabled={isPerformingSelectEdit} - icon={} - > - Tag ... - - } + setIsPerformingSelectEdit?.(true)} + onDelete={resetForm} + onFinish={() => setIsPerformingSelectEdit?.(false)} + /> + } + disabled={isFormDisabled} + confirmText={`Are you sure you want to favorite ${photosText}?`} + onClick={() => { + setIsPerformingSelectEdit?.(true); + tagMultiplePhotosAction( + TAG_FAVS, + selectedPhotoIds ?? [], + ) + .then(() => { + toastSuccess(`${photosText} favorited`); + resetForm(); + }) + .finally(() => setIsPerformingSelectEdit?.(false)); + }} + /> + setTags('')} + disabled={isFormDisabled} + icon={} + > + Tag ... + } onClick={() => setSelectedPhotoIds?.(undefined)} diff --git a/src/admin/DeleteButton.tsx b/src/admin/DeleteButton.tsx index b404723e..4d48e4d9 100644 --- a/src/admin/DeleteButton.tsx +++ b/src/admin/DeleteButton.tsx @@ -18,8 +18,9 @@ export default function DeleteButton({ 'active:bg-red-100/50! dark:active:bg-red-950/50!', 'disabled:text-red-500/60! dark:disabled:text-red-500/60!', 'disabled:bg-red-100/50! dark:disabled:bg-red-950/50!', - 'border-red-200! hover:border-red-300!', - 'dark:border-red-900/75! dark:hover:border-red-900!', + 'border-red-200! disabled:border-red-200! hover:border-red-300!', + // eslint-disable-next-line max-len + 'dark:border-red-900/75! dark:disabled:border-red-900/75! dark:hover:border-red-900!', className, )} /> diff --git a/src/components/SelectTileOverlay.tsx b/src/components/SelectTileOverlay.tsx index a0a8771e..a3362853 100644 --- a/src/components/SelectTileOverlay.tsx +++ b/src/components/SelectTileOverlay.tsx @@ -1,7 +1,7 @@ 'use client'; import { clsx } from 'clsx/lite'; -import Checkbox from './primitives/Checkbox'; +import SimpleCheckbox from './primitives/SimpleCheckbox'; import { useAppState } from '@/state/AppState'; import Spinner from './Spinner'; @@ -45,7 +45,7 @@ export default function SelectTileOverlay({ className="m-[1px]" /> : null - : - : ; -} diff --git a/src/components/primitives/Checkbox.tsx b/src/components/primitives/SimpleCheckbox.tsx similarity index 95% rename from src/components/primitives/Checkbox.tsx rename to src/components/primitives/SimpleCheckbox.tsx index 4f0b7c05..382641bf 100644 --- a/src/components/primitives/Checkbox.tsx +++ b/src/components/primitives/SimpleCheckbox.tsx @@ -4,7 +4,7 @@ import { ImCheckboxUnchecked, ImCheckboxChecked } from 'react-icons/im'; const ICON_CLASS_NAME = 'text-[1rem]'; -export default function Checkbox(props: { +export default function SimpleCheckbox(props: { children?: ReactNode } & InputHTMLAttributes) { const {