Skip to content

Select

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

import {
Select,
SelectTrigger,
SelectValue,
SelectContent,
SelectGroup,
SelectLabel,
SelectItem,
} from '@nim-ui/components';

Variants

Default

Default Select

View 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>

With Groups

Grouped Select

View 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>

Sizes

The SelectTrigger supports size variants through CVA styling.

Select Sizes

View 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>

States

Disabled

Disabled State

View Code
<Select disabled>
<SelectTrigger className="w-[200px]">
<SelectValue placeholder="Disabled select" />
</SelectTrigger>
<SelectContent>
<SelectItem value="a">Option A</SelectItem>
</SelectContent>
</Select>

Disabled Items

Disabled Individual Items

View 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>

Props

Select

Name Type Default Description
value string - Controlled value of the selected item
onValueChange (value: string) => void - Callback fired when the selected value changes
defaultValue string - Initial selected value for uncontrolled usage
disabled boolean false Whether the select is disabled

SelectTrigger

Name Type Default Description
className string - Additional CSS classes for styling the trigger button
children * ReactNode - Trigger content, typically a SelectValue component

SelectValue

Name Type Default Description
placeholder string - Text to display when no value is selected

SelectContent

Name Type Default Description
position 'popper' | 'item-aligned' 'popper' Positioning mode for the dropdown content
className string - Additional CSS classes for the dropdown container

SelectItem

Name Type Default Description
value * string - Unique value for this option
disabled boolean false Whether this item is disabled
className string - Additional CSS classes to apply
children * ReactNode - Display text for this option

SelectGroup

Name Type Default Description
className string - Additional CSS classes for the group container

SelectLabel

Name Type Default Description
className string - Additional CSS classes for the group label
children * ReactNode - Label text for the group

Usage Examples

Country Selector

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>
);
}

Form with Select

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>
);
}

Dynamic Options

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>
);
}

Accessibility

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

Keyboard Support

KeyAction
Space / EnterOpens the select dropdown or selects focused item
Arrow DownOpens dropdown or moves focus to next item
Arrow UpMoves focus to previous item
HomeMoves focus to first item
EndMoves focus to last item
EscapeCloses the dropdown
Type-aheadFocuses matching item by typing characters

Best Practices

  • 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