import { Combobox, Dialog, Transition } from "@headlessui/react"; import { MagnifyingGlassIcon } from "@heroicons/react/20/solid"; import { Dispatch, Fragment, SetStateAction } from "react"; const people = [ { id: 1, name: "Leslie Alexander", url: "#" }, // More people... ]; function classNames(...classes: (string | boolean)[]) { return classes.filter(Boolean).join(" "); } export default function CommandPalette({ open, setOpen, query, setQuery, }: { open: boolean; setOpen: Dispatch<SetStateAction<boolean>>; query: string; setQuery: Dispatch<SetStateAction<string>>; }) { const filteredPeople = query === "" ? [] : people.filter((person) => { return person.name.toLowerCase().includes(query.toLowerCase()); }); return ( <Transition.Root show={open} as={Fragment} afterLeave={() => setQuery("")} appear > <Dialog className="relative z-10" onClose={setOpen}> <Transition.Child as={Fragment} enter="ease-out duration-300" enterFrom="opacity-0" enterTo="opacity-100" leave="ease-in duration-200" leaveFrom="opacity-100" leaveTo="opacity-0" > <div className="fixed inset-0 bg-gray-500 bg-opacity-25 transition-opacity" /> </Transition.Child> <div className="fixed inset-0 z-10 w-screen overflow-y-auto p-4 sm:p-6 md:p-20"> <Transition.Child as={Fragment} enter="ease-out duration-300" enterFrom="opacity-0 scale-95" enterTo="opacity-100 scale-100" leave="ease-in duration-200" leaveFrom="opacity-100 scale-100" leaveTo="opacity-0 scale-95" > <Dialog.Panel className="mx-auto max-w-xl transform divide-y divide-gray-100 overflow-hidden rounded-xl bg-white shadow-2xl ring-1 ring-black ring-opacity-5 transition-all"> <Combobox onChange={(option) => (window.location = option.url)}> <div className="relative"> <MagnifyingGlassIcon className="pointer-events-none absolute left-4 top-3.5 h-5 w-5 text-gray-400" aria-hidden="true" /> <Combobox.Input className="h-12 w-full border-0 bg-transparent pl-11 pr-4 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm" placeholder="Search..." onChange={(event) => setQuery(event.target.value)} onBlur={() => setQuery("")} /> </div> <CommandPaletteOptionsContainer query={query} options={filteredPeople} /> {query !== "" && filteredPeople.length === 0 && ( <p className="p-4 text-sm text-gray-500">No people found.</p> )} </Combobox> </Dialog.Panel> </Transition.Child> </div> </Dialog> </Transition.Root> ); } const CommandPaletteOptionsContainer = ({ query, options, }: { query: string; options: any[]; }) => { if (options.length > 0) return ( <Combobox.Options static className="max-h-72 scroll-py-2 overflow-y-auto py-2 text-sm text-gray-800" > {options.map((option, idx) => ( <Combobox.Option key={idx} value={option} className={({ active }) => classNames( "cursor-default select-none px-4 py-2", active && "bg-indigo-600 text-white" ) } > {option.name} </Combobox.Option> ))} </Combobox.Options> ); if (query !== "" && options.length === 0) return <p className="p-4 text-sm text-gray-500">No results found.</p>; };