Edit Profile

Dark Mode

Copy config

Copy and paste the following code into your global.css file to apply the styles.

DISCLAIMER: This component is in
Beta
status. That means that it is ready for production, but the API might change.

Combobox

A customizable text field with a listbox, enabling users to constrain a list of choices based on their search criteria.

Qwik UI's Combobox implementation follows the WAI-Aria Combobox specifications, along with some additional API's that enhance the flexibility, types, and performance.

✨ Features

  • Full WAI-Aria compliance
  • Full keyboard navigation
  • Custom Autocomplete behavior
  • Custom filter functionality
  • Controlled or uncontrolled
  • Supports disabled options
  • Custom signal binds
  • Animatable, dynamic, and resumable

Building blocks

import { component$ } from '@builder.io/qwik';
import { Combobox, ResolvedOption } from '@qwik-ui/headless';

export default component$(() => {
  const data = ['a', 'b', 'c'];

  return (
    <Combobox.Root options={data}>
      <Combobox.Label>Label Element</Combobox.Label>
      <Combobox.Control>
        <Combobox.Input />
        <Combobox.Trigger>Opens Listbox</Combobox.Trigger>
      </Combobox.Control>
      <Combobox.Popover>
        <Combobox.Listbox
          optionRenderer$={(option: ResolvedOption, index: number) => (
            <Combobox.Option index={index} resolved={option}>
              Option Label
            </Combobox.Option>
          )}
        />
      </Combobox.Popover>
    </Combobox.Root>
  );
});

🎨 Anatomy

ComponentDescription
Combobox.Root

The root container for the Combobox.

Combobox.Label

A label element to connect to the Combobox.

Combobox.Control

A container for the combobox trigger, and input.

Combobox.Input

An input element used for filtering, and controlling the combobox state.

Combobox.Trigger

A button that toggles the corresponding listbox when clicked.

Combobox.Popover

A Popover component that teleports the children outside its parent when the listbox state is open.

Combobox.Listbox

An unordered list that contains multiple options that display when opened.

Combobox.Option

A list item that is shown based on the listbox state and filter API.

Passing data

Qwik UI's Combobox supports both string and option data. Whether that's an array of strings, or an array of objects. To pass in data, add the options prop on the Combobox Root.

String example

Under the hood, the data passed in populates the listbox with options. To see options visually, add the renderOption$ prop on the Combobox Listbox. This prop is a QRL, inside is a callback where the ComboboxOption component needs to be passed in.

Object example

The callback takes two parameters:

  • An object that holds the resolved option data.
  • The option index.

The resolved object also holds:

  • The key.
  • Option Label.
  • Option Value.
  • Any disabled options.

Import the ResolvedOption type from Qwik UI and pass in the data according to the code block below.

import { component$ } from '@builder.io/qwik';
import { Combobox, ResolvedOption } from '@qwik-ui/headless';

export default component$(() => {
  return (
    <Combobox.Listbox
      optionRenderer$={(option: ResolvedOption, index: number) => (
        <Combobox.Option key={option.key} index={index} resolved={option}>
          {option.label}
        </Combobox.Option>
      )}
    />
  );
});

Adding a filter

Out of the box, the Combobox comes with a default filter that uses the string.includes method to filter options. To add a custom filter, you can use the filter$ QRL.

In this example, the filter function retrieves the input value and options object. It then filters the options using the JavaScript string.startsWith method as part of our filter logic. However, you are not limited to this method. You can use any filtering method of your choice to customize the behavior to suit your needs.

Sorting

In our previous example, you may have noticed that the country data wasn't sorted alphabetically. To sort options, add an additional sort method after the filter.

Disabled Behavior

There are two ways to indicate that an option is disabled:

  • Using the default disabled key.
  • Passing a unique key name using the optionDisabledKey prop.

The optionDisabledKey prop does not need to be passed when there is a key already named disabled, OR you do not have any disabled options.

Custom Key Names

As we saw previously with the optionDisabledKey prop, custom key names can also be passed in for values and labels.

In some cases, your data object keys may not match the default keys that the Combobox component expects for option values and labels. By default, the Combobox component looks for keys named value for option values and label for option labels.

If your data object keys are different, you can specify custom key names using the optionValueKey and optionLabelKey props.

import { Combobox } from '@qwik-ui/headless';
import { component$ } from '@builder.io/qwik';

type Pokemon = {
  pokedex: string;
  pokemon: string;
  isPokemonCaught: boolean;
};

const pokemonExample: Array<Pokemon> = [
  { pokedex: '1', pokemon: 'Bulbasaur', isPokemonCaught: true },
  { pokedex: '2', pokemon: 'Ivysaur', isPokemonCaught: false },
  { pokedex: '3', pokemon: 'Venusaur', isPokemonCaught: false },
  { pokedex: '4', pokemon: 'Charmander', isPokemonCaught: true },
  { pokedex: '5', pokemon: 'Charmeleon', isPokemonCaught: true },
  { pokedex: '6', pokemon: 'Charizard', isPokemonCaught: true },
  { pokedex: '7', pokemon: 'Squirtle', isPokemonCaught: false },
  { pokedex: '8', pokemon: 'Wartortle', isPokemonCaught: false },
];

