Dropdown Components
Proton provides dropdown components for menus, actions, and select inputs with full keyboard navigation and accessibility support.
Dropdown
The main dropdown component with popper positioning.
Location: components/dropdown/Dropdown.tsx
Basic Usage
import { useRef, useState } from 'react';
import { Button } from '@proton/atoms/Button/Button';
import Dropdown from '@proton/components/components/dropdown/Dropdown';
import DropdownMenu from '@proton/components/components/dropdown/DropdownMenu';
import DropdownMenuButton from '@proton/components/components/dropdown/DropdownMenuButton';
const MyDropdown = () => {
const anchorRef = useRef<HTMLButtonElement>(null);
const [isOpen, setIsOpen] = useState(false);
return (
<>
<Button ref={anchorRef} onClick={() => setIsOpen(!isOpen)}>
Actions
</Button>
<Dropdown
isOpen={isOpen}
anchorRef={anchorRef}
onClose={() => setIsOpen(false)}
>
<DropdownMenu>
<DropdownMenuButton onClick={() => console.log('Edit')}>
Edit
</DropdownMenuButton>
<DropdownMenuButton onClick={() => console.log('Delete')}>
Delete
</DropdownMenuButton>
</DropdownMenu>
</Dropdown>
</>
);
};
Props
anchorRef
RefObject<HTMLElement>
required
Reference to the element that triggers the dropdown
Whether the dropdown is open. Default: false
Callback when dropdown should close
Callback when dropdown animation completes
Initial placement of dropdown. Default: bottom
Array of allowed placements for auto-positioning
Dropdown dimensions configuration
Distance from anchor element in pixels. Default: 8
Hide the caret/arrow pointing to anchor. Default: false
Auto close on item click. Default: true
Auto close when clicking outside. Default: true
Auto close when clicking outside anchor. Default: true
Disable focus trap. Default: false
disableDefaultArrowNavigation
Disable arrow key navigation. Default: false
Adapt UI for touch screens. Default: true
Border radius size: xl, lg, md, sm. Default: md
Props passed to content container
Examples
Wrapper for dropdown menu items.
Location: components/dropdown/DropdownMenu.tsx
Usage
import DropdownMenu from '@proton/components/components/dropdown/DropdownMenu';
<DropdownMenu>
{/* Menu items here */}
</DropdownMenu>
Clickable menu item button.
Location: components/dropdown/DropdownMenuButton.tsx
Usage
import DropdownMenuButton from '@proton/components/components/dropdown/DropdownMenuButton';
<DropdownMenuButton onClick={handleAction}>
Action Label
</DropdownMenuButton>
Props
Link menu item for navigation.
Location: components/dropdown/DropdownMenuLink.tsx
Usage
import DropdownMenuLink from '@proton/components/components/dropdown/DropdownMenuLink';
<DropdownMenuLink href="/settings">
Settings
</DropdownMenuLink>
SimpleDropdown
Simplified dropdown with built-in button.
Location: components/dropdown/SimpleDropdown.tsx
Usage
import SimpleDropdown from '@proton/components/components/dropdown/SimpleDropdown';
import DropdownMenu from '@proton/components/components/dropdown/DropdownMenu';
import DropdownMenuButton from '@proton/components/components/dropdown/DropdownMenuButton';
const MySimpleDropdown = () => {
return (
<SimpleDropdown content="More Actions">
<DropdownMenu>
<DropdownMenuButton onClick={handleEdit}>Edit</DropdownMenuButton>
<DropdownMenuButton onClick={handleDelete}>Delete</DropdownMenuButton>
</DropdownMenu>
</SimpleDropdown>
);
};
SelectTwo
Advanced select component with search and keyboard navigation.
Location: components/selectTwo/SelectTwo.tsx
Basic Usage
import { useState } from 'react';
import SelectTwo from '@proton/components/components/selectTwo/SelectTwo';
import Option from '@proton/components/components/option/Option';
const MySelect = () => {
const [value, setValue] = useState('option1');
return (
<SelectTwo
value={value}
onChange={({ value }) => setValue(value)}
>
<Option value="option1" title="Option 1">Option 1</Option>
<Option value="option2" title="Option 2">Option 2</Option>
<Option value="option3" title="Option 3">Option 3</Option>
</SelectTwo>
);
};
Props
onChange
({ value, selectedIndex }) => void
Called when selection changes
Alternative change handler receiving only value
Enable multiple selection. Default: false
Placeholder text when no selection
Remove border styling. Default: false
Take full width of container
Hide the dropdown caret icon
Milliseconds to clear search input. Default: 500
Function to extract searchable string from complex values
Custom render function for selected value
Dropdown size configuration
Optional heading above options
Examples
Basic Select
Multiple Selection
Complex Values
Custom Rendering
<SelectTwo value={value} onChange={({ value }) => setValue(value)}>
<Option value="1">Option 1</Option>
<Option value="2">Option 2</Option>
<Option value="3">Option 3</Option>
</SelectTwo>
<SelectTwo
multiple
value={values}
onChange={({ value }) => setValues(value)}
>
<Option value="1">Option 1</Option>
<Option value="2">Option 2</Option>
<Option value="3">Option 3</Option>
</SelectTwo>
interface User {
id: string;
name: string;
}
<SelectTwo<User>
value={selectedUser}
onChange={({ value }) => setSelectedUser(value)}
getSearchableValue={(user) => user.name}
>
<Option value={{ id: '1', name: 'Alice' }} title="Alice">
Alice
</Option>
<Option value={{ id: '2', name: 'Bob' }} title="Bob">
Bob
</Option>
</SelectTwo>
<SelectTwo
value={value}
onChange={onChange}
renderSelected={(val) => (
<div className="flex items-center gap-2">
<Icon name={val.icon} />
<span>{val.label}</span>
</div>
)}
>
{options.map(opt => (
<Option key={opt.id} value={opt}>
<Icon name={opt.icon} /> {opt.label}
</Option>
))}
</SelectTwo>
Best Practices
Managing Dropdown State
const [isOpen, setIsOpen] = useState(false);
const anchorRef = useRef<HTMLButtonElement>(null);
const handleToggle = () => setIsOpen(!isOpen);
const handleClose = () => setIsOpen(false);
return (
<>
<Button ref={anchorRef} onClick={handleToggle}>
Menu
</Button>
<Dropdown
isOpen={isOpen}
anchorRef={anchorRef}
onClose={handleClose}
>
{/* Content */}
</Dropdown>
</>
);
Keyboard Navigation
Dropdowns support:
- Arrow keys to navigate items
- Enter/Space to select
- Escape to close
- Type to search (when enabled)
Accessibility
<Button
ref={anchorRef}
onClick={handleToggle}
aria-expanded={isOpen}
aria-haspopup="true"
>
Actions
</Button>
<Dropdown
isOpen={isOpen}
anchorRef={anchorRef}
onClose={handleClose}
role="menu"
>
<DropdownMenuButton role="menuitem">
Action
</DropdownMenuButton>
</Dropdown>
Positioning
Control dropdown placement:
// Open above the anchor
<Dropdown originalPlacement="top" />
// Open to the right
<Dropdown originalPlacement="right" />
// Auto-adjust with fallbacks
<Dropdown
originalPlacement="bottom"
availablePlacements={['bottom', 'top', 'left', 'right']}
/>
Source Code
View source:
- Dropdown:
packages/components/components/dropdown/Dropdown.tsx:1
- SelectTwo:
packages/components/components/selectTwo/SelectTwo.tsx:1
- SimpleDropdown:
packages/components/components/dropdown/SimpleDropdown.tsx:1