-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ca78129
commit 0db8d6b
Showing
5 changed files
with
315 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
168 changes: 168 additions & 0 deletions
168
apps/crepe/src/app/checkout/components/search-palette.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
"use client"; | ||
|
||
import { | ||
Combobox, | ||
ComboboxInput, | ||
ComboboxOption, | ||
ComboboxOptions, | ||
Dialog, | ||
DialogBackdrop, | ||
DialogPanel, | ||
} from "@headlessui/react"; | ||
import { MagnifyingGlassIcon } from "@heroicons/react/20/solid"; | ||
import { useState } from "react"; | ||
|
||
export type SearchPaletteItem = { | ||
filterString: string; | ||
group: string; | ||
content: React.ReactNode; | ||
onClick: () => void; | ||
}; | ||
|
||
export function SearchPaletteWithGroups({ | ||
items, | ||
open, | ||
onClose, | ||
}: { | ||
items: SearchPaletteItem[]; | ||
open: boolean; | ||
onClose: () => void; | ||
}) { | ||
const [query, setQuery] = useState(""); | ||
|
||
const filteredItems = | ||
query === "" | ||
? [] | ||
: items.filter((item) => { | ||
return item.filterString.toLowerCase().includes(query.toLowerCase()); | ||
}); | ||
|
||
const groups = items.reduce<Record<string, SearchPaletteItem[]>>( | ||
(groups, item) => { | ||
return { | ||
...groups, | ||
[item.group]: [...(groups[item.group] || []), item], | ||
}; | ||
}, | ||
{} | ||
); | ||
|
||
const filteredGroups = filteredItems.reduce< | ||
Record<string, SearchPaletteItem[]> | ||
>((groups, item) => { | ||
return { | ||
...groups, | ||
[item.group]: [...(groups[item.group] || []), item], | ||
}; | ||
}, {}); | ||
|
||
return ( | ||
<Dialog | ||
transition | ||
className="relative z-10" | ||
open={open} | ||
onClose={() => { | ||
onClose(); | ||
setQuery(""); | ||
}} | ||
> | ||
<DialogBackdrop | ||
transition | ||
className="fixed inset-0 bg-gray-500 bg-opacity-25 transition-opacity data-[closed]:opacity-0 data-[enter]:duration-300 data-[leave]:duration-200 data-[enter]:ease-out data-[leave]:ease-in" | ||
/> | ||
|
||
<div className="fixed inset-0 z-10 w-screen overflow-y-auto p-4 sm:p-6 md:p-20"> | ||
<DialogPanel | ||
transition | ||
className="mx-auto max-w-xl transform overflow-hidden rounded-xl bg-white shadow-2xl ring-1 ring-black ring-opacity-5 transition-all data-[closed]:scale-95 data-[closed]:opacity-0 data-[enter]:duration-300 data-[leave]:duration-200 data-[enter]:ease-out data-[leave]:ease-in" | ||
> | ||
<Combobox | ||
onChange={(item: SearchPaletteItem) => { | ||
if (item) item.onClick(); | ||
}} | ||
> | ||
<div className="relative"> | ||
<MagnifyingGlassIcon | ||
className="pointer-events-none absolute left-4 top-3.5 h-5 w-5 text-gray-400" | ||
aria-hidden="true" | ||
/> | ||
<ComboboxInput | ||
autoFocus | ||
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> | ||
|
||
{/* Query is empty. Show all groups */} | ||
{query === "" && ( | ||
<ComboboxOptions | ||
static | ||
as="ul" | ||
className="max-h-80 scroll-pb-2 scroll-pt-11 space-y-2 overflow-y-auto pb-2" | ||
> | ||
{Object.entries(groups).map(([group, items]) => ( | ||
<SearchGroup key={group} group={group} items={items} /> | ||
))} | ||
</ComboboxOptions> | ||
)} | ||
|
||
{/* Query is not empty and there are results. Show filtered groups */} | ||
{filteredItems.length > 0 && ( | ||
<ComboboxOptions | ||
static | ||
as="ul" | ||
className="max-h-80 scroll-pb-2 scroll-pt-11 space-y-2 overflow-y-auto pb-2" | ||
> | ||
{Object.entries(filteredGroups).map(([group, items]) => ( | ||
<SearchGroup key={group} group={group} items={items} /> | ||
))} | ||
</ComboboxOptions> | ||
)} | ||
|
||
{/* Query is not empty and there are no results. Show no results message */} | ||
{query !== "" && filteredItems.length === 0 && ( | ||
<div className="border-t border-gray-100 px-6 pt-8 pb-14 text-center text-sm sm:px-14"> | ||
<p className="mt-4 font-semibold text-gray-900"> | ||
No results found | ||
</p> | ||
<p className="mt-2 text-gray-500"> | ||
This address does not have sufficient balance for this search | ||
result. | ||
</p> | ||
</div> | ||
)} | ||
</Combobox> | ||
</DialogPanel> | ||
</div> | ||
</Dialog> | ||
); | ||
} | ||
|
||
function SearchGroup({ | ||
group, | ||
items, | ||
}: { | ||
group: string; | ||
items: SearchPaletteItem[]; | ||
}) { | ||
return ( | ||
<li key={group}> | ||
<h2 className="bg-gray-100 px-4 py-2.5 text-xs font-semibold text-gray-900 capitalize"> | ||
{group} | ||
</h2> | ||
<ul> | ||
{items.map((item, index) => ( | ||
<ComboboxOption | ||
key={index} | ||
value={item} | ||
className="cursor-pointer select-none px-2 py-1 data-[focus]:bg-gray-100" | ||
> | ||
{item.content} | ||
</ComboboxOption> | ||
))} | ||
</ul> | ||
</li> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.