Skip to content

Headless Core — Select

Powers Select internally. The most keyboard-heavy factory in the package — full ArrowDown/ArrowUp/Home/End navigation that skips disabled options and wraps at the ends, plus typeahead (type letters to jump to a matching option).

import { createSelect } from '@andersseen/headless-components/select';
const select = createSelect({
options: [
{ value: 'sm', text: 'Small' },
{ value: 'md', text: 'Medium' },
{ value: 'lg', text: 'Large', disabled: true },
],
defaultValue: 'sm',
onValueChange: value => console.log('Selected:', value),
});
select.actions.open();
select.actions.highlightNext();
select.actions.selectHighlighted();
OptionTypeDefaultNotes
optionsSelectOption[][]{ value, text, disabled? }.
defaultValuestring
disabledbooleanfalse
onValueChange(value: string) => void
onOpenChange(isOpen: boolean) => void

isOpen, highlightedIndex (-1 = none), selectedValue: string | null, disabled.

MemberSignatureNotes
actions.open() / close() / toggle()() => voidopen() highlights the current selection, or the first enabled option.
actions.highlightNext() / highlightPrev()() => voidSkips disabled options; wraps at the ends.
actions.highlightFirst() / highlightLast()() => void
actions.selectHighlighted()() => voidSelects the highlighted option, then closes.
actions.selectValue(value)(value: string) => void
actions.setDisabled(v)(disabled: boolean) => void
actions.setOptions(options)(options: SelectOption[]) => voidRe-registers the option list (e.g. after an async load).
queries.isOpen()() => boolean
queries.getSelectedText()() => string | undefined
queries.getHighlightedOption()() => SelectOption | undefined
queries.getOptions()() => SelectOption[]
GetterReturns
getTriggerProps()aria-haspopup: 'listbox', aria-expanded, aria-disabled, data-state
getMenuProps()role: 'listbox', aria-label: 'Options', data-state, hidden
getItemProps(option, index)role: 'option', aria-selected, aria-disabled, data-state ('active' | 'highlighted' | 'inactive'), tabindex (0 only when highlighted)

handleTriggerKeyDown(event) opens on Enter/Space/ArrowDown/ArrowUp, or on any printable character (which also starts a typeahead search). handleMenuKeyDown(event)Escape/Tab close; ArrowDown/ArrowUp move the highlight (Alt+ArrowDown/Alt+ArrowUp close instead, matching the native <select> convention); Home/End jump; Enter/Space select the highlighted option; any other printable character continues the typeahead buffer (reset after 500ms of inactivity).

Open Highlight next Select highlighted

Input — the simpler text-entry relative, no options list.