Files
headlessui/playgrounds/react/pages/combobox/command-palette.tsx
T
Robin Malfait e10f54bc12 Migrate React playground to Tailwind CSS v4 (#3695)
This PR bumps the internal React playground to use Tailwind CSS v4
2025-04-11 19:28:04 +02:00

136 lines
5.8 KiB
TypeScript

import { Combobox } from '@headlessui/react'
import { useEffect, useState } from 'react'
import { classNames } from '../../utils/class-names'
let everybody = [
{ id: 1, img: 'https://github.com/adamwathan.png', name: 'Adam Wathan' },
{ id: 2, img: 'https://github.com/sschoger.png', name: 'Steve Schoger' },
{ id: 3, img: 'https://github.com/bradlc.png', name: 'Brad Cornes' },
{ id: 4, img: 'https://github.com/simonswiss.png', name: 'Simon Vrachliotis' },
{ id: 5, img: 'https://github.com/robinmalfait.png', name: 'Robin Malfait' },
{
id: 6,
img: 'https://pbs.twimg.com/profile_images/1478879681491394569/eV2PyCnm_400x400.jpg',
name: 'James McDonald',
},
{ id: 7, img: 'https://github.com/reinink.png', name: 'Jonathan Reinink' },
{ id: 8, img: 'https://github.com/thecrypticace.png', name: 'Jordan Pittman' },
]
export default function Home() {
let [query, setQuery] = useState('')
let [activePerson, setActivePerson] = useState(everybody[2])
// Choose a random person on mount
useEffect(() => {
setActivePerson(everybody[Math.floor(Math.random() * everybody.length)])
}, [])
let people =
query === ''
? everybody
: everybody.filter((person) => person.name.toLowerCase().includes(query.toLowerCase()))
return (
<div className="flex h-full w-screen justify-center bg-gray-50 p-12">
<div className="mx-auto w-full max-w-lg">
<div className="space-y-1">
<Combobox
as="div"
value={activePerson}
onChange={(person) => setActivePerson(person)}
className="shadow-xs w-full overflow-hidden rounded-sm border border-black/5 bg-white bg-clip-padding"
>
{({ activeOption, open }) => {
return (
<div className="flex w-full flex-col">
<Combobox.Input
onChange={(e) => setQuery(e.target.value)}
className="outline-hidden w-full rounded-none border-none px-3 py-1"
placeholder="Search users…"
displayValue={(item: typeof activePerson) => item?.name}
/>
<div
className={classNames(
'flex border-t',
activePerson && !open ? 'border-transparent' : 'border-gray-200'
)}
>
<Combobox.Options className="shadow-2xs focus:outline-hidden max-h-60 flex-1 overflow-auto py-1 text-base leading-6 sm:text-sm sm:leading-5">
{people.map((person) => (
<Combobox.Option
key={person.id}
value={person}
className={({ active }) => {
return classNames(
'focus:outline-hidden relative flex cursor-default select-none space-x-4 py-2 pl-3 pr-9',
active ? 'bg-indigo-600 text-white' : 'text-gray-900'
)
}}
>
{({ active, selected }) => (
<>
<img
src={person.img}
className="h-6 w-6 overflow-hidden rounded-full"
/>
<span
className={classNames(
'block truncate',
selected ? 'font-semibold' : 'font-normal'
)}
>
{person.name}
</span>
{active && (
<span
className={classNames(
'absolute inset-y-0 right-0 flex items-center pr-4',
active ? 'text-white' : 'text-indigo-600'
)}
>
<svg className="h-5 w-5" viewBox="0 0 25 24" fill="none">
<path
d="M11.25 8.75L14.75 12L11.25 15.25"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</span>
)}
</>
)}
</Combobox.Option>
))}
</Combobox.Options>
{people.length === 0 ? (
<div className="w-full py-4 text-center">No person selected</div>
) : activeOption === null ? null : (
<div className="border-l">
<div className="flex flex-col">
<div className="p-8 text-center">
<img
src={activeOption.img}
className="mb-4 inline-block h-16 w-16 overflow-hidden rounded-full"
/>
<div className="font-bold text-gray-900">{activeOption.name}</div>
<div className="text-gray-700">Obviously cool person</div>
</div>
</div>
</div>
)}
</div>
</div>
)
}}
</Combobox>
</div>
</div>
</div>
)
}