Combobox
A searchable dropdown component that combines the functionality of a select and input field with filtering capabilities.
Installation
Install the component:
npx natively-ui add combobox
Usage
ComboboxDemo.jsx
1import { Combobox } from '@/components/ui/combobox';
2
3const items = [
4 { value: "apple", label: "Apple" },
5 { value: "banana", label: "Banana" },
6 { value: "orange", label: "Orange" },
7];
8
9export default function MyComponent() {
10 return (
11 <Combobox
12 items={items}
13 placeholder="Select a fruit..."
14 onValueChange={(value) => console.log('Selected:', value)}
15 />
16 );
17}
Props
Prop | Type | Default | Description |
---|---|---|---|
items | ComboboxItem[] | - | Array of items to display in the dropdown. Each item should have value and label properties. |
defaultValue | string | "" | Initial selected value for uncontrolled combobox. |
value | string | - | Controlled value for the combobox. When provided, combobox becomes controlled. |
onValueChange | (value: string) => void | - | Function called when the selected value changes. |
placeholder | string | "Select an option..." | Text displayed when no item is selected. |
searchPlaceholder | string | "Search..." | Placeholder text for the search input field. |
emptyMessage | string | "No results found." | Message shown when no items match the search query. |
disabled | boolean | false | Whether the combobox is disabled. |
className | string | "" | Additional CSS classes for the combobox container. |
buttonClassName | string | "" | Additional CSS classes for the trigger button. |
contentClassName | string | "" | Additional CSS classes for the dropdown content. |
width | number | 300 | Width of the combobox and dropdown in pixels. |
maxHeight | number | 300 | Maximum height of the dropdown content in pixels. |
Types
types.ts
1interface ComboboxItem {
2 value: string;
3 label: string;
4}
Features
- Real-time search filtering with case-insensitive matching
- Controlled and uncontrolled modes for flexible state management
- Modal-based dropdown with backdrop dismissal
- Built-in accessibility support with proper ARIA attributes
- Keyboard navigation and focus management
- Customizable sizing with width and maxHeight props
- Visual selection indicators with checkmarks
- Empty state handling with custom messages
- Responsive design that adapts to screen height
- Custom styling support with multiple className props
Examples
Basic Usage
ComboboxDemo.jsx
1const fruits = [
2 { value: "apple", label: "Apple" },
3 { value: "banana", label: "Banana" },
4 { value: "orange", label: "Orange" },
5 { value: "grape", label: "Grape" },
6 { value: "strawberry", label: "Strawberry" },
7];
8
9<Combobox
10 items={fruits}
11 placeholder="Choose a fruit..."
12 onValueChange={(value) => console.log('Selected:', value)}
13/>
Controlled Combobox
ComboboxDemo.jsx
1const [selectedValue, setSelectedValue] = useState("");
2
3const countries = [
4 { value: "us", label: "United States" },
5 { value: "ca", label: "Canada" },
6 { value: "uk", label: "United Kingdom" },
7 { value: "au", label: "Australia" },
8];
9
10<View style={{ gap: 16 }}>
11 <Combobox
12 items={countries}
13 value={selectedValue}
14 onValueChange={setSelectedValue}
15 placeholder="Select country..."
16 />
17
18 <Text>Selected: {selectedValue || 'None'}</Text>
19</View>
Custom Sizing
ComboboxDemo.jsx
1const options = [
2 { value: "option1", label: "Very long option name that might overflow" },
3 { value: "option2", label: "Another lengthy option description" },
4 { value: "option3", label: "Short option" },
5];
6
7<View style={{ gap: 16 }}>
8 <Combobox
9 items={options}
10 width={400}
11 maxHeight={200}
12 placeholder="Wide combobox..."
13 />
14
15 <Combobox
16 items={options}
17 width={200}
18 maxHeight={150}
19 placeholder="Narrow combobox..."
20 />
21</View>
Custom Messages
ComboboxDemo.jsx
1const products = [
2 { value: "laptop", label: "Laptop" },
3 { value: "phone", label: "Smartphone" },
4 { value: "tablet", label: "Tablet" },
5];
6
7<Combobox
8 items={products}
9 placeholder="Find your device..."
10 searchPlaceholder="Type to search devices..."
11 emptyMessage="No devices match your search."
12 onValueChange={(value) => console.log('Product:', value)}
13/>
Large Dataset
ComboboxDemo.jsx
1// Generate a large list of options
2const generateOptions = () => {
3 const options = [];
4 for (let i = 1; i <= 1000; i++) {
5 options.push({
6 value: `item-${i}`,
7 label: `Item ${i} - Sample data entry`
8 });
9 }
10 return options;
11};
12
13const largeDataset = generateOptions();
14
15<Combobox
16 items={largeDataset}
17 placeholder="Search from 1000 items..."
18 searchPlaceholder="Type to filter..."
19 width={350}
20 maxHeight={250}
21 onValueChange={(value) => console.log('Selected item:', value)}
22/>
Custom Styling
ComboboxDemo.jsx
1const themes = [
2 { value: "light", label: "Light Theme" },
3 { value: "dark", label: "Dark Theme" },
4 { value: "auto", label: "Auto Theme" },
5];
6
7<Combobox
8 items={themes}
9 placeholder="Select theme..."
10 buttonClassName="border-blue-500 bg-blue-50"
11 contentClassName="border-blue-300"
12 className="shadow-lg"
13 width={280}
14 onValueChange={(value) => console.log('Theme:', value)}
15/>
Disabled State
ComboboxDemo.jsx
1const options = [
2 { value: "option1", label: "Option 1" },
3 { value: "option2", label: "Option 2" },
4];
5
6<View style={{ gap: 16 }}>
7 <Combobox
8 items={options}
9 placeholder="Disabled combobox"
10 disabled
11 />
12
13 <Combobox
14 items={options}
15 defaultValue="option1"
16 disabled
17 />
18</View>