Select Dropdown selection component built on Radix UI
The Select component is a composite dropdown selection control built on Radix UI Select . It provides accessible, keyboard-navigable dropdowns with support for grouped options, custom triggers, and CVA-based styling variants.
import {
Select ,
SelectTrigger ,
SelectValue ,
SelectContent ,
SelectGroup ,
SelectLabel ,
SelectItem ,
} from '@nim-ui/components' ;
Default Select Code< Select >
< SelectTrigger className = "w-[200px]" >
< SelectValue placeholder = "Select a fruit" />
</ SelectTrigger >
< SelectContent >
< SelectItem value = "apple" > Apple </ SelectItem >
< SelectItem value = "banana" > Banana </ SelectItem >
< SelectItem value = "cherry" > Cherry </ SelectItem >
< SelectItem value = "grape" > Grape </ SelectItem >
< SelectItem value = "orange" > Orange </ SelectItem >
</ SelectContent >
</ Select >
Grouped Select Code< Select >
< SelectTrigger className = "w-[240px]" >
< SelectValue placeholder = "Select a timezone" />
</ SelectTrigger >
< SelectContent >
< SelectGroup >
< SelectLabel > North America </ SelectLabel >
< SelectItem value = "est" > Eastern (EST) </ SelectItem >
< SelectItem value = "cst" > Central (CST) </ SelectItem >
< SelectItem value = "pst" > Pacific (PST) </ SelectItem >
</ SelectGroup >
< SelectGroup >
< SelectLabel > Europe </ SelectLabel >
< SelectItem value = "gmt" > Greenwich (GMT) </ SelectItem >
< SelectItem value = "cet" > Central European (CET) </ SelectItem >
< SelectItem value = "eet" > Eastern European (EET) </ SelectItem >
</ SelectGroup >
</ SelectContent >
</ Select >
The SelectTrigger supports size variants through CVA styling.
Select Sizes Small Medium (default) Large Code{ /* Small */ }
< Select >
< SelectTrigger className = "w-[180px] h-8 text-sm" >
< SelectValue placeholder = "Small" />
</ SelectTrigger >
< SelectContent >
< SelectItem value = "a" > Option A </ SelectItem >
< SelectItem value = "b" > Option B </ SelectItem >
</ SelectContent >
</ Select >
{ /* Medium (default) */ }
< Select >
< SelectTrigger className = "w-[180px]" >
< SelectValue placeholder = "Medium (default)" />
</ SelectTrigger >
< SelectContent >
< SelectItem value = "a" > Option A </ SelectItem >
< SelectItem value = "b" > Option B </ SelectItem >
</ SelectContent >
</ Select >
{ /* Large */ }
< Select >
< SelectTrigger className = "w-[180px] h-12 text-lg" >
< SelectValue placeholder = "Large" />
</ SelectTrigger >
< SelectContent >
< SelectItem value = "a" > Option A </ SelectItem >
< SelectItem value = "b" > Option B </ SelectItem >
</ SelectContent >
</ Select >
Disabled State Code< Select disabled >
< SelectTrigger className = "w-[200px]" >
< SelectValue placeholder = "Disabled select" />
</ SelectTrigger >
< SelectContent >
< SelectItem value = "a" > Option A </ SelectItem >
</ SelectContent >
</ Select >
Disabled Individual Items Code< Select >
< SelectTrigger className = "w-[200px]" >
< SelectValue placeholder = "Pick an option" />
</ SelectTrigger >
< SelectContent >
< SelectItem value = "available" > Available </ SelectItem >
< SelectItem value = "sold-out" disabled > Sold Out </ SelectItem >
< SelectItem value = "coming-soon" disabled > Coming Soon </ SelectItem >
< SelectItem value = "in-stock" > In Stock </ SelectItem >
</ SelectContent >
</ Select >
Name Type Default Description valuestring- Controlled value of the selected item onValueChange(value: string) => void- Callback fired when the selected value changes defaultValuestring- Initial selected value for uncontrolled usage disabledbooleanfalseWhether the select is disabled
Name Type Default Description classNamestring- Additional CSS classes for styling the trigger button children* ReactNode- Trigger content, typically a SelectValue component
Name Type Default Description placeholderstring- Text to display when no value is selected
Name Type Default Description position'popper' | 'item-aligned''popper'Positioning mode for the dropdown content classNamestring- Additional CSS classes for the dropdown container
Name Type Default Description value* string- Unique value for this option disabledbooleanfalseWhether this item is disabled classNamestring- Additional CSS classes to apply children* ReactNode- Display text for this option
Name Type Default Description classNamestring- Additional CSS classes for the group container
Name Type Default Description classNamestring- Additional CSS classes for the group label children* ReactNode- Label text for the group
function CountrySelector () {
const [ country , setCountry ] = useState ( '' );
return (
< div className = "space-y-2" >
< label className = "block text-sm font-medium" > Country </ label >
< Select value ={ country } onValueChange ={ setCountry }>
< SelectTrigger className = "w-full" >
< SelectValue placeholder = "Select your country" />
</ SelectTrigger >
< SelectContent >
< SelectGroup >
< SelectLabel > Americas </ SelectLabel >
< SelectItem value = "us" > United States </ SelectItem >
< SelectItem value = "ca" > Canada </ SelectItem >
< SelectItem value = "mx" > Mexico </ SelectItem >
< SelectItem value = "br" > Brazil </ SelectItem >
</ SelectGroup >
< SelectGroup >
< SelectLabel > Europe </ SelectLabel >
< SelectItem value = "uk" > United Kingdom </ SelectItem >
< SelectItem value = "de" > Germany </ SelectItem >
< SelectItem value = "fr" > France </ SelectItem >
< SelectItem value = "es" > Spain </ SelectItem >
</ SelectGroup >
< SelectGroup >
< SelectLabel > Asia </ SelectLabel >
< SelectItem value = "jp" > Japan </ SelectItem >
< SelectItem value = "kr" > South Korea </ SelectItem >
< SelectItem value = "sg" > Singapore </ SelectItem >
</ SelectGroup >
</ SelectContent >
</ Select >
</ div >
);
}
function ProfileForm () {
const [ role , setRole ] = useState ( '' );
const [ department , setDepartment ] = useState ( '' );
return (
< form className = "space-y-4" >
< div >
< label className = "block text-sm font-medium mb-1" > Role </ label >
< Select value ={ role } onValueChange ={ setRole }>
< SelectTrigger className = "w-full" >
< SelectValue placeholder = "Select role" />
</ SelectTrigger >
< SelectContent >
< SelectItem value = "admin" > Administrator </ SelectItem >
< SelectItem value = "editor" > Editor </ SelectItem >
< SelectItem value = "viewer" > Viewer </ SelectItem >
</ SelectContent >
</ Select >
</ div >
< div >
< label className = "block text-sm font-medium mb-1" > Department </ label >
< Select value ={ department } onValueChange ={ setDepartment }>
< SelectTrigger className = "w-full" >
< SelectValue placeholder = "Select department" />
</ SelectTrigger >
< SelectContent >
< SelectItem value = "engineering" > Engineering </ SelectItem >
< SelectItem value = "design" > Design </ SelectItem >
< SelectItem value = "marketing" > Marketing </ SelectItem >
< SelectItem value = "sales" > Sales </ SelectItem >
</ SelectContent >
</ Select >
</ div >
< Button type = "submit" > Save Profile </ Button >
</ form >
);
}
function DynamicSelect ({ options , loading }) {
return (
< Select disabled ={ loading }>
< SelectTrigger className = "w-[240px]" >
< SelectValue placeholder ={ loading ? 'Loading...' : 'Select an option' } />
</ SelectTrigger >
< SelectContent >
{ options . map (( option ) => (
< SelectItem key ={ option . value } value ={ option . value }>
{ option . label }
</ SelectItem >
))}
</ SelectContent >
</ Select >
);
}
The Select component is built on Radix UI and follows WAI-ARIA best practices:
Uses role="combobox" on the trigger with aria-expanded state
Dropdown uses role="listbox" with role="option" on each item
Supports aria-label and aria-labelledby for screen reader announcements
Full keyboard navigation with type-ahead support
Focus is managed automatically when opening and closing
Disabled state properly communicated to assistive technology
Key Action Space / Enter Opens the select dropdown or selects focused item Arrow Down Opens dropdown or moves focus to next item Arrow Up Moves focus to previous item Home Moves focus to first item End Moves focus to last item Escape Closes the dropdown Type-ahead Focuses matching item by typing characters
Always provide a descriptive placeholder via SelectValue
Pair Select with a visible label for form context
Use SelectGroup and SelectLabel for long lists of options
Disable individual items rather than hiding them to maintain context
Provide clear, concise option labels
Radio - Radio group for visible single selection
Input - Text input for free-form entry
Checkbox - Multiple selection control
Button - Interactive button for actions