nalarx-ui
Components

Select

The one dropdown, plain or searchable, with groups, hints and an optional create row.

bunx shadcn@latest add @nalarx/select

Usage

<Select ariaLabel="Time zone" value={zone} onChange={setZone} options={zones} />
<Select ariaLabel="Owner" value={owner} onChange={setOwner} searchable groups={teams} />

Secondary text, hints at size="sm", a searchable grouped list with a placeholder, a searchable list with a create row, an icon-only trigger, disabled:

States

  • Placeholder: ink-4 when value matches no option.
  • Open: the chevron turns; the panel is at least the trigger's width and at most maxPanelWidth (360px) and the screen width.
  • Chosen option: semibold, bg-hover, check on the right.
  • Disabled option: 55% in ink-4, skipped by the keyboard. Disabled select: 50%.
  • Searchable: a search box tops the panel and filters by label, secondary text, hint and value. Nothing matching shows emptyMessage. Empty groups disappear.
  • createOption: with flat options, a typed query can add one more row (for example Add "foo"); picking it calls onChange with its value.

Keyboard

KeyPlainSearchable
Enter, Space, ArrowDown on the triggerOpens on the chosen optionOpens with focus in the search box
ArrowDown / ArrowUpMoves through optionsMoves the highlight while you keep typing
Home / EndFirst / last optionCaret start / end in the search box
TypingJumps to the option starting with the lettersFilters the list
EnterPicks and closesPicks the highlighted option
EscapeCloses, focus back on the triggerSame

Props

PropTypeDefault
valueT
onChange(value: T) => void
ariaLabelstringNames the trigger and the list.
options / groupsSelectOption<T>[] / SelectGroup<T>[]groups wins.
placeholderstringselectPlaceholder string
size"sm" | "md""md"30px / 36px.
width, minWidthnumber | stringA number is pixels.
heightnumberOverrides size.
searchablebooleanfalse
searchPlaceholderstringsearchPlaceholder stringAlso the search box's name.
emptyMessagestringnoMatches string
maxPanelWidthnumber360
triggerContentReactNodeReplaces label and chevron.
createOption(query, hasMatches) => SelectOption<T> | nullSearchable, flat options only. Keep it stable.
disabled, className

SelectOption has value, label, icon?, disabled?, hint?, secondary?. filterSelectOptions is the search rule as a pure function.

Replaces

Select.tsx and ModernSelect.tsx in both apps; the Platform base/Select.tsx becomes an adapter (onValueChange → onChange, height={32}); the web base/Select.tsx is deleted.

On this page