Select API
View componentThe full prop reference for the Select component. Displays a list of options for the user to pick from, triggered by a button.
Import
import { Select } from '@structyl/styled';Props
Select.Root
Root wrapper that manages the select state and provides context to child components
| Prop | Type | Default |
|---|---|---|
| children# | React.ReactNodeChild components (Trigger, Content, etc.) | — |
| value# | stringControlled selected value | — |
| defaultValue# | stringUncontrolled initial value | — |
| onValueChange# | (value: string) => voidCalled when selected value changes | — |
| open# | booleanControlled open state of dropdown | — |
| defaultOpen# | booleanUncontrolled initial open state | false |
| onOpenChange# | (open: boolean) => voidCalled when dropdown opens or closes | — |
| dir# | 'ltr' | 'rtl'Text direction for RTL support | — |
| name# | stringName attribute for form submission (creates hidden select element) | — |
| autoComplete# | stringHTML autoComplete attribute for the hidden select | — |
| disabled# | booleanDisables all interactions with the select | — |
| required# | booleanMarks the field as required for form validation | false |
| searchable# | booleanEnables search/filter functionality in dropdown | false |
| searchValue# | stringControlled search input value | — |
| defaultSearchValue# | stringUncontrolled initial search value | '' |
| onSearchValueChange# | (value: string) => voidCalled when search input changes | — |
| filterOption# | (option: SelectFilterOption, searchValue: string) => booleanCustom filter function for search (defaults to textValue/value matching) | — |
| onCreateOption# | (value: string) => voidCalled when user creates a new option via search | — |
| createOptionLabel# | React.ReactNode | ((value: string) => React.ReactNode)Label shown for create option in dropdown | — |
| resetSearchOnClose# | booleanClear search value when dropdown closes | true |
Select.Trigger
Button that opens/closes the dropdown, styled with icon and state
| Prop | Type | Default |
|---|---|---|
| asChild# | booleanMerge props onto child element instead of creating a button | — |
| className# | stringCSS class for custom styling (styled layer adds default classes) | — |
| disabled# | booleanDisable this specific trigger (merged with Root.disabled) | — |
| onClick# | (event: React.MouseEvent) => voidCustom click handler (composed with open handler) | — |
| onPointerDown# | (event: React.PointerEvent) => voidCustom pointer down handler (composed with open handler) | — |
| onKeyDown# | (event: React.KeyboardEvent) => voidCustom key down handler (composed with open handler) | — |
| children# | React.ReactNodeContent inside trigger (typically Value + Icon) | — |
Select.Value
Displays the selected value or placeholder in the trigger
| Prop | Type | Default |
|---|---|---|
| placeholder# | React.ReactNodeText/node shown when no value is selected | — |
| asChild# | booleanMerge props onto child element instead of creating a span | — |
| className# | stringCSS class for custom styling | — |
| children# | React.ReactNodeCustom render function for selected value (overrides value text) | — |
Select.Icon
Dropdown chevron icon displayed in the trigger
| Prop | Type | Default |
|---|---|---|
| asChild# | booleanMerge props onto child element instead of creating a span | — |
| className# | stringCSS class for custom styling (default: '▼') | — |
| children# | React.ReactNodeCustom icon content | '▼' |
Select.SearchInput
Search input field in the dropdown (only renders when searchable=true)
| Prop | Type | Default |
|---|---|---|
| asChild# | booleanMerge props onto child element instead of creating an input | — |
| className# | stringCSS class for custom styling | — |
| placeholder# | stringPlaceholder text for search input | — |
| onChange# | (event: React.ChangeEvent<HTMLInputElement>) => voidCustom change handler (composed with search update) | — |
| onKeyDown# | (event: React.KeyboardEvent) => voidCustom key down handler (composed with navigation/create) | — |
Select.Portal
Portals the dropdown content to document body (for z-index/overflow)
| Prop | Type | Default |
|---|---|---|
| children# | React.ReactNodeChild elements to portal | — |
| container# | Element | DocumentFragment | nullTarget DOM element for portal (defaults to document.body) | — |
| forceMount# | booleanAlways render content in DOM (even when closed) | — |
Select.Content
Dropdown content container with positioning and animations (styled wrapper)
| Prop | Type | Default |
|---|---|---|
| asChild# | booleanMerge props onto child element instead of creating a div | — |
| className# | stringCSS class for custom styling | — |
| position# | 'item-aligned' | 'popper'Positioning strategy | 'popper' |
| side# | 'top' | 'right' | 'bottom' | 'left'Preferred side to place content relative to trigger | 'bottom' |
| sideOffset# | numberDistance from trigger to content | 4 |
| align# | 'start' | 'center' | 'end'Alignment relative to trigger | 'start' |
| alignOffset# | numberOffset alignment by this distance | — |
| avoidCollisions# | booleanAuto-flip side when hitting viewport boundaries | true |
| collisionBoundary# | Element | Element[] | nullElements to check for collisions | — |
| collisionPadding# | numberPadding from collision boundary | — |
| strategy# | 'fixed' | 'absolute'CSS positioning strategy | — |
| sticky# | 'partial' | 'always'Keep content sticky when scrolling | — |
| hideWhenDetached# | booleanHide content when trigger is hidden | — |
| updatePositionStrategy# | 'always' | 'optimized'How often to recalculate position | — |
| onCloseAutoFocus# | (event: Event) => voidCalled when content closes (focus returns to trigger) | — |
| onEscapeKeyDown# | (event: KeyboardEvent) => voidCalled when Escape key pressed | — |
| onPointerDownOutside# | (event: Event) => voidCalled when pointer down outside content | — |
| options# | SelectOption[]Array of options (styled wrapper convenience, renders with Options component) | — |
| optionHeight# | numberHeight of each option for virtualization | 36 |
| optionOverscan# | numberNumber of options to render outside visible area | 6 |
| optionEmptyMessage# | React.ReactNodeMessage shown when no options match search | — |
| renderOption# | (option: SelectOption) => React.ReactNodeCustom render function for each option | — |
| showCreateItem# | booleanShow 'Create' option when onCreateOption is provided | true |
| container# | Element | DocumentFragment | nullPortal container target | — |
| forceMount# | booleanForce mount content in DOM | — |
| children# | React.ReactNodeCustom child content (alternative to options prop) | — |
Select.Item
Individual selectable option in the dropdown
| Prop | Type | Default |
|---|---|---|
| value# | stringUnique value for this option (required) | — |
| disabled# | booleanPrevent selection of this option | — |
| textValue# | stringText used for search filtering (extracted from children if not provided) | — |
| asChild# | booleanMerge props onto child element instead of creating a div | — |
| className# | stringCSS class for custom styling | — |
| children# | React.ReactNodeItem label/content (typically ItemText and ItemIndicator) | — |
| onClick# | (event: React.MouseEvent) => voidCustom click handler (composed with selection logic) | — |
| onPointerMove# | (event: React.PointerEvent) => voidCustom pointer move handler (composed with focus) | — |
| onPointerLeave# | (event: React.PointerEvent) => voidCustom pointer leave handler | — |
| onKeyDown# | (event: React.KeyboardEvent) => voidCustom key down handler (composed with arrow/enter navigation) | — |
| onFocus# | (event: React.FocusEvent) => voidCustom focus handler | — |
Select.ItemText
Text content of a select item (displays in both item and value)
| Prop | Type | Default |
|---|---|---|
| asChild# | booleanMerge props onto child element instead of creating a span | — |
| className# | stringCSS class for custom styling | — |
| children# | React.ReactNodeItem text content | — |
Select.ItemIndicator
Checkmark or custom indicator shown when item is selected
| Prop | Type | Default |
|---|---|---|
| asChild# | booleanMerge props onto child element instead of creating a span | — |
| className# | stringCSS class for custom styling | — |
| children# | React.ReactNodeCustom indicator content | — |
Select.CreateItem
Option to create a new item when searchable and onCreateOption provided
| Prop | Type | Default |
|---|---|---|
| value# | stringOverride the created value (defaults to search input) | — |
| asChild# | booleanMerge props onto child element instead of creating a div | — |
| className# | stringCSS class for custom styling | — |
| children# | React.ReactNode | ((value: string) => React.ReactNode)Custom label or function that receives search value | — |
| onClick# | (event: React.MouseEvent) => voidCustom click handler (composed with create logic) | — |
| onPointerMove# | (event: React.PointerEvent) => voidCustom pointer move handler | — |
| onPointerLeave# | (event: React.PointerEvent) => voidCustom pointer leave handler | — |
| onKeyDown# | (event: React.KeyboardEvent) => voidCustom key down handler (composed with navigation/create) | — |
Select.Options
Virtualized options container with automatic rendering of SelectOption array
| Prop | Type | Default |
|---|---|---|
| options# | SelectOption[]Array of options to render (required) | — |
| itemHeight# | numberHeight of each option for virtualization | 36 |
| overscan# | numberNumber of items to render outside visible area | 6 |
| visibleItemCount# | numberNumber of items visible at once for fallback height | 8 |
| emptyMessage# | React.ReactNodeMessage when no options match filter | 'No options found.' |
| itemClassName# | stringCSS class added to each rendered Item | — |
| itemTextClassName# | stringCSS class added to each ItemText | — |
| itemIndicatorClassName# | stringCSS class added to each ItemIndicator | — |
| renderOption# | (option: SelectOption) => React.ReactNodeCustom render function for option label | — |
| renderItemIndicator# | (option: SelectOption) => React.ReactNodeCustom render function for selection indicator | — |
| asChild# | booleanMerge props onto child element | — |
| className# | stringCSS class for custom styling | — |
| children# | React.ReactNodeRendered option items (auto-populated from options prop) | — |
Select.Group
Logical grouping of select items with optional label
| Prop | Type | Default |
|---|---|---|
| asChild# | booleanMerge props onto child element instead of creating a div | — |
| className# | stringCSS class for custom styling | — |
| children# | React.ReactNodeGroup contents (Label, Items, etc.) | — |
Select.Label
Label/header for a select group
| Prop | Type | Default |
|---|---|---|
| asChild# | booleanMerge props onto child element instead of creating a div | — |
| className# | stringCSS class for custom styling | — |
| children# | React.ReactNodeLabel text | — |
Select.Separator
Visual divider between groups or items
| Prop | Type | Default |
|---|---|---|
| asChild# | booleanMerge props onto child element instead of creating a div | — |
| className# | stringCSS class for custom styling | — |
| children# | React.ReactNodeSeparator content | — |
Select.Viewport
Scrollable container for options (used with Content)
| Prop | Type | Default |
|---|---|---|
| asChild# | booleanMerge props onto child element instead of creating a div | — |
| className# | stringCSS class for custom styling | — |
| children# | React.ReactNodeOptions/content to display | — |
Keyboard interactions
Adheres to the WAI-ARIA design pattern .
| Key | Description |
|---|---|
| Space / Enter | Opens the select / selects the focused item. |
| ArrowDown / ArrowUp | Moves focus between options. |
| Esc | Closes the select. |
Source code
If you didn't find what you need here, read the component implementation .