Select
Accessible custom select dropdown with search, keyboard navigation, and floating positioning.
Select
The Select component provides a fully accessible custom dropdown with keyboard navigation, optional search/filtering, and floating UI positioning. It replaces the native <select> with a customizable interface while maintaining all accessibility semantics.
Select requires multiple sub-components: SelectTrigger, SelectValue, SelectContent, SelectItem, and optionally SelectGroup, SelectLabel, and SelectSeparator.
Features
- Controlled/uncontrolled modes
- Keyboard navigation (arrow keys, Home, End, Type to search)
- Grouped items with labels
- Scroll buttons for long lists
- Floating positioning (no clipping)
- Form integration (works in forms)
- RTL support
Usage
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem, SelectGroup, SelectLabel } from '@loke/ui/select';
export default function Example() {
const [value, setValue] = React.useState('apple');
return (
<Select value={value} onValueChange={setValue}>
<SelectTrigger>
<SelectValue placeholder="Choose a fruit..." />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Fruits</SelectLabel>
<SelectItem value="apple">Apple</SelectItem>
<SelectItem value="banana">Banana</SelectItem>
<SelectItem value="orange">Orange</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
);
}Props
Select
Prop
Type
SelectItem
Prop
Type
Sub-components
- SelectTrigger: Button that opens the dropdown
- SelectValue: Displays the selected value (or placeholder)
- SelectContent: The dropdown menu container
- SelectItem: A selectable option
- SelectGroup: Groups items with a label
- SelectLabel: Group header label
- SelectSeparator: Visual divider between groups
- SelectScrollUpButton: Button to scroll up (for long lists)
- SelectScrollDownButton: Button to scroll down (for long lists)
Examples
Basic select
Grouped options
Keyboard Navigation
- Arrow Down/Up: Move focus to next/previous item
- Home/End: Jump to first/last item
- Type: Search for items starting with typed characters
- Enter/Space: Select focused item
- Escape: Close dropdown and return focus to trigger
Accessibility
- Trigger has
role="button"andaria-haspopup="listbox" - Content has
role="listbox"andaria-label/aria-labelledby - Items have
role="option"andaria-selected - Disabled items have
aria-disabled="true" - Type-ahead is announced via
aria-live
Best practices
- Always provide a placeholder in SelectValue
- Group related options with SelectGroup for clarity
- Keep option lists scannable; use separators if needed
- Test type-ahead behavior with screen readers
- For native form submission, ensure Select is inside a form