AI Dropdown
A powerful dropdown component supporting single select, multi-select, search, grouping, and multiple visual appearances.
Loading...
Overview
Resources
Install
yarn add @camp/ai-dropdown
Usage
Set up ThemeProvider
The AiDropdown component requires a styled-components
ThemeProvider
to be set up in your application. See the Styled Components & ThemeProvider guide for more details on setting up the ThemeProvider
.
Single select (basic)
import { AiDropdown, DropdownMenuItem } from '@camp/ai-dropdown';
import { useState } from 'react';
// This matches the basicOptions used in the Default story
const options = [
{ label: 'Option 1', id: 'opt-1' },
{ label: 'Option 2', id: 'opt-2' },
{ label: 'Option 3', id: 'opt-3' },
];
const MyDropdown = () => {
const [value, setValue] = useState();
return (
<AiDropdown
appearance="default"
type="single"
options={options}
value={value}
onSelect={setValue}
renderDisplayValue={(option) => option.label}
renderMenuItem={(option, args) => (
<DropdownMenuItem {...args} id={option.id}>
{option.label}
</DropdownMenuItem>
)}
placeholder="Select an option"
/>
);
};
Multi-select with search
import { AiDropdown, DropdownMenuItem } from '@camp/ai-dropdown';
import { useState } from 'react';
const options = [
{ label: 'List Item 1', id: 'list-item-1' },
{ label: 'List Item 2', id: 'list-item-2' },
{ label: 'List Item 3', invalid: true, id: 'list-item-3' },
{ label: 'List Item 4', id: 'list-item-4' },
{ label: 'List Item 5', id: 'list-item-5' },
];
const MyMultiDropdown = () => {
const [selectedOptions, setSelectedOptions] = useState([]);
return (
<AiDropdown
appearance="default"
type="multi"
options={options}
value={selectedOptions}
onSelect={setSelectedOptions}
renderDisplayValue={(option) => option.label}
renderMenuItem={(option, args) => (
<DropdownMenuItem {...args} id={option.id} invalid={option.invalid}>
{option.label}
</DropdownMenuItem>
)}
showSearch={true}
placeholder="Select an option..."
/>
);
};
Grouped options with accordion
Options with the same group
property are automatically grouped together and sorted alphabetically by group name.
import { AiDropdown, DropdownMenuItem } from '@camp/ai-dropdown';
import { useState } from 'react';
const groupedOptions = [
{ label: 'React', group: 'Frontend Frameworks' },
{ label: 'Angular', group: 'Frontend Frameworks' },
{ label: 'Vue.js', group: 'Frontend Frameworks' },
{ label: 'Node.js', group: 'Backend Technologies' },
{ label: 'Python', group: 'Backend Technologies' },
{ label: 'PostgreSQL', group: 'Databases' },
{ label: 'Redis', group: 'Databases', invalid: true },
{ label: 'MongoDB', group: 'Databases' },
{ label: 'Git' },
];
const GroupedDropdown = () => {
const [value, setValue] = useState();
return (
<AiDropdown
appearance="default"
type="single"
value={value}
onSelect={setValue}
options={groupedOptions}
renderDisplayValue={(option) => option.label}
renderMenuItem={(option, args) => (
<DropdownMenuItem {...args} id={option.id} invalid={option.invalid}>
{option.label}
</DropdownMenuItem>
)}
placeholder="Select an option..."
accordionGroups={['Backend Technologies', 'Databases']}
/>
);
};
With label and custom styling
import { AiDropdown, DropdownMenuItem } from '@camp/ai-dropdown';
import { useState } from 'react';
const options = [
{ id: 'opt-1', label: 'Option 1' },
{ id: 'opt-2', label: 'Option 2' },
{ id: 'opt-3', label: 'Option 3' },
];
const LabeledDropdown = () => {
const [value, setValue] = useState();
return (
<AiDropdown
appearance="default"
type="single"
value={value}
onSelect={setValue}
options={options}
label="Category"
labelPosition="left" // or "top"
renderDisplayValue={(option) => option.label}
renderMenuItem={(option, args) => (
<DropdownMenuItem {...args} id={option.id}>
{option.label}
</DropdownMenuItem>
)}
placeholder="Select"
/>
);
};
Variations
Toggle theming
Prop: themed
Type: boolean
Default value: true
The themed
prop toggles light and dark mode support for the AiDropdown component. This makes the component adaptable to areas of the product that support theme switching, such as AI agent interfaces or other areas with dark mode capabilities, as well as standard application areas that only support light mode.
When to use themed
:
- ✅ If you need light mode support only, use
themed={false}
. This is useful in standard application areas that only support light mode. - ❌ If you need light and dark mode support, themed is not required as it is set to
true
by default. This is useful in AI agent interfaces or other areas with dark mode capabilities. - 🔨 If light and dark mode support is not working as expected, try explicitly setting
themed={true}
(and check that your component has been updated to the latest version).
Behavior:
- Without
themed
prop (or withthemed={true}
): AiDropdown will be themed, supporting light and dark mode styling - With
themed={false}
: AiDropdown will not respond to theme changes and display in light mode only
import { AiDropdown } from '@camp/ai-dropdown';
function UnthemedDropdown() {
return (
<AiDropdown<OptionType>
themed={false} // explicitly set to false to disable theming
type="single"
appearance="default"
value={undefined}
onSelect={() => {}}
renderDisplayValue={(option) => option.label}
options={basicOptions}
placeholder="Unthemed default dropdown"
renderMenuItem={(option, args) => (
<DropdownMenuItem {...args} id={option.id} invalid={option.invalid}>
{option.label}
</DropdownMenuItem>
)}
/>
);
}
Invalid states
Invalid styling adapts to each appearance - red borders for default
and inline
, red text for floating
.
Default
Inline
Floating
const InvalidDropdown = () => {
return (
<AiDropdown
invalid={true}
...{/* your other props here */}
/>
);
};
Value prefix
Add visual indicators like color dots or icons before the display value.
const Dot = ({ color }) => (
<span
style={{
display: 'inline-block',
width: 10,
height: 10,
borderRadius: '50%',
background: color,
marginRight: 8,
flex: '0 0 auto',
}}
/>
);
const ColorDropdown = () => {
return (
<AiDropdown
renderValuePrefix={(current) =>
current && !Array.isArray(current) ? <Dot color={current.color} /> : null
}
...{/* your other props here */}
/>
);
};
Custom trigger
Replace the default button with any custom trigger element like icon buttons.
import { AiIconButton } from '@camp/ai-icon-button';
import { SettingsCogMedium } from '@camp/icon';
const CustomTriggerDropdown = () => {return (
<AiDropdown
renderTrigger={(props) => (
<AiIconButton appearance="secondary" shape="rectangle" size="medium" {...props}>
<SettingsCogMedium title="Settings" />
</AiIconButton>
)}
...{/* your other props here */}
/>
);
};
Menu actions
Add custom buttons or actions at the bottom of the dropdown menu with the renderMenuActions
prop.
import { AiButton } from '@camp/ai-button';
const MenuActionsDropdown = () => {
return (
<AiDropdown
renderMenuActions={() => (
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
padding: '8px 12px',
}}
>
<AiButton
appearance="secondary"
size="small"
onClick={() => alert('Add new label')}
style={{ width: '100%' }}
>
Add new label
</AiButton>
</div>
)}
...{/* your other props here */}
/>
);
};
Search functionality
The search input filters options by both label and group name, with a “No results” state when no matches exist.
const SearchableDropdown = () => {
return (
<AiDropdown
showSearch={true}
...{/* your other props here */}
/>
);
};
Disabled state
To achieve a disabled state, the disabled
value should be passed to the default trigger button using buttonProps
.
const DisabledDropdown = () => (
<AiDropdown
buttonProps={{ disabled: true }}
...{/* your other props here */}
/>
);
Advanced configurations
The dropdown supports several advanced configuration options for fine-tuning behavior and appearance.
const AdvancedDropdown = () => {
return (
<AiDropdown
// Portal rendering to avoid clipping issues
usePortal={true}
// Custom z-index for stacking control
zIndex={1000}
// Minimum menu width
minMenuWidth="200px"
// Theme support (defaults to true)
themed={true}
// Custom placement
placement="bottom-start"
// Full width menu
fullWidthMenu={true}
// Maximum menu height (defaults to 300px)
maxMenuHeight={400}
...{/* your other props here */}
/>
);
};
Props reference
The AI Dropdown component supports a comprehensive set of props for customization:
Core Props:
appearance
: Visual style -"default"
|"inline"
|"floating"
type
: Selection type -"single"
|"multi"
options
: Array of options to displayvalue
: Current selected value(s)onSelect
: Callback when selection changesrenderDisplayValue
: Function to render option display textrenderMenuItem
: Function to render each menu item
Layout & Styling:
label
: Optional label textlabelPosition
: Label position -"left"
|"top"
placeholder
: Placeholder text when no selectioninvalid
: Invalid state stylingbuttonProps
: Props passed to the trigger buttonmaxTriggerWidth
: Maximum trigger widthminTriggerWidth
: Minimum trigger widththemed
: Enable or disable theme support (default: true)
Menu Configuration:
maxMenuHeight
: Maximum menu height (default: 300px)minMenuWidth
: Minimum menu widthfullWidthMenu
: Match menu width to triggerplacement
: Menu placement (default: “bottom-end”)zIndex
: Custom z-index for stackingusePortal
: Render menu in portal to avoid clipping
Features:
showSearch
: Enable search functionalityshowSelectAll
: Show select all option (multi-select only)accordionGroups
: Array of group names to make collapsiblerenderMenuActions
: Custom actions at menu bottomrenderTrigger
: Custom trigger elementrenderValuePrefix
: Prefix element in trigger value areathemed
: Enable theme support (default: true)
Best practices
- Dropdown menus work best for small data sets where a user has anywhere from 5 to 15 items to choose from. For smaller datasets, checkboxes or radios should be used (depending on single or multiselect), and for datasets larger than 15, it is recommended to use a combobox instead.
- When grouped, listed items should be in some logical order that makes it easy for the user to read and understand, whether that is numerical or alphabetical or some other contextually-based grouping.
Accessibility
Keyboard support
- Tab: Navigate to/from the dropdown trigger
- Space/Enter: Open dropdown when focused on trigger
- Arrow keys: Navigate options when menu is open
- Enter: Select focused option
- Escape: Close dropdown menu