Skip to main content

Select

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

import { Select } from '@nofinite/nui';

const options = [
{ value: 'apple', label: 'Apple' },
{ value: 'banana', label: 'Banana' },
{ value: 'orange', label: 'Orange' },
];

<Select options={options} />;

Controlled usage

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

<Select options={options} value={value} onChange={setValue} />;

With placeholder

<Select options={options} placeholder="Choose fruit" />

Disabled options

<Select
options={[
{ value: 'a', label: 'A' },
{ value: 'b', label: 'B', disabled: true },
]}
/>

Error state

<Select options={options} error />

Form integration

<Select options={options} name="fruit" />

Props

PropTypeDefaultDescription
optionsSelectOption[]List of selectable options
valuestringControlled selected value
defaultValuestringInitial uncontrolled value
onChange(value: string) => voidFired when selection changes
placeholderstringSelect...Placeholder when no value selected
namestringHidden input name for form submission
disabledbooleanfalseDisables trigger interaction
errorbooleanfalseDisplays error styling
idstringautoBase id for accessibility
classNamestringAdditional class names

Extends HTMLButtonElement attributes (excluding value, defaultValue, onChange).


Variants

Validation state

<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

KeyBehavior
ArrowDown / ArrowUpNavigate options
Enter / SpaceSelect active option
HomeJump to first enabled option
EndJump to last enabled option
EscapeClose dropdown
Character typingTypeahead search
Enter / Space on triggerOpen dropdown

Accessibility

  • Uses button trigger with aria-haspopup="listbox"
  • aria-expanded and aria-controls reflect open state
  • List uses role="listbox"
  • Options use role="option"
  • aria-selected and aria-disabled per option
  • Focus restored to trigger after close
  • Typeahead navigation for screen reader parity
  • Hidden input ensures form compatibility

Design Tokens

TokenUsage
--nui-bg-surfaceTrigger & listbox background
--nui-border-defaultInput border
--nui-border-hoverHover border
--nui-color-primarySelected option & focus
--nui-color-dangerError state
--nui-bg-subtleActive option background
--nui-brand-50Selected active background
--nui-z-dropdownPortal layering
--nui-radius-md/lgShape tokens
--nui-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