Combobox
Searchable dropdown with type-ahead filtering.
<arc-combobox> Overview
>
Combobox combines a text input with a filterable dropdown list, giving users the speed of typing with the certainty of selecting from a known set of options. As the user types into the input, the listbox narrows to show only options whose labels match the query string. This makes Combobox ideal for fields where the option set is too large for a plain Select but still needs to be constrained to predefined values — country selectors, tag pickers, and user-mention fields are common examples.
Options are provided declaratively via `<arc-option>` children, each carrying a `value` and a visible `label`. The component reads these from the default slot on connect and rebuilds the filtered list on every keystroke. When the user selects an option — by clicking it or pressing Enter on the highlighted item — the combobox closes, the input displays the chosen label, and an `arc-change` event fires with the selected value.
Keyboard navigation follows the WAI-ARIA combobox pattern: Arrow Down/Up move the active highlight through the filtered list, Enter confirms the selection, and Escape dismisses the popup. The input carries `role="combobox"`, `aria-expanded`, `aria-controls`, and `aria-activedescendant` attributes so screen readers can announce the interaction accurately. Clicking outside the component closes the listbox via a document-level click listener.Guidelines
When to use
- Use Combobox when the option list exceeds 7-10 items and users benefit from filtering by typing
- Provide clear, distinct labels on every <arc-option> so filtering produces meaningful results
- Set a descriptive placeholder like "Search countries..." to indicate the field is searchable
- Include a label attribute for accessibility — it renders a visible label above the input
- Listen to arc-change to capture the selected value and sync it with your application state
When not to use
- Do not use Combobox for short lists (under 5 items) where a simple Select is faster
- Do not omit the value attribute on <arc-option> — the component needs it to track selection
- Do not place non-<arc-option> elements in the default slot; they will be ignored by the filter logic
- Do not rely on Combobox for free-text entry — it only accepts values from the predefined option set
- Do not disable the component without providing a visual explanation of why it is unavailable
Features
- Type-ahead filtering that narrows options as the user types
- Declarative option list via `<arc-option>` children with value and label attributes
- Full keyboard navigation: ArrowDown, ArrowUp, Enter to select, Escape to dismiss
- WAI-ARIA combobox pattern with role, `aria-expanded`, `aria-controls`, and `aria-activedescendant`
- Visual active highlight and selected-state accent color on the current option
- Automatic close on outside click via a document-level event listener
- Configurable label, placeholder, and disabled state
- "No results found" empty state when the query matches zero options
Preview
No results found
Usage
This component requires JavaScript. No pure HTML/CSS version is available — use the Web Component directly or a framework wrapper.
<arc-combobox label="Select Fruit" placeholder="Type to search...">
<arc-option value="apple">Apple</arc-option>
<arc-option value="banana">Banana</arc-option>
<arc-option value="cherry">Cherry</arc-option>
</arc-combobox> import { Combobox, Option } from '@arclux/arc-ui-react';
export default function Example() {
return (
<Combobox label="Select Fruit" placeholder="Type to search...">
<Option value="apple">Apple</Option>
<Option value="banana">Banana</Option>
<Option value="cherry">Cherry</Option>
</Combobox>
);
} <script setup>
import { Combobox, Option } from '@arclux/arc-ui-vue';
</script>
<template>
<Combobox label="Select Fruit" placeholder="Type to search...">
<Option value="apple">Apple</Option>
<Option value="banana">Banana</Option>
<Option value="cherry">Cherry</Option>
</Combobox>
</template> <script>
import { Combobox, Option } from '@arclux/arc-ui-svelte';
</script>
<Combobox label="Select Fruit" placeholder="Type to search...">
<Option value="apple">Apple</Option>
<Option value="banana">Banana</Option>
<Option value="cherry">Cherry</Option>
</Combobox> import { Component } from '@angular/core';
import { Combobox, Option } from '@arclux/arc-ui-angular';
@Component({
imports: [Combobox, Option],
template: `
<arc-combobox label="Select Fruit" placeholder="Type to search...">
<arc-option value="apple">Apple</arc-option>
<arc-option value="banana">Banana</arc-option>
<arc-option value="cherry">Cherry</arc-option>
</arc-combobox>
`,
})
export class MyComponent {} import { Combobox, Option } from '@arclux/arc-ui-solid';
export default function Example() {
return (
<Combobox label="Select Fruit" placeholder="Type to search...">
<Option value="apple">Apple</Option>
<Option value="banana">Banana</Option>
<Option value="cherry">Cherry</Option>
</Combobox>
);
} import { Combobox, Option } from '@arclux/arc-ui-preact';
export default function Example() {
return (
<Combobox label="Select Fruit" placeholder="Type to search...">
<Option value="apple">Apple</Option>
<Option value="banana">Banana</Option>
<Option value="cherry">Cherry</Option>
</Combobox>
);
} API
-
size'sm' | 'md' | 'lg''md' - Control size. `md` is the default; `sm` and `lg` scale the field padding.
-
valuestring'' - The currently selected option value. Reflected as an attribute so it can be read from the DOM. Updated automatically when the user selects an option.
-
placeholderstring'' - Placeholder text shown in the input when no value is entered.
-
labelstring'' - Visible label rendered above the input. Also used as the accessible label for the combobox.
-
namestring'' -
disabledbooleanfalse - Disables the input and prevents interaction. The host element receives reduced opacity and pointer-events: none.
-
readonlybooleanfalse - Prevents typing and selecting an option while the input stays focusable; the list can still be opened for viewing and the value still submits.
-
formAssociatedbooleantrue -
propertiesobject{ required: { type: Boolean, reflect: true }, readonly: { type: Boolean, reflect: true }, } - Lit merges static properties up the prototype chain, so every consumer gets these without declaring them. `required` participates in constraint validation below; `readonly` reflects for styling and is enforced by each component's interaction handlers (the mixin can't know which gestures mutate state).
-
autoValidatesbooleantrue - Components that run their own constraint-validation logic (pattern checks, range checks) opt out of the automatic required sync by overriding this to false, and own the whole validity flag set instead.
-
form -
validity -
validationMessage -
requiredbooleanfalse
Events
-
arc-input - Fired on every keystroke in the filter input. `event.detail.value` contains the current query text.
-
arc-change - Fired when an option is selected. `event.detail.value` contains the selected option value.
See Also
- Select Dropdown select with searchable options, keyboard navigation, and full ARIA listbox semantics for accessible form inputs.
- Multi Select Multi-value select with tag chips, inline search filtering, and keyboard navigation.
- Search Search input with a magnifying glass icon, clear button, loading spinner, and autocomplete suggestions dropdown.
- Command Palette Spotlight-style command palette with search and keyboard shortcuts.