Select
Dropdown select component for choosing a single value from a list. Supports searchable filtering, grouped options, keyboard navigation, clearable selection, and multiple visual variants. Built for professional editor interfaces.
Live Preview
Import
import { Select } from 'entangle-ui';Usage
<Select options={[ { value: 'normal', label: 'Normal' }, { value: 'multiply', label: 'Multiply' }, { value: 'screen', label: 'Screen' }, ]} value={blendMode} onChange={setBlendMode}/>Controlled vs Uncontrolled
The Select component supports both controlled and uncontrolled patterns.
// Controlledconst [value, setValue] = useState<string | null>('normal');<Select options={options} value={value} onChange={setValue} />
// Uncontrolled<Select options={options} defaultValue="normal" />Grouped Options
Options can be organized into groups with non-selectable headers.
<Select label="Blend Mode" options={[ { label: 'Normal', options: [ { value: 'normal', label: 'Normal' }, { value: 'dissolve', label: 'Dissolve' }, ], }, { label: 'Darken', options: [ { value: 'multiply', label: 'Multiply' }, { value: 'darken', label: 'Darken' }, { value: 'color-burn', label: 'Color Burn' }, ], }, ]} value={mode} onChange={setMode}/>Searchable
Enable the searchable prop to show a filter input inside the dropdown. A custom filter function can be provided with filterFn.
<Select searchable searchPlaceholder="Filter blend modes..." emptyMessage="No matching modes" options={allBlendModes} value={mode} onChange={setMode}/>// Custom filter logic<Select searchable filterFn={(option, query) => option.value.startsWith(query.toLowerCase())} options={options} value={value} onChange={setValue}/>Clearable
When clearable is enabled, a clear button appears when a value is selected.
<Select clearable placeholder="Choose a material..." options={materials} value={material} onChange={setMaterial}/>Options with Icons
Each option can include an icon rendered before its label.
<Select options={[ { value: 'mesh', label: 'Mesh', icon: <MeshIcon /> }, { value: 'light', label: 'Light', icon: <LightIcon /> }, { value: 'camera', label: 'Camera', icon: <CameraIcon /> }, ]} value={objectType} onChange={setObjectType}/>Variants
The variant prop controls the trigger button style.
<Select variant="default" options={opts} value={v} onChange={setV} /><Select variant="ghost" options={opts} value={v} onChange={setV} /><Select variant="filled" options={opts} value={v} onChange={setV} />Sizes
<Select size="sm" options={opts} value={v} onChange={setV} /><Select size="md" options={opts} value={v} onChange={setV} /><Select size="lg" options={opts} value={v} onChange={setV} />| Size | Trigger Height | Use case |
|---|---|---|
sm | 20px | Compact toolbars |
md | 24px | Standard panels |
lg | 32px | Prominent forms |
Labels and Helper Text
<Select label="Render Engine" helperText="Select the rendering backend" required options={engines} value={engine} onChange={setEngine}/>Error State
<Select label="Material" error errorMessage="A material is required" options={materials} value={material} onChange={setMaterial}/>Form Integration
Use the name prop for native form submission. A hidden <input> is rendered with the selected value.
<Select name="blendMode" options={blendModes} value={mode} onChange={setMode} />Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | T | null | — | Selected value (controlled). |
defaultValue | T | — | Default selected value (uncontrolled). |
options | Array<SelectOptionItem<T> | SelectOptionGroup<T>> | — | Options to display — flat list or grouped. |
placeholder | string | 'Select...' | Placeholder text when no value is selected. |
searchable | boolean | false | Whether to show a search input inside the dropdown. |
searchPlaceholder | string | 'Search...' | Placeholder for the search input. |
filterFn | (option: SelectOptionItem<T>, query: string) => boolean | — | Custom filter function for searchable mode. |
emptyMessage | string | 'No results found' | Message shown when search yields no results. |
size | 'sm' | 'md' | 'lg' | 'md' | Size of the trigger button. |
variant | 'default' | 'ghost' | 'filled' | 'default' | Visual variant of the trigger button. |
label | string | — | Label displayed above the select. |
helperText | string | — | Helper text displayed below the select. |
error | boolean | false | Error state. |
errorMessage | string | — | Error message shown when in error state. |
disabled | boolean | false | Whether the select is disabled. |
required | boolean | false | Whether the select is required. |
clearable | boolean | false | Whether a clear button appears when a value is selected. |
maxDropdownHeight | number | 240 | Maximum height of the dropdown in pixels. |
minDropdownWidth | number | — | Minimum width of the dropdown in pixels. |
name | string | — | Name attribute for hidden input (form submission). |
onChange | (value: T | null) => void | — | Callback when the selected value changes. |
onOpenChange | (open: boolean) => void | — | Callback when the dropdown open state changes. |
className | string | — | Additional CSS class names. |
style | CSSProperties | — | Inline styles. |
testId | string | — | Test identifier for automated testing. |
ref | Ref<HTMLButtonElement> | — | Ref to the trigger button element. |
SelectOptionItem
| Prop | Type | Description |
|---|---|---|
value | T | Unique value used for selection. |
label | string | Display label (falls back to value). |
icon | ReactNode | Optional icon rendered before the label. |
disabled | boolean | Whether this option is disabled. |
SelectOptionGroup
| Prop | Type | Description |
|---|---|---|
label | string | Group header label (non-selectable). |
options | SelectOptionItem<T>[] | Options within this group. |
Accessibility
- Trigger renders as a
<button>withrole="combobox"andaria-haspopup="listbox" - Dropdown renders as a
role="listbox"withrole="option"children - Grouped options use
role="group"witharia-label - Full keyboard navigation: Arrow Up/Down to navigate, Enter to select, Escape to close, Home/End for first/last
aria-expandedreflects the dropdown open statearia-selectedmarks the current selectionaria-invalidis set when in error statearia-requiredis set when the select is requiredaria-describedbylinks to helper/error text- Clear button has
aria-label="Clear selection"