Select
A composable, accessible Select component for modern React applications.
tsx
import { Select } from '@nofinite/nui';Interactive Preview
Loading preview...
A fully accessible dropdown component that allows users to choose a single option from a list. It supports controlled and uncontrolled modes, portal-based positioning, keyboard navigation with typeahead search, and error/disabled states.
Usage
Basic usage
tsx
import { Select } from '@nofinite/nui';
const options = [
{ value: 'apple', label: 'Apple' },
{ value: 'banana', label: 'Banana' },
{ value: 'orange', label: 'Orange' },
];
<Select options={options} />;Controlled usage
tsx
const [value, setValue] = useState('apple');
<Select options={options} value={value} onChange={setValue} />;With placeholder
tsx
<Select options={options} placeholder="Choose fruit" />Disabled options
tsx
<Select
options={[
{ value: 'a', label: 'A' },
{ value: 'b', label: 'B', disabled: true },
]}
/>Error state
tsx
<Select options={options} error />Form integration
tsx
<Select options={options} name="fruit" />Variants
Validation state
tsx
<Select error />
<Select disabled />Available variants
- default
- error
- disabled
Guidelines
- Use error for validation feedback
- Use disabled when input is unavailable
- Avoid mixing disabled and error simultaneously
States
- Default
- Open / closed
- Hover
- Focus visible
- Active option (keyboard)
- Selected option
- Disabled option
- Error
- Typeahead navigation
Keyboard Interaction
| Key | Behavior |
|---|---|
| ArrowDown / ArrowUp | Navigate options |
| Enter / Space | Select active option |
| Home | Jump to first enabled option |
| End | Jump to last enabled option |
| Escape | Close dropdown |
| Character typing | Typeahead search |
| Enter / Space on trigger | Open dropdown |
Accessibility
- Uses
buttontrigger witharia-haspopup="listbox" aria-expandedandaria-controlsreflect open state- List uses
role="listbox" - Options use
role="option" aria-selectedandaria-disabledper option- Focus restored to trigger after close
- Typeahead navigation for screen reader parity
- Hidden input ensures form compatibility
z-dropdown | Portal layering | | --radius-md/lg | Shape tokens | | --space-* | Padding & spacing |
Best Practices
Do
- Use portal positioning for overflow-safe dropdowns
- Provide placeholder for clarity
- Keep option labels concise
- Disable unavailable options instead of removing them
- Use error state with supporting helper text
Don’t
- Use extremely long option labels without truncation
- Nest interactive elements inside options
- Use dropdowns for very large datasets (prefer combobox)
- Disable typeahead in keyboard-heavy workflows
- Omit name prop when using in forms
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
data* | SelectOption[] | — | Array of available options |
value | string | — | Controlled state value |
defaultValue | string | — | Uncontrolled initial value |
onChange | ((value: string) => void) | — | Callback fired when an option is selected |
placeholder | string | Select... | Text displayed when no option is selected |
name | string | — | Name attribute applied to the hidden input for native form submission |
error | boolean | false | Applies error styling to the trigger button |