Skip to content

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.

// Controlled
const [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} />
SizeTrigger HeightUse case
sm20pxCompact toolbars
md24pxStandard panels
lg32pxProminent 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

PropTypeDescription
valueTUnique value used for selection.
labelstringDisplay label (falls back to value).
iconReactNodeOptional icon rendered before the label.
disabledbooleanWhether this option is disabled.

SelectOptionGroup

PropTypeDescription
labelstringGroup header label (non-selectable).
optionsSelectOptionItem<T>[]Options within this group.

Accessibility

  • Trigger renders as a <button> with role="combobox" and aria-haspopup="listbox"
  • Dropdown renders as a role="listbox" with role="option" children
  • Grouped options use role="group" with aria-label
  • Full keyboard navigation: Arrow Up/Down to navigate, Enter to select, Escape to close, Home/End for first/last
  • aria-expanded reflects the dropdown open state
  • aria-selected marks the current selection
  • aria-invalid is set when in error state
  • aria-required is set when the select is required
  • aria-describedby links to helper/error text
  • Clear button has aria-label="Clear selection"