app-ui / forms / comboboxes
With Avatar
04-with-avatar.jsx
'use client'
import { Combobox, ComboboxButton, ComboboxInput, ComboboxOption, ComboboxOptions, Label } from '@headlessui/react'
import { ChevronDownIcon } from '@heroicons/react/20/solid'
import { UserIcon } from '@heroicons/react/16/solid'
import { useState } from 'react'
const people = [
{
id: 1,
name: 'Leslie Alexander',
imageUrl:
'https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
// More users...
]
export default function Example() {
const [query, setQuery] = useState('')
const [selectedPerson, setSelectedPerson] = useState(null)
const filteredPeople =
query === ''
? people
: people.filter((person) => {
return person.name.toLowerCase().includes(query.toLowerCase())
})
return (
<Combobox
as="div"
value={selectedPerson}
onChange={(person) => {
setQuery('')
setSelectedPerson(person)
}}
>
<Label className="block text-sm/6 font-medium text-gray-900 dark:text-white">Assigned to</Label>
<div className="relative mt-2">
<ComboboxInput
className="block w-full rounded-md bg-white py-1.5 pr-12 pl-3 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6 dark:bg-white/5 dark:text-white dark:outline-white/10 dark:placeholder:text-gray-500 dark:focus:outline-indigo-500"
onChange={(event) => setQuery(event.target.value)}
onBlur={() => setQuery('')}
displayValue={(person) => person?.name}
/>
<ComboboxButton className="absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-hidden">
<ChevronDownIcon className="size-5 text-gray-400" aria-hidden="true" />
</ComboboxButton>
<ComboboxOptions
transition
className="absolute z-10 mt-1 max-h-56 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg outline outline-black/5 data-leave:transition data-leave:duration-100 data-leave:ease-in data-closed:data-leave:opacity-0 sm:text-sm dark:bg-gray-800 dark:shadow-none dark:-outline-offset-1 dark:outline-white/10"
>
{query.length > 0 && (
<ComboboxOption
value={{ id: null, name: query }}
className="cursor-default px-3 py-2 text-gray-900 select-none data-focus:bg-indigo-600 data-focus:text-white data-focus:outline-hidden dark:text-white dark:data-focus:bg-indigo-500"
>
<div className="flex items-center">
<div className="grid size-6 shrink-0 place-items-center rounded-full bg-gray-300 in-data-focus:bg-white dark:bg-gray-600">
<UserIcon
className="size-4 fill-white in-data-focus:fill-indigo-600 dark:in-data-focus:fill-indigo-500"
aria-hidden="true"
/>
</div>
<span className="ml-3 block truncate">{query}</span>
</div>
</ComboboxOption>
)}
{filteredPeople.map((person) => (
<ComboboxOption
key={person.id}
value={person}
className="cursor-default px-3 py-2 text-gray-900 select-none data-focus:bg-indigo-600 data-focus:text-white data-focus:outline-hidden dark:text-white dark:data-focus:bg-indigo-500"
>
<div className="flex items-center">
<img
src={person.imageUrl}
alt=""
className="size-6 shrink-0 rounded-full bg-gray-100 outline -outline-offset-1 outline-black/5 dark:bg-gray-700 dark:outline-white/10"
/>
<span className="ml-3 block truncate">{person.name}</span>
</div>
</ComboboxOption>
))}
</ComboboxOptions>
</div>
</Combobox>
)
}