---
outline: deep
---

# Combobox

A text input paired with a filterable list of options — type to narrow the list, then pick a match.

**`<l-combobox>`** — Custom Element · Shadow DOM

```html
<l-combobox
  label="Country"
  name="country"
  placeholder="Search a country…"
>
  <datalist>
    <option value="us">United States</option>
    <option value="fr">France</option>
    <option value="de">Germany</option>
  </datalist>
</l-combobox>
```

Options are authored as a native `<datalist>` of `<option>` — the same authoring surface as [`<select>`](/elements/select).

## Options

### Basic

Author the choices as `<option>` inside a `<datalist>`. `label` names the input; `name` submits the chosen `value`.

```html
<div class="w-72">
  <l-combobox
    label="Country"
    name="country"
    placeholder="Search a country…"
  >
    <datalist>
      <option value="us">United States</option>
      <option value="fr">France</option>
      <option value="de">Germany</option>
      <option value="es">Spain</option>
      <option value="it">Italy</option>
      <option value="jp">Japan</option>
    </datalist>
  </l-combobox>
</div>
```

### Clearable

Add `with-clear` for a button that resets the value.

```html
<div class="w-72">
  <l-combobox
    label="Country"
    value="fr"
    with-clear
  >
    <datalist>
      <option value="us">United States</option>
      <option value="fr">France</option>
      <option value="de">Germany</option>
      <option value="es">Spain</option>
    </datalist>
  </l-combobox>
</div>
```

### Custom values

Add `allow-custom` to accept a typed value that matches no option.

```html
<div class="w-72">
  <l-combobox
    label="Tag"
    placeholder="Pick or type a tag…"
    allow-custom
  >
    <datalist>
      <option value="bug">Bug</option>
      <option value="feature">Feature</option>
      <option value="docs">Documentation</option>
    </datalist>
  </l-combobox>
</div>
```

### Rich options

Put markup inside each `<option>` — the same `.l-select-item-media` / `.l-select-item-text` / `.l-select-item-title` / `.l-select-item-description` classes as [`<select>`](/elements/select). Set a `label` (or `.l-select-item-title`) so filtering and the input display use the title.

```html
<div class="w-72">
  <l-combobox
    label="Country"
    placeholder="Search a country…"
  >
    <datalist>
      <option
        value="us"
        label="United States"
      >
        <span class="l-select-item-media"><l-icon name="circle-flags:us"></l-icon></span>
        <span class="l-select-item-text">
          <span class="l-select-item-title">United States</span>
          <span class="l-select-item-description">North America</span>
        </span>
      </option>
      <option
        value="fr"
        label="France"
      >
        <span class="l-select-item-media"><l-icon name="circle-flags:fr"></l-icon></span>
        <span class="l-select-item-text">
          <span class="l-select-item-title">France</span>
          <span class="l-select-item-description">Europe</span>
        </span>
      </option>
      <option
        value="jp"
        label="Japan"
      >
        <span class="l-select-item-media"><l-icon name="circle-flags:jp"></l-icon></span>
        <span class="l-select-item-text">
          <span class="l-select-item-title">Japan</span>
          <span class="l-select-item-description">Asia</span>
        </span>
      </option>
    </datalist>
  </l-combobox>
</div>
```

### Disabled

Native `disabled` attribute.

```html
<div class="w-72">
  <l-combobox
    label="Country"
    value="fr"
    disabled
  >
    <datalist>
      <option value="fr">France</option>
      <option value="de">Germany</option>
    </datalist>
  </l-combobox>
</div>
```

### Custom filter

By default options are matched case- and accent-insensitively (every space-separated keyword must appear). Override the `filter` property — `(item, query) => boolean` — for `startsWith`, fuzzy, or remote-driven filtering.

## Accessibility

### Criteria

- **Role** — The input is a `role="combobox"` with `aria-expanded` / `aria-controls` / `aria-activedescendant`; options are `role="option"` in a `role="listbox"`
- **Accessible name** — Set `label` (or wrap with `<l-form-field>`)
- **Focus** — Focus stays on the input; the active option is tracked via `aria-activedescendant`

### Rules

- Always set `label` so the input has an accessible name

### Keyboard interactions

- `Down / Up` — Opens the list, then moves the active option
- `Home / End` — Jumps to the first / last option
- `Enter` — Selects the active option
- `Escape` — Closes the list, or clears the value when already closed
- `Tab` — Selects the active option (if any) and moves focus on

## API reference

### Importing

```js
import 'luxen-ui/combobox';
```

### Attributes & Properties

- **value**: `string` — Selected value (the chosen option's `value`).
- **placeholder**: `string` — Placeholder text in the input.
- **label**: `string` — Accessible label for the input.
- **size**: `ComboboxSize` (default: `'md'`) — Control size.
- **with-clear**: `boolean` (default: `false`) — Show a button to clear the value.
- **allow-custom**: `boolean` (default: `false`) — Accept a typed value that matches no option.
- **highlight**: `boolean` (default: `true`) — Wrap the matching substring of each option in `<mark>`.
- **placement**: `Placement` (default: `'bottom-start'`) — Panel placement relative to the control.
- **filter**: `ComboboxFilter` (default: `defaultFilter`) — Override the option filter. `(item, query) => boolean`.

### Events

- **change** — Fired when an option is selected. Bubbles. Not cancelable. Properties: `value: string`.
- **input** — Fired as the user types. Bubbles. Not cancelable. Properties: `value: string` (the query).
- **show** (cancelable) — Fired before the list opens. Cancelable.
- **hide** (cancelable) — Fired before the list closes. Cancelable.

### CSS parts

- `base` — The host wrapper.
- `control` — The input control row (input + clear + chevron).
- `input` — The text input.
- `panel` — The floating popover panel.
- `listbox` — The options container.
- `option` — Each option row.
- `empty` — The "no results" message.

### CSS custom properties

- `--height` — Control height. Defaults to the form-control height.
- `--border-radius` — Control + panel radius.
- `--background` — Panel background.
