Skip to content

State & Events

State

getState() returns a readonly SelkitState. Subscribers receive it on every change.

FieldTypeDescription
isOpenbooleanWhether the dropdown is open.
querystringCurrent search string.
activeIndexnumberHighlighted index in visibleOptions, or -1.
selectedSelkitOption<T>[]Selected options (length 0–1 for single, 0–n for multiple).
visibleOptionsSelkitOption<T>[]Filtered, flattened options currently shown.
loadingbooleanAn initial async load is in flight.
noResultsbooleanNot loading and visibleOptions is empty (not merely below minInputLength).
disabledbooleanWhether the control is disabled.
pagenumberLoaded page for pagination (1-based; 0 before any load).
hasMorebooleanWhether another page can be loaded.
loadingMorebooleanAppending the next page (distinct from loading).

Events

Subscribe with on(event, handler).

EventPayloadFired when
openvoidThe dropdown opens.
closevoidThe dropdown closes.
change{ selected, value }Selection changes (select / deselect / clear / tag / reorder).
search{ query }The query changes via setQuery.
highlight{ index, option }The highlighted option changes.
load:start{ query }An async load begins.
load:end{ options }An async load resolves.
load:error{ error }An async load rejects.
create{ option }A tag is created.
announce{ message }A screen-reader message should be read (selection / result-count changes). Adapters write it to an aria-live region automatically.
js
controller.on('change', ({ selected, value }) => {
  console.log(value, selected)
})

controller.on('load:error', ({ error }) => {
  console.error('load failed', error)
})

a11y attributes

a11y() returns the attributes adapters spread onto the markup:

ts
interface SelkitA11y {
  trigger: {
    role: 'combobox'
    'aria-expanded': boolean
    'aria-controls': string
    'aria-haspopup': 'listbox'
    'aria-activedescendant'?: string
    'aria-disabled'?: boolean
  }
  listbox: {
    role: 'listbox'
    id: string
    'aria-multiselectable'?: boolean
  }
  option(index: number): {
    role: 'option'
    id: string
    'aria-selected': boolean
    'aria-disabled'?: boolean
  }
}

Live announcements

Beyond the static ARIA attributes, every adapter renders a visually-hidden aria-live="polite" region and writes the announce message to it, so screen readers hear selection and result-count changes. Customize the wording with the selected / deselected / cleared / resultsCountmessages. The behavior is on by default — no config needed.

Give the search input an accessible name via ariaLabel (or a placeholder, which is used as a fallback) so screen readers can identify the field. The adapters are checked against axe-core in the test suite.

Released under the MIT License.