Overview
Dropdown is a versatile select component that supports both single and multiple selection modes. It includes built-in search functionality, custom icons for options, and automatic click-outside detection.
Basic Usage
import { Dropdown } from '@adoptaunabuelo/react-components';
import { useState } from 'react';
function App() {
const [selected, setSelected] = useState([]);
const options = [
{ id: '1', title: 'Option 1' },
{ id: '2', title: 'Option 2' },
{ id: '3', title: 'Option 3' }
];
return (
<Dropdown
id="my-dropdown"
placeholder="Select an option"
type="single"
options={options}
selectedOptions={selected}
onChange={setSelected}
/>
);
}
Selection Modes
Single Selection
Radio-style selection where only one option can be selected at a time.
<Dropdown
id="category-dropdown"
placeholder="Select category"
type="single"
options={[
{ id: 'tech', title: 'Technology' },
{ id: 'health', title: 'Healthcare' },
{ id: 'edu', title: 'Education' }
]}
selectedOptions={selectedCategory}
onChange={(items) => setSelectedCategory(items)}
/>
Multiple Selection
Checkbox-style selection allowing multiple options to be selected.
<Dropdown
id="tags-dropdown"
placeholder="Select tags"
type="multiple"
options={[
{ id: 'react', title: 'React' },
{ id: 'typescript', title: 'TypeScript' },
{ id: 'nodejs', title: 'Node.js' }
]}
selectedOptions={selectedTags}
onChange={(items) => setSelectedTags(items)}
/>
With Search
Enable search functionality by providing an onSearchChange callback.
const [searchText, setSearchText] = useState('');
const [filteredOptions, setFilteredOptions] = useState(allOptions);
const handleSearch = (text: string) => {
setSearchText(text);
const filtered = allOptions.filter(option =>
option.title.toLowerCase().includes(text.toLowerCase())
);
setFilteredOptions(filtered);
};
<Dropdown
id="searchable-dropdown"
placeholder="Search options"
type="multiple"
options={filteredOptions}
selectedOptions={selected}
onSearchChange={handleSearch}
onChange={setSelected}
/>
With Icons
Add visual icons to options for better recognition.
import { Users, Settings, Bell } from 'lucide-react';
<Dropdown
id="actions-dropdown"
placeholder="Select action"
type="single"
options={[
{
id: 'users',
title: 'Manage Users',
icon: <Users size={16} />
},
{
id: 'settings',
title: 'Settings',
icon: <Settings size={16} />
},
{
id: 'notifications',
title: 'Notifications',
icon: <Bell size={16} />
}
]}
selectedOptions={selectedAction}
onChange={setSelectedAction}
/>
Control where the dropdown menu appears relative to the trigger.
// Menu opens upward (useful when dropdown is at bottom of viewport)
<Dropdown
id="bottom-dropdown"
placeholder="Select option"
type="single"
options={options}
menuPosition="top"
onChange={handleChange}
/>
// Menu opens downward (default)
<Dropdown
id="top-dropdown"
placeholder="Select option"
type="single"
options={options}
menuPosition="bottom"
onChange={handleChange}
/>
Props
Unique identifier required for click-outside detection functionality.
Text displayed when no options are selected.
options
Array<OptionProps>
required
Array of selectable options:{
id: string; // Unique identifier
title?: string; // Display text
icon?: ReactElement; // Optional icon
}
type
'single' | 'multiple'
default:"single"
Selection mode:
single: Only one option can be selected (radio behavior)
multiple: Multiple options can be selected (checkbox behavior)
Currently selected options (controlled component pattern).
onChange
(items: Array<OptionProps>) => void
Callback fired when selection changes. Receives array of selected options (even for single selection).
Callback fired when search input changes. When provided, enables search bar in dropdown menu.
Position of dropdown menu relative to trigger button.
Custom styles applied to the dropdown container.
Custom styles applied to the dropdown menu.
Custom styles applied to individual option items.
Advanced Examples
With Custom Styling
<Dropdown
id="styled-dropdown"
placeholder="Custom styled"
type="multiple"
options={options}
selectedOptions={selected}
onChange={setSelected}
style={{
backgroundColor: '#f5f5f5',
borderRadius: '8px'
}}
menuStyle={{
maxHeight: '400px',
width: '100%'
}}
optionStyle={{
padding: '12px'
}}
/>
Async Search
const [loading, setLoading] = useState(false);
const [options, setOptions] = useState([]);
const handleSearch = async (text: string) => {
if (!text) {
setOptions([]);
return;
}
setLoading(true);
try {
const results = await searchAPI(text);
setOptions(results);
} finally {
setLoading(false);
}
};
<Dropdown
id="async-dropdown"
placeholder="Search users..."
type="multiple"
options={options}
selectedOptions={selected}
onSearchChange={handleSearch}
onChange={setSelected}
/>
Controlled with External State
const [isOpen, setIsOpen] = useState(false);
const [selected, setSelected] = useState([]);
const handleChange = (items) => {
setSelected(items);
// Close dropdown after single selection
if (type === 'single' && items.length > 0) {
setIsOpen(false);
}
};
<Dropdown
id="controlled-dropdown"
placeholder="Select"
type="single"
options={options}
selectedOptions={selected}
onChange={handleChange}
/>
Behavior Notes
- Auto-close: Dropdown automatically closes when clicking outside
- Single selection: Dropdown closes immediately after selecting an option
- Multiple selection: Dropdown stays open until user clicks outside
- Selected display: Shows comma-separated list of selected option titles
- Overflow: Selected text is truncated with ellipsis if too long
- Max height: Menu has
250px max height with scroll
- Max width: Menu is
94% of container width
Styling Notes
- Container has
40px fixed height
- Background uses
Color.background.soft
- Menu appears with
box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.08)
- Selected options highlighted with
Color.background.primary
- Hover state uses
Color.status.neutral.hover
- Icons are displayed at
16x16px
Accessibility
- Uses semantic
role="dropdown" attribute
- Checkboxes visible in multiple selection mode
- Check icons shown for selected items in single selection mode
- Keyboard accessible with mouse and keyboard interactions
- Search input has proper placeholder text