From 7182e6db0eaf855ff7f3a63a76b58f5df339b9df Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sat, 28 Feb 2026 21:20:54 -0600 Subject: [PATCH] Create custom photo chooser menu --- src/components/SegmentMenu.tsx | 52 +++++++++++ src/photo/form/FieldsetPhotoChooser.tsx | 117 ++++++++++++++---------- 2 files changed, 123 insertions(+), 46 deletions(-) create mode 100644 src/components/SegmentMenu.tsx diff --git a/src/components/SegmentMenu.tsx b/src/components/SegmentMenu.tsx new file mode 100644 index 00000000..2e027bb5 --- /dev/null +++ b/src/components/SegmentMenu.tsx @@ -0,0 +1,52 @@ +import clsx from 'clsx/lite'; +import { ReactNode } from 'react'; + +export default function SegmentMenu({ + items, + selected, + onChange, + className, +}: { + items: { + value: T + icon?: ReactNode + iconSelected?: ReactNode + }[] + selected: T + onChange: (value: T) => void + className?: string +}) { + return ( +
+ {items.map(({ value, icon, iconSelected }) => ( + + ))} +
+ ); +} diff --git a/src/photo/form/FieldsetPhotoChooser.tsx b/src/photo/form/FieldsetPhotoChooser.tsx index 2d5bcae7..aae1b602 100644 --- a/src/photo/form/FieldsetPhotoChooser.tsx +++ b/src/photo/form/FieldsetPhotoChooser.tsx @@ -6,10 +6,34 @@ import ImageMedium from '@/components/image/ImageMedium'; import { menuSurfaceStyles } from '@/components/primitives/surface'; import { GRID_SPACE_CLASSNAME } from '@/components'; import useDynamicPhoto from '../useDynamicPhoto'; -import { IoClose, IoSearch } from 'react-icons/io5'; +import { IoSearch } from 'react-icons/io5'; import { useEffect, useRef, useState } from 'react'; import usePhotoQuery from '../usePhotoQuery'; import Spinner from '@/components/Spinner'; +import { BiChevronDown } from 'react-icons/bi'; +import SegmentMenu from '@/components/SegmentMenu'; +import IconFavs from '@/components/icons/IconFavs'; +import IconLock from '@/components/icons/IconLock'; + +type Mode = 'all' | 'favs' | 'hidden' | 'search'; + +const renderPhoto = ({ + photo, + className, + onClick, +}: { + photo: Photo, + className?: string, + onClick?: () => void, +}) => + ; export default function FieldsetPhotoChooser({ label, @@ -26,10 +50,12 @@ export default function FieldsetPhotoChooser({ photosCount?: number photosHidden?: Photo[] }) { + const [mode, setMode] = useState('all'); + + const showQuery = mode === 'search'; + const inputRef = useRef(null); - const [showQuery, setShowQuery] = useState(true); - // TODO: Move query into hook const [query, setQuery] = useState(''); const { photos: photosQuery, @@ -60,21 +86,27 @@ export default function FieldsetPhotoChooser({ - @@ -83,34 +115,32 @@ export default function FieldsetPhotoChooser({ onCloseAutoFocus={e => e.preventDefault()} align="start" sideOffset={10} - className={menuSurfaceStyles('z-20 px-1.5 py-1.5')} + className={menuSurfaceStyles('z-20 px-1.5 py-1.5 rounded-2xl')} >
-
-
- Choose photo -
- {isLoading - ? - : showQuery - ? setShowQuery(false)} - /> - : setShowQuery(true)} - />} -
+ , + iconSelected: , + }, { + value: 'hidden', + icon: , + }, { + value: 'search', + icon: isLoading + ? + : , + }]} + selected={mode} + onChange={setMode} + /> {showQuery && - onChange(photo.id)} - /> + {renderPhoto({ + photo, + onClick: () => onChange(photo.id), + })} ))}