Select
The Select
component provides a dropdown interface for selecting a single value from a list of options. It supports both controlled and uncontrolled modes, async loading states, search functionality, and integrates seamlessly with form validation.
Usage
import { Select } from "@harnessio/ui/components";
//...
return ( <Select options={[ { label: "One", value: "one" }, { label: "Two", value: "two" }, { label: "Three", value: "three" }, { label: "Four", value: "four", disabled: true }, ]} defaultValue="three" onChange={(value) => console.log(value)} />)
Suffix Example
The Select
component can be customized with a suffix element that appears on the right side of the input.
Form Integration
The Select
component integrates seamlessly with form elements like labels, captions, and validation messages.
Search Functionality
Enable client-side search filtering to help users find options quickly in large or structured lists.
Async Loading
Options can be loaded asynchronously by passing a function that returns a Promise.
Disabled States
Both the entire select and individual options can be disabled.
Loading States
The Select component provides clear loading indicators for different scenarios.
Complex Option Labels
Options can have ReactNode labels for rich content display.
Custom Option Renderer
Customize how individual options are rendered using the optionRenderer
prop. This allows advanced layouts or UI elements for each option.
Grouped Options and Separators
Header and Footer
Sizes
The Select
component supports two sizes: default
and sm
. The default size is suitable for most use cases, while the sm
size is useful for compact layouts.
API Reference
Select
The Select
component is the main component for creating dropdown selections.
<Select options={options} // Array of options or async function value={value} // [OPTIONAL] controlled value defaultValue // [OPTIONAL] default value for uncontrolled mode onChange={onChange} // [OPTIONAL] change handler disabled // [OPTIONAL] disable the select onScrollEnd={onScroll} // [OPTIONAL] infinite scroll callback placeholder="Select..." // [OPTIONAL] placeholder text isLoading // [OPTIONAL] loading state allowSearch // [OPTIONAL] enable search onSearch={customSearch} // [OPTIONAL] custom search function optionRenderer={renderer} // [OPTIONAL] custom option renderer
// Form integration props id="my-select" // [OPTIONAL] HTML id label="Label" // [OPTIONAL] form label error="Error message" // [OPTIONAL] error message warning="Warning" // [OPTIONAL] warning message caption="Help text" // [OPTIONAL] caption text optional // [OPTIONAL] mark as optional theme="default" // [OPTIONAL] theme variant className="custom-class" // [OPTIONAL] custom className/>
Prop | Required | Default | Type |
---|---|---|---|
options | true | SelectOption<T>[] | () => Promise<SelectOption<T>[]> | |
value | false | T | |
defaultValue | false | T | |
onChange | false | (value: T) => void | |
onSelectedChange | false | (event: ChangeEvent<HTMLInputElement>) => void | |
disabled | false | false | boolean |
onScrollEnd | false | () => void | |
size | false | 'md' | 'sm' | 'md' |
placeholder | false | 'Select an option' | string |
isLoading | false | false | boolean |
id | false | Auto-generated | string |
name | false | string | |
label | false | string | |
suffix | false | ReactNode | |
theme | false | 'default' | 'default' | 'danger' | 'warning' |
caption | false | string | |
error | false | string | |
warning | false | string | |
optional | false | false | boolean |
allowSearch | false | false | boolean |
onSearch | false | Filters by label containing query | (query: string) => SelectOption<T>[] |
searchValue | false | string | |
optionRenderer | false | (option: ValueOption<T>) => SelectItemType | |
header | false | ReactNode | |
footer | false | ReactNode | |
contentWidth | false | 'auto' | 'triggerWidth' | 'auto' |
rootClassName | false | string | |
triggerClassName | false | string | |
contentClassName | false | '' | string |
SelectOption
The SelectOption
interface defines the shape of each option in the select dropdown.
type SelectOption<T = string> = | { label: string | ReactNode; value: T; disabled?: boolean; } | { label: string; options: Array< | { label: string | ReactNode; value: T; disabled?: boolean; } | "-" >; } | "-";
Prop | Required | Default | Type |
---|---|---|---|
label | true | string | ReactNode | |
value | true | T | |
disabled | false | false | boolean |
Behavior
- When
options
is a promise-returning function, the component shows a loading spinner while fetching - The dropdown shows a loading spinner at the bottom when
isLoading
is true and there are existing options (for infinite scroll) - Search input appears at the top of the dropdown when
allowSearch
is true - The default search implementation filters options by checking if the label contains the query (case-insensitive)
- Search query is cleared when the dropdown closes or an option is selected
- Form validation states (
error
,warning
) automatically set the appropriate theme - The component supports generic types for option values, not limited to strings
- If optionRenderer is provided, it overrides the default option rendering logic. This can be used to inject custom components such as avatars, icons, or descriptions for each option.
Accessibility
- The Select component uses semantic HTML with proper ARIA attributes
- Keyboard navigation is fully supported (Arrow keys, Enter, Escape)
- Screen readers announce the selected value and available options
- The trigger button is properly labeled when used with the
label
prop - Focus management follows WCAG guidelines
- Search input receives focus automatically when the dropdown opens with search enabled