Select Input

A form input component that combines the styling and features of a text input with dropdown selection functionality. Displays as an input field that opens a selector dropdown when clicked.

Basic Usage

import { SelectInput } from '@/components'
import { Selector } from '@/components'

const [value, setValue] = useState('')

<SelectInput
  placeholder="Select a department..."
  value={value}
  onValueChange={setValue}
>
  <Selector.Content>
    <Selector.Search placeholder="Search..." />
    <Selector.Item value="design">Design</Selector.Item>
    <Selector.Item value="development">Development</Selector.Item>
    <Selector.Item value="marketing">Marketing</Selector.Item>
  </Selector.Content>
</SelectInput>

With Label and Hint

Add a label and helper text to guide users.

<SelectInput
  label="Department"
  hint="Select the department you work in"
  placeholder="Select a department..."
  value={value}
  onValueChange={setValue}
>
  <Selector.Content>
    <Selector.Search placeholder="Search..." />
    <Selector.Item value="design">Design</Selector.Item>
    <Selector.Item value="development">Development</Selector.Item>
  </Selector.Content>
</SelectInput>

Select the department you work in

Required Field

Use the required prop to show a required indicator (blue asterisk). Add showInfoIcon and tooltip for additional context.

<SelectInput
  label="Department"
  hint="This is a hint text to help users."
  placeholder="Select a department..."
  value={value}
  onValueChange={setValue}
  required
  showInfoIcon
  tooltip="Select your primary department"
>
  <Selector.Content>
    ...
  </Selector.Content>
</SelectInput>

This is a hint text to help users.

Optional Field

Use showOptionalBadge to indicate optional fields.

<SelectInput
  label="Secondary Department"
  hint="You can optionally select a secondary department"
  placeholder="Select a department..."
  value={value}
  onValueChange={setValue}
  showOptionalBadge
  showInfoIcon
>
  <Selector.Content>
    ...
  </Selector.Content>
</SelectInput>

You can optionally select a secondary department

Sizes

The input comes in three sizes: small (36px), medium (40px, default), and large (44px).

Small (36px)

Medium (40px) - Default

Large (44px)

Small

<SelectInput size="sm" label="Department" placeholder="Select..." ... />

Medium (Default)

<SelectInput size="md" label="Department" placeholder="Select..." ... />

Large

<SelectInput size="lg" label="Department" placeholder="Select..." ... />

States

The input has multiple visual states: Default (idle), Filled, Error, and Disabled.

Default (Idle)

Filled

Error

Please select a department

Disabled

With Left Icon

Add an icon to the left side of the input for visual context.

import { User } from 'iconoir-react'

<SelectInput
  label="Select User"
  hint="Choose a team member"
  placeholder="Select a user..."
  value={value}
  onValueChange={setValue}
  leftIcon={<User className="size-5" />}
>
  <Selector.Content>
    <Selector.Search placeholder="Search users..." />
    <Selector.Item value="john" variant="user" secondaryText="@johndoe">
      John Doe
    </Selector.Item>
    ...
  </Selector.Content>
</SelectInput>

Choose a team member

Multi-Select

Enable multi-selection mode with the multiple and showCheck props.

const [value, setValue] = useState<string[]>([])

const selectedLabels = value
  .map(v => options.find(o => o.value === v)?.label)
  .filter(Boolean)
  .join(', ')

<SelectInput
  label="Departments"
  hint="Select multiple departments"
  placeholder="Select departments..."
  value={value}
  onValueChange={setValue}
  multiple
  showCheck
  displayValue={selectedLabels || undefined}
>
  <Selector.Content>
    <Selector.Search placeholder="Search..." />
    <Selector.Item value="design">Design</Selector.Item>
    <Selector.Item value="development">Development</Selector.Item>
    <Selector.Item value="marketing">Marketing</Selector.Item>
  </Selector.Content>
</SelectInput>

Select multiple departments

With Add Button

Allow users to add new options using Selector.AddButton.

<SelectInput
  label="Department"
  hint="You can add new departments"
  placeholder="Select a department..."
  value={value}
  onValueChange={setValue}
>
  <Selector.Content>
    <Selector.Search placeholder="Search..." />
    {options.map(opt => (
      <Selector.Item key={opt.value} value={opt.value}>
        {opt.label}
      </Selector.Item>
    ))}
    <Selector.AddButton onClick={handleAdd}>Add new department</Selector.AddButton>
  </Selector.Content>
</SelectInput>

You can add new departments

Controlled Component

Control the input value externally and display the selected label.

const [value, setValue] = useState('')
const selectedLabel = options.find(o => o.value === value)?.label

<SelectInput
  label="Department"
  hint={`Selected: ${selectedLabel || 'None'}`}
  placeholder="Select a department..."
  value={value}
  onValueChange={setValue}
  displayValue={selectedLabel}
  required
>
  <Selector.Content>
    ...
  </Selector.Content>
</SelectInput>

Selected: None

Country Selection Example

Example showing country selection with an icon.

Select your country

All States Overview

Idle

Filled

Error

Disabled

Accessibility

  • Labels are properly associated with the trigger via htmlFor/id
  • aria-describedby connects hint/error text to the input
  • aria-invalid is set when in error state
  • aria-required is set for required fields
  • Full keyboard navigation support for the dropdown
  • Trigger button is focusable and activates with Enter/Space

API Reference

SelectInput Props

PropTypeDefaultDescription
labelstring-Label text above the input
hintstring-Hint text below the input
errorboolean | stringfalseError state or error message
size'sm' | 'md' | 'lg''md'Input size variant
requiredbooleanfalseMark as required (shows asterisk)
disabledbooleanfalseDisable the input
showOptionalBadgebooleanfalseShow "(Optional)" badge
showInfoIconbooleanfalseShow info icon in label
tooltipstring-Tooltip text for info icon
leftIconReactNode-Icon to show on the left
placeholderstring'Select an option...'Placeholder text
valuestring | string[]-Controlled value
defaultValuestring | string[]-Default value (uncontrolled)
onValueChange(value: string | string[]) => void-Callback when value changes
multiplebooleanfalseEnable multi-selection
showCheckbooleanfalseShow checkmarks on selected items
openboolean-Controlled open state
defaultOpenbooleanfalseDefault open state
onOpenChange(open: boolean) => void-Callback when open state changes
displayValuestring-Custom display text for selected value
childrenReactNode-Selector.Content with items

Styling Props

PropTypeDescription
containerClassNamestringClass for the root container
labelClassNamestringClass for the label
fieldClassNamestringClass for the input field
hintClassNamestringClass for the hint text