Skip to content

components combobox

GitHub Actions edited this page Sep 18, 2026 · 2 revisions

components/combobox

Import: import { ComboboxList, Combobox } from "@tundralibs/ui/combobox"

Rendered in every variant on the catalogue (deno task build:demos, then demo/index.html). Guides: Getting started · rAPId integration · Theming.

Functions

ComboboxList

ComboboxList(props: ComboboxListProps): Html

The listbox alone — what a route returns for a swap of #<id>-list (§3: every swap target needs a self-contained partial).

Combobox

Combobox(props: ComboboxProps): Html

Types

ComboboxOption

Prop Type Required Description
value string yes
label string yes
group string
meta string
disabled boolean Rendered and announced, but not pickable.
lead Html Rendered before the label — an avatar or badge.

ComboboxProps

Prop Type Required Description
id string yes Required: the listbox is a swap target and needs a stable id.
name string yes
label string
placeholder string
query string Current text in the input (what the server matched against).
options ComboboxOption[] yes
selected `string string[]`
open boolean
multi boolean
action string URL that returns a fresh ComboboxList(...) fragment for ?q=<text>. combobox.js debounces input and calls window.rapid.swap() on it; without it (or without rAPId's runtime) the rendered options are filtered client-side instead.
emptyText string
hint string

ComboboxListProps

type ComboboxListProps = Pick

Usage

Each example as the rAPId call and the HTML it renders — the markup a plain page writes by hand. Icons are inline SVG in the real output; they are shortened to <svg …>…</svg> here.

Pick a reviewer, filtered by the server

Each keystroke fetches action?q=… and swaps the reply into #reviewer-list; without action the rendered options are filtered on the client.

Combobox({
  id: "reviewer",
  name: "reviewer",
  label: "Reviewer",
  placeholder: "Type a name…",
  action: "/fragments/reviewers",
  options: [{ value: "ada", label: "Ada Lovelace", meta: "Finance" }, {
    value: "grace",
    label: "Grace Hopper",
    meta: "Ops",
  }],
})
<div class="combobox" data-combobox>
  <label class="form-field__label" for="reviewer">Reviewer</label>
  <div class="combobox__anchor">
    <div class="combobox__field">
      <input type="hidden" name="reviewer" value="" data-combobox-value>
      <input class="combobox__input" id="reviewer" type="text" role="combobox" autocomplete="off" value="" placeholder="Type a name…" aria-expanded="false" aria-controls="reviewer-list" aria-autocomplete="list" data-combobox-action="/fragments/reviewers" data-combobox-target="#reviewer-list">
      <span class="combobox__caret">
        <svg width="15" height="15" width="2" ></svg>
      </span>
    </div>
    <div class="combobox__list" id="reviewer-list" role="listbox" hidden>
      <div class="combobox__option" role="option" id="reviewer-opt-0" aria-selected="false" data-value="ada">
        <span class="combobox__option-label">Ada Lovelace</span>
        <span class="combobox__option-meta">Finance</span>
      </div>
      <div class="combobox__option" role="option" id="reviewer-opt-1" aria-selected="false" data-value="grace">
        <span class="combobox__option-label">Grace Hopper</span>
        <span class="combobox__option-meta">Ops</span>
      </div>
      <div class="combobox__hints">
        <span>&uarr;&darr; navigate</span>
        <span>&crarr; select</span>
        <span class="combobox__count">2 matches</span>
      </div>
    </div>
  </div>
</div>

The fragment the route returns

ComboboxList({
  id: "reviewer",
  query: "gr",
  options: [{ value: "grace", label: "Grace Hopper", meta: "Ops" }],
})
<div class="combobox__option" role="option" id="reviewer-opt-0" aria-selected="false" data-value="grace">
  <span class="combobox__option-label">
    <span class="combobox__match">Gr</span>
    ace Hopper
  </span>
  <span class="combobox__option-meta">Ops</span>
</div>
<div class="combobox__hints">
  <span>&uarr;&darr; navigate</span>
  <span>&crarr; select</span>
  <span class="combobox__count">1 match</span>
</div>

CSS hooks

Classes defined by components/combobox/combobox.css — structural, token-driven; override from an unlayered stylesheet (see Theming):

.combobox, .combobox--multi, .combobox--open, .combobox__anchor, .combobox__caret, .combobox__check, .combobox__count, .combobox__empty, .combobox__field, .combobox__group, .combobox__hints, .combobox__input, .combobox__list, .combobox__match, .combobox__option, .combobox__option-label, .combobox__option-meta, .combobox__token, .combobox__token-remove, .form-field__help

Behaviour

components/combobox/combobox.js ships in ui.js (delegated on document, re-initialised after a rAPId swap).

Attributes it reads or writes: data-active, data-combobox, data-combobox-action, data-combobox-name, data-combobox-remove, data-combobox-target, data-combobox-value, data-value.

Events: combobox:pick.

Clone this wiki locally