From 8a6131d539060bcf6ec00e6b5669da33704681aa Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sun, 1 Mar 2026 19:56:07 -0600 Subject: [PATCH] Add photo chooser empty states --- src/components/more/MoreMenu.tsx | 9 ++- src/components/primitives/surface/index.ts | 3 +- src/photo/form/FieldsetPhotoChooser.tsx | 80 +++++++++++++++------- src/photo/usePhotoQuery.ts | 6 ++ 4 files changed, 68 insertions(+), 30 deletions(-) diff --git a/src/components/more/MoreMenu.tsx b/src/components/more/MoreMenu.tsx index 0ab0926f..e02e4056 100644 --- a/src/components/more/MoreMenu.tsx +++ b/src/components/more/MoreMenu.tsx @@ -11,7 +11,7 @@ import { FiMoreHorizontal } from 'react-icons/fi'; import MoreMenuItem from './MoreMenuItem'; import { clearGlobalFocus } from '@/utility/dom'; import { FaChevronRight } from 'react-icons/fa6'; -import { menuSurfaceStyles } from '../primitives/surface'; +import { MENU_SURFACE_STYLES } from '../primitives/surface'; export type MoreMenuSection = { label?: string @@ -101,7 +101,10 @@ export default function MoreMenu({ onCloseAutoFocus={e => e.preventDefault()} align={align} sideOffset={sideOffset} - className={menuSurfaceStyles(className)} + className={clsx( + MENU_SURFACE_STYLES, + className, + )} > {header &&
{item.items.map(item =>
diff --git a/src/components/primitives/surface/index.ts b/src/components/primitives/surface/index.ts index b086f784..183083e1 100644 --- a/src/components/primitives/surface/index.ts +++ b/src/components/primitives/surface/index.ts @@ -1,6 +1,6 @@ import clsx from 'clsx/lite'; -export const menuSurfaceStyles = (className?: string) => clsx( +export const MENU_SURFACE_STYLES = clsx( 'z-10', 'min-w-[8rem]', 'component-surface', @@ -12,5 +12,4 @@ export const menuSurfaceStyles = (className?: string) => clsx( 'data-[side=top]:animate-fade-in-from-bottom', 'data-[side=bottom]:animate-fade-in-from-top', 'data-[side=right]:animate-fade-in-from-top', - className, ); diff --git a/src/photo/form/FieldsetPhotoChooser.tsx b/src/photo/form/FieldsetPhotoChooser.tsx index 02fc4cca..c4154924 100644 --- a/src/photo/form/FieldsetPhotoChooser.tsx +++ b/src/photo/form/FieldsetPhotoChooser.tsx @@ -9,17 +9,16 @@ import { import clsx from 'clsx/lite'; import * as DropdownMenu from '@radix-ui/react-dropdown-menu'; import ImageMedium from '@/components/image/ImageMedium'; -import { menuSurfaceStyles } from '@/components/primitives/surface'; +import { MENU_SURFACE_STYLES } from '@/components/primitives/surface'; import { IoSearch } from 'react-icons/io5'; import { useCallback, useEffect, useRef, useState } from 'react'; import usePhotoQuery from '../usePhotoQuery'; -import { BiChevronDown } from 'react-icons/bi'; +import { BiChevronRight } from 'react-icons/bi'; import SegmentMenu from '@/components/SegmentMenu'; import IconFavs from '@/components/icons/IconFavs'; import InfinitePhotoScroll from '../InfinitePhotoScroll'; - -// TODO: -// Create empty state for all modes, including no search results +import AdminEmptyState from '@/admin/AdminEmptyState'; +import { TbPhotoSearch } from 'react-icons/tb'; type Mode = 'all' | 'favs' | 'search'; @@ -66,6 +65,7 @@ export default function FieldsetPhotoChooser({ photos: photosQuery, isLoading: isLoadingPhotoQuery, reset: resetPhotoQuery, + resultsNotFound, } = usePhotoQuery({ query, isPrivate: true }); const reset = useCallback((resetMenu?: boolean) => { @@ -125,11 +125,18 @@ export default function FieldsetPhotoChooser({ 'font-sans', 'text-xs text-medium font-medium uppercase tracking-wider', 'py-1', + 'select-none', )}> {label} - + e.preventDefault()} align="start" - sideOffset={10} - className={menuSurfaceStyles('z-20 rounded-2xl pb-0 overflow-auto')} + sideOffset={-80} + className={clsx( + MENU_SURFACE_STYLES, + 'z-20 rounded-2xl pb-0 overflow-auto', + )} >
-
- setQuery(e.target.value)} - /> -
-
-
+
+
+ setQuery(e.target.value)} + /> +
+
+ {showQuery && resultsNotFound && + } + className="translate-y-8" + includeContainer={false} + > + No photos found + } + {!showQuery && photosToShow.length === 0 && + } + className="translate-y-16" + includeContainer={false} + > + No photos + }
{photosToShow.map(photo => renderPhotoButton(photo))}
diff --git a/src/photo/usePhotoQuery.ts b/src/photo/usePhotoQuery.ts index eeb425bd..52091c16 100644 --- a/src/photo/usePhotoQuery.ts +++ b/src/photo/usePhotoQuery.ts @@ -28,6 +28,11 @@ export default function usePhotoQuery({ const [photos, setPhotos] = useState([]); + const resultsNotFound = + queryDebounced.length >= minimumQueryLength && + !isLoading && + photos.length === 0; + const reset = useCallback(() => { setPhotos([]); setIsLoading(false); @@ -62,6 +67,7 @@ export default function usePhotoQuery({ queryFormatted, photos, isLoading, + resultsNotFound, reset, }; }