export default component$(() => {
  return (
    <Combobox.Root
      options={pokemonExample}
      optionValueKey="pokedex"
      optionLabelKey="pokemon"
      optionDisabledKey="isPokemonCaught"
    />
  );
});

Within our example, the value key is called pokedex and the label key is called pokemon. This tells the Combobox component to use the "pokedex" key for option values and the "pokemon" key for option labels.

Configuring the Input

Disabling Blur

The Qwik UI Combobox uses the onBlur$ event on the input to close the listbox when interacting with other elements.

I have blur disabled! Inspect me in the dev tools.

This can get tedious if certain custom behavior needs to be added, or the listbox needs to be inspected in the dev tools.

To disable this behavior, set disableOnBlur={true} on the Input.

Customizing State Signals

The Combobox component allows you to customize its state signals. This can be useful if you want to control or observe these states externally.

In reality it is a signal prop, we prefer using this syntax, because we believe it is familiar to Qwik developers with the bind syntax.

PropTypeDescription
bind:inputValue
Signal

Controls the current value of the input.

bind:selectedIndex
Signal

Controls the selected option index.

bind:isListboxOpen
Signal

Controls the open state of the listbox.

bind:isInputFocused
Signal

Controls the focus state of the input.

bind:highlightedIndex
Signal

Controls which option is highlighted.

Here is an example of how to customize these signals:

When clicking on the input, it will now toggle the listbox. Signal binds are a useful toolbelt when customizing state is needed.

Default Label

To set a default Label, pass the defaultLabel prop to the Combobox Root, along with the string label. This label connects to its proper option value, and highlights it accordingly.

Setting a default highlighted index

With the trick we learned about signal binds earlier, we can highlight an index by default, or customize the highlighted index based on user interaction.

Third option highlighted! 🚨

A common use case for an Autocomplete is a search bar. Here's an example of that using the Combobox.

This example shows MPA navigation using the Search Bar component. For SPA navigation, use Qwik's useNavigate hook.

Keyboard interactions

Key

Description

Enter
Selects the highlighted option. The listbox closes and the selected option becomes the input's value.
Down Arrow
Opens the listbox and shifts focus to the first option. If focus is already on an option, it moves to the next one. If no next option exists, focus returns to the first option.
Up Arrow
If focus is on an option, it moves to the previous option. If no previous option exists, focus moves to the last option.
Escape
Closes the listbox.
Home
Moves the cursor to the start of the input value when the input is focused. When any listbox option is focused, focus shifts to the first enabled option.
End
Moves the cursor to the end of the input value when the input is focused. When any listbox option is focused, focus shifts to the last enabled option.
Delete
Deletes the selected text in the input.

API

The Combobox component API provides a set of properties that allow you to customize the behavior and appearance of the combobox. Here are the notable properties for this component.

Combobox (Root)

PropTypeDescription
options
O[]

An array of options for the combobox.

filter$
QRL

A QRL for a custom filter function.

optionValueKey
string

The key for the option value.

optionLabelKey
string

The key for the option label.

optionDisabledKey
string

The key for the disabled option.

defaultLabel
string

The default label for the combobox.

bind:selectedIndex
Signal<number>

A signal for the selected option index.

bind:isListboxOpen
Signal<boolean>

A signal for the open state of the listbox.

bind:isInputFocused
Signal<boolean>

A signal for the focus state of the input.

bind:inputValue
Signal<string>

A signal for the current value of the input.

bind:highlightedIndex
Signal<number>

A signal for the highlighted option index.

ComboboxTrigger

PropTypeDescription
onMouseDown$
function

A QRL that toggles the open state of the listbox on mouse down.

tabIndex
number

The tab index of the trigger button. Set to 0 by default.

ComboboxInput

PropTypeDescription
disableOnBlur
boolean

Disables the onBlur event on the input.

onInput$
function

A QRL for handling input events.

onBlur$
function

A QRL for handling blur events.

onKeyDown$
function

A QRL for handling keydown events.

type
string

The type of the input element.

value
string

The current value of the input element.

placeholder
string

The placeholder text for the input element.

ComboboxPopover

The Combobox Popover is a wrapper of Qwik UI's popover component. You can view the full API table at the bottom of the popover page.

ComboboxListbox

PropTypeDescription
optionRenderer$
QRL

A QRL for rendering the options.

placement
union

The placement of the listbox.

gutter
number

The gutter space between the input and the floating element.

flip
boolean

Allows the listbox to flip its position based on available space.

size
boolean

Controls the size of the listbox.

autoPlacement
boolean

Automatically places the listbox based on available space.

hide
union

Allows hiding the listbox when it appears detached from the reference element.

ancestorScroll
boolean

Controls the scroll behavior of the listbox.

ancestorResize
boolean

Controls the resize behavior of the listbox.

elementResize
boolean

Controls the resize behavior of the listbox element.

layoutShift
boolean

Controls the layout shift of the listbox.

animationFrame
boolean

Whether to update the position of the listbox on every animation frame.

ComboboxOption

PropTypeDescription
index
number

The index of the option.

resolved
ResolvedOption

The resolved option data.

onMouseEnter$
function

A QRL for handling mouse enter events.

onClick$
function

A QRL for handling click events.

ComboboxIcon

PropTypeDescription
svg
HTMLOrSVGElement

A custom SVG element wrapped around a span with aria-hidden to be used as the icon. If an SVG is not passed inside, it will use the library default caret icon.