diff --git a/src/components/CommandKClient.tsx b/src/components/cmdk/CommandKClient.tsx similarity index 91% rename from src/components/CommandKClient.tsx rename to src/components/cmdk/CommandKClient.tsx index 82a20a24..edcbe431 100644 --- a/src/components/CommandKClient.tsx +++ b/src/components/cmdk/CommandKClient.tsx @@ -18,11 +18,11 @@ import { PATH_SIGN_IN, pathForPhoto, pathForTag, -} from '../site/paths'; -import Modal from './Modal'; +} from '../../site/paths'; +import Modal from '../Modal'; import { clsx } from 'clsx/lite'; import { useDebounce } from 'use-debounce'; -import Spinner from './Spinner'; +import Spinner from '../Spinner'; import { useRouter } from 'next/navigation'; import { useTheme } from 'next-themes'; import { BiDesktop, BiMoon, BiSun } from 'react-icons/bi'; @@ -41,6 +41,7 @@ import { FaCheck } from 'react-icons/fa6'; import { TagsWithMeta, addHiddenToTags, formatTag } from '@/tag'; import { FaTag } from 'react-icons/fa'; import { formatCount, formatCountDescriptive } from '@/utility/string'; +import CommandKItem from './CommandKItem'; const LISTENER_KEYDOWN = 'keydown'; const MINIMUM_QUERY_LENGTH = 2; @@ -373,23 +374,17 @@ export default function CommandKClient({ {items.map(({ label, keywords, + accessory, annotation, annotationAria, - accessory, path, action, }) => - { if (path) { startTransition(() => { @@ -401,23 +396,11 @@ export default function CommandKClient({ action?.(); } }} - > -
- {accessory} - - {label} - - {annotation && - - - {annotation} - - } -
-
)} + accessory={accessory} + annotation={annotation} + annotationAria={annotationAria} + showSpinner={Boolean(path)} + />)} )} {footer && !queryLive &&
diff --git a/src/components/cmdk/CommandKItem.tsx b/src/components/cmdk/CommandKItem.tsx new file mode 100644 index 00000000..9f72f423 --- /dev/null +++ b/src/components/cmdk/CommandKItem.tsx @@ -0,0 +1,65 @@ +import { clsx } from 'clsx/lite'; +import { Command } from 'cmdk'; +import { ReactNode, useState } from 'react'; +import Spinner from '../Spinner'; + +export default function CommandKItem({ + label, + value, + keywords, + onSelect, + accessory, + annotation, + annotationAria, + showSpinner, +}: { + label: string + value: string + keywords?: string[] + onSelect: () => void + accessory?: ReactNode + annotation?: ReactNode + annotationAria?: string + showSpinner?: boolean +}) { + const [isLoading, setIsLoading] = useState(false); + + return ( + { + onSelect?.(); + if (showSpinner) { + setIsLoading(true); + } + }} + > +
+ {accessory} + + {label} + + {annotation && !isLoading && + + + {annotation} + + } + {isLoading && + } +
+
+ ); +} diff --git a/src/site/CommandK.tsx b/src/site/CommandK.tsx index 829f0f73..f7a7c356 100644 --- a/src/site/CommandK.tsx +++ b/src/site/CommandK.tsx @@ -1,4 +1,6 @@ -import CommandKClient, { CommandKSection } from '@/components/CommandKClient'; +import CommandKClient, { + CommandKSection, +} from '@/components/cmdk/CommandKClient'; import { getPhotosMetaCached, getUniqueCamerasCached,