User Search ComboBox
A user search ComboBox styled with Tailwind CSS.
Example#
import {Button, ComboBox, Group, Input, Label, ListBox, ListBoxItem, Popover} from 'react-aria-components';
import type {ListBoxItemProps} from 'react-aria-components';
import ChevronUpDownIcon from '@spectrum-icons/workflow/ChevronUpDown';
import CheckIcon from '@spectrum-icons/workflow/Checkmark';
function ComboBoxExample() {
return (
<div className="bg-gradient-to-r from-sky-300 to-cyan-300 p-8 sm:h-[300px] rounded-lg flex justify-center">
<ComboBox className="group flex flex-col gap-1 w-[200px]">
<Label className="text-black cursor-default">Assignee</Label>
<Group className="flex rounded-lg bg-white bg-opacity-90 focus-within:bg-opacity-100 transition shadow-md ring-1 ring-black/10 focus-visible:ring-2 focus-visible:ring-black">
<Input className="flex-1 w-full border-none py-2 px-3 leading-5 text-gray-900 bg-transparent outline-none text-base" />
<Button className="px-3 flex items-center text-gray-700 transition border-0 border-solid border-l border-l-sky-200 bg-transparent rounded-r-lg pressed:bg-sky-100">
<ChevronUpDownIcon size="XS" />
</Button>
</Group>
<Popover className="max-h-60 w-[--trigger-width] overflow-auto rounded-md bg-white text-base shadow-lg ring-1 ring-black/5 entering:animate-in entering:fade-in exiting:animate-out exiting:fade-out">
<ListBox className="outline-none p-1" items={people}>
{(item) => (
<UserItem textValue={item.name}>
<img
alt=""
src={item.avatar}
className="w-6 h-6 rounded-full"
/>
<span className="truncate">{item.name}</span>
</UserItem>
)}
</ListBox>
</Popover>
</ComboBox>
</div>
);
}
function UserItem(props: ListBoxItemProps & { children: React.ReactNode }) {
return (
<ListBoxItem
{...props}
className="group flex items-center gap-2 cursor-default select-none py-2 pl-2 pr-4 outline-none rounded text-gray-900 focus:bg-sky-600 focus:text-white"
>
{({ isSelected }) => (
<>
<span className="flex-1 flex items-center gap-3 truncate font-normal group-selected:font-medium">
{props.children}
</span>
{isSelected &&
(
<span className="w-5 flex items-center text-sky-600 group-focus:text-white">
<CheckIcon size="S" />
</span>
)}
</>
)}
</ListBoxItem>
);
}
import {
Button,
ComboBox,
Group,
Input,
Label,
ListBox,
ListBoxItem,
Popover
} from 'react-aria-components';
import type {ListBoxItemProps} from 'react-aria-components';
import ChevronUpDownIcon from '@spectrum-icons/workflow/ChevronUpDown';
import CheckIcon from '@spectrum-icons/workflow/Checkmark';
function ComboBoxExample() {
return (
<div className="bg-gradient-to-r from-sky-300 to-cyan-300 p-8 sm:h-[300px] rounded-lg flex justify-center">
<ComboBox className="group flex flex-col gap-1 w-[200px]">
<Label className="text-black cursor-default">
Assignee
</Label>
<Group className="flex rounded-lg bg-white bg-opacity-90 focus-within:bg-opacity-100 transition shadow-md ring-1 ring-black/10 focus-visible:ring-2 focus-visible:ring-black">
<Input className="flex-1 w-full border-none py-2 px-3 leading-5 text-gray-900 bg-transparent outline-none text-base" />
<Button className="px-3 flex items-center text-gray-700 transition border-0 border-solid border-l border-l-sky-200 bg-transparent rounded-r-lg pressed:bg-sky-100">
<ChevronUpDownIcon size="XS" />
</Button>
</Group>
<Popover className="max-h-60 w-[--trigger-width] overflow-auto rounded-md bg-white text-base shadow-lg ring-1 ring-black/5 entering:animate-in entering:fade-in exiting:animate-out exiting:fade-out">
<ListBox
className="outline-none p-1"
items={people}
>
{(item) => (
<UserItem textValue={item.name}>
<img
alt=""
src={item.avatar}
className="w-6 h-6 rounded-full"
/>
<span className="truncate">
{item.name}
</span>
</UserItem>
)}
</ListBox>
</Popover>
</ComboBox>
</div>
);
}
function UserItem(
props: ListBoxItemProps & { children: React.ReactNode }
) {
return (
<ListBoxItem
{...props}
className="group flex items-center gap-2 cursor-default select-none py-2 pl-2 pr-4 outline-none rounded text-gray-900 focus:bg-sky-600 focus:text-white"
>
{({ isSelected }) => (
<>
<span className="flex-1 flex items-center gap-3 truncate font-normal group-selected:font-medium">
{props.children}
</span>
{isSelected &&
(
<span className="w-5 flex items-center text-sky-600 group-focus:text-white">
<CheckIcon size="S" />
</span>
)}
</>
)}
</ListBoxItem>
);
}
import {
Button,
ComboBox,
Group,
Input,
Label,
ListBox,
ListBoxItem,
Popover
} from 'react-aria-components';
import type {ListBoxItemProps} from 'react-aria-components';
import ChevronUpDownIcon from '@spectrum-icons/workflow/ChevronUpDown';
import CheckIcon from '@spectrum-icons/workflow/Checkmark';
function ComboBoxExample() {
return (
<div className="bg-gradient-to-r from-sky-300 to-cyan-300 p-8 sm:h-[300px] rounded-lg flex justify-center">
<ComboBox className="group flex flex-col gap-1 w-[200px]">
<Label className="text-black cursor-default">
Assignee
</Label>
<Group className="flex rounded-lg bg-white bg-opacity-90 focus-within:bg-opacity-100 transition shadow-md ring-1 ring-black/10 focus-visible:ring-2 focus-visible:ring-black">
<Input className="flex-1 w-full border-none py-2 px-3 leading-5 text-gray-900 bg-transparent outline-none text-base" />
<Button className="px-3 flex items-center text-gray-700 transition border-0 border-solid border-l border-l-sky-200 bg-transparent rounded-r-lg pressed:bg-sky-100">
<ChevronUpDownIcon size="XS" />
</Button>
</Group>
<Popover className="max-h-60 w-[--trigger-width] overflow-auto rounded-md bg-white text-base shadow-lg ring-1 ring-black/5 entering:animate-in entering:fade-in exiting:animate-out exiting:fade-out">
<ListBox
className="outline-none p-1"
items={people}
>
{(item) => (
<UserItem
textValue={item
.name}
>
<img
alt=""
src={item
.avatar}
className="w-6 h-6 rounded-full"
/>
<span className="truncate">
{item
.name}
</span>
</UserItem>
)}
</ListBox>
</Popover>
</ComboBox>
</div>
);
}
function UserItem(
props:
& ListBoxItemProps
& {
children:
React.ReactNode;
}
) {
return (
<ListBoxItem
{...props}
className="group flex items-center gap-2 cursor-default select-none py-2 pl-2 pr-4 outline-none rounded text-gray-900 focus:bg-sky-600 focus:text-white"
>
{(
{ isSelected }
) => (
<>
<span className="flex-1 flex items-center gap-3 truncate font-normal group-selected:font-medium">
{props
.children}
</span>
{isSelected &&
(
<span className="w-5 flex items-center text-sky-600 group-focus:text-white">
<CheckIcon size="S" />
</span>
)}
</>
)}
</ListBoxItem>
);
}
Tailwind config#
This example uses the following plugins:
Add them to your tailwind.config.js
:
module.exports = {
// ...
plugins: [
require('tailwindcss-react-aria-components'),
require('tailwindcss-animate')
]
};
module.exports = {
// ...
plugins: [
require('tailwindcss-react-aria-components'),
require('tailwindcss-animate')
]
};
module.exports = {
// ...
plugins: [
require(
'tailwindcss-react-aria-components'
),
require(
'tailwindcss-animate'
)
]
};
Components#
ComboBox
A combobox combines a text input with a listbox, and allows a user to filter a list of options.
ListBox
A listbox allows a user to select one or more options from a list.
Popover
A popover displays content in context with a trigger element.
Button
A button allows a user to perform an action.