Skip to content

Listbox ​

Searchable, keyboard-navigable list. Built on reka-ui's Listbox with aurora's automatic filtering on top.

Unlike Combobox, this is not a form element — it's a standalone filterable list you compose into popovers, sidebars, or any container. Use it when you want filtering + keyboard nav without the form-input chrome.

The four pieces:

  • Listbox — root, manages selection and provides filter context
  • ListboxInput — search field, auto-filters items by their text content
  • ListboxContent — scrollable container for items
  • ListboxItem — selectable item; self-registers its text for filtering
  • ListboxEmpty — renders when the search matches nothing

Basic ​

Apple
Banana
Cherry
Durian
Elderberry
Fig
Grape
Honeydew
Kiwi
Lemon
Mango
html
<Listbox v-model="selected">
  <ListboxInput placeholder="Search…" />
  <ListboxContent>
    <ListboxItem v-for="f in fruits" :key="f" :value="f.toLowerCase()">
      {{ f }}
    </ListboxItem>
    <ListboxEmpty>No matches</ListboxEmpty>
  </ListboxContent>
</Listbox>

Custom item content ​

ListboxItem accepts arbitrary slot content. Filtering uses each item's rendered text — composite items still match against everything inside.

United StatesUS
United KingdomGB
GermanyDE
FranceFR
JapanJP
BrazilBR
AustraliaAU
html
<Listbox v-model="country">
  <ListboxInput placeholder="Search countries…" />
  <ListboxContent>
    <ListboxItem v-for="c in countries" :key="c.value" :value="c.value">
      <span class="truncate">{{ c.label }}</span>
      <span class="ml-auto text-secondary paragraph-2xs">{{ c.value.toUpperCase() }}</span>
    </ListboxItem>
    <ListboxEmpty>No countries found</ListboxEmpty>
  </ListboxContent>
</Listbox>

Inside a Popper (dropdown pattern) ​

Listbox + Popper is the canonical way to build a click-to-open searchable picker without using Combobox (which is a form input).

html
<Popper v-model:is-open="isOpen" placement="bottom-start">
  <PopperTrigger>
    <Tag clickable outline>{{ selected || 'Pick one' }}</Tag>
  </PopperTrigger>
  <PopperContent>
    <div class="w-72 rounded-2 border border-primary bg-white shadow-300 overflow-hidden">
      <Listbox v-model="selected">
        <ListboxInput placeholder="Search…" />
        <ListboxContent>
          <ListboxItem v-for="item in items" :key="item" :value="item">
            {{ item }}
          </ListboxItem>
          <ListboxEmpty>No results</ListboxEmpty>
        </ListboxContent>
      </Listbox>
    </div>
  </PopperContent>
</Popper>

Listbox — Props ​

Listbox extends reka-ui's ListboxRoot — every prop documented there is accepted. Most-used:

PropTypeDefaultDescription
modelValuestring | string[]''Selected value(s). Use v-model.
multiplebooleanfalseAllow multi-selection (modelValue becomes an array).
disabledbooleanfalseDisable the entire listbox.
classstring—Additional classes for the root.

ListboxInput ​

Search input with auto-focus on mount. Text typed here filters the items in real time (case-insensitive substring match against each item's rendered text).

PropTypeDefaultDescription
classstring—Additional classes.

Also forwards reka-ui's ListboxFilterProps.

ListboxContent ​

Scrollable container for the items. Add max-h-* and overflow-auto (or use the default styling) to constrain long lists.

ListboxItem ​

PropTypeDefaultDescription
valueAcceptableValuerequiredItem value used by v-model.
disabledbooleanfalseDisable selection.
classstring—Additional classes.

Items hide automatically when their rendered text doesn't match the current search term.

ListboxEmpty ​

Renders only when the user has typed something and zero items match. Slot content is whatever you want to display.

html
<ListboxEmpty>No results</ListboxEmpty>