Combobox ​

Combobox root with role="combobox", aria-expanded, and aria-haspopup="listbox". Pair with listbox/option resolve helpers (or your own list UI) for option picking.

PreviewCombobox

Usage ​

tsx
import { useState } from "react";
import { Combobox } from "@sometic/react/selection";

export function Example() {
    const [open, setOpen] = useState(false);
    const [value, setValue] = useState(null);
    return (
        <Combobox open={open} onOpenChange={setOpen} value={value} onValueChange={setValue}>
            {value ?? "Pick a framework"}
        </Combobox>
    );
}
vue
<!-- Vue adapter not shipped for this surface yet. Use React or @sometic/dom (Vanilla). -->
js
import {
    createComboboxController,
    resolveCombobox,
    resolveComboboxList,
    resolveComboboxOption,
} from "@sometic/dom/combobox";

const root = document.querySelector("#combobox");
const list = document.querySelector("#combobox-list");

const controller = createComboboxController({
    defaultOpen: false,
    defaultValue: null,
    onOpenChange: (open) => {
        const view = resolveCombobox({ open });
        for (const [key, value] of Object.entries(view.attributes)) {
            root.setAttribute(key, value);
        }
        list.hidden = !open;
    },
    onValueChange: (value) => {
        root.dataset.value = value ?? "";
        root.textContent = value ?? "Pick a framework";
    },
});

root.addEventListener("click", () => {
    controller.setOpen(!controller.open.get());
});

const listView = resolveComboboxList({ open: true });
for (const [key, value] of Object.entries(listView.attributes)) {
    list.setAttribute(key, value);
}

for (const option of list.querySelectorAll("[data-option]")) {
    const view = resolveComboboxOption({
        value: option.dataset.option,
        selected: false,
    });
    for (const [key, value] of Object.entries(view.attributes)) {
        option.setAttribute(key, value);
    }
    option.addEventListener("click", () => {
        controller.setValue(option.dataset.option);
        controller.setOpen(false);
    });
}
html
<!-- CE not shipped for this surface. Use React, Vue, or @sometic/dom (Vanilla) above. -->
html
<!-- CDN not available for this surface yet (no shipped custom element). Use npm adapters or Vanilla. -->

Custom element not shipped in this beta; use the DOM controller.

Custom element not shipped for Combobox (sometic-select exists for native select, not combobox). Vanilla uses @sometic/dom/combobox. React + DOM are primary; Vue has no Combobox component (Checkbox/Switch/Radio/Select only).

How it works ​

  1. Resolve: resolveCombobox, resolveComboboxList, resolveComboboxOption.
  2. Controller (createComboboxController): controllable value, open, and inputValue for filter UIs.
  3. React root: manages open/value props and emits combobox attributes; compose the list yourself or via DOM helpers. Click on the root toggles open when not disabled.

Anatomy ​

PartRole / notes
Rootrole="combobox", aria-expanded
Listrole="listbox" (compose yourself)
Optionrole="option", aria-selected

Props / attributes ​

React ComboboxProps ​

Extends HTMLAttributes<HTMLDivElement>. Remaining native div attrs are forwarded to the root (including your onClick, which runs before the built-in open toggle).

PropTypeDefaultDescription
openboolean—Controlled open
defaultOpenbooleanfalseUncontrolled open
onOpenChange(open: boolean) => void—Open changes
valuestring | null—Controlled value
defaultValuestring | nullnullUncontrolled value
onValueChange(value: string | null) => void—Value changes
disabledboolean—Disables interaction
childrenReactNode—Trigger / label UI
Native attrsremaining div HTML attrs—Forwarded to the root

React also reflects data-value from the current value when set.

Vue ​

No Vue Combobox component. Use React or @sometic/dom/combobox.

Custom element ​

CE not shipped. Use Vanilla DOM controller or React. For a native <select>, see Select (sometic-select).

Events / callbacks ​

SurfaceEventPayload
ReactonOpenChangeboolean
ReactonValueChangestring | null
Vue——
Custom element——
DOM controlleronOpenChangeboolean
DOM controlleronValueChangestring | null

Controlled vs uncontrolled ​

Open and value are independently controllable. You may control one and leave the other uncontrolled.

Accessibility ​

  • Root uses combobox + expanded state.
  • List should use role="listbox"; options role="option" with aria-selected.
  • For typeahead, drive inputValue from createComboboxController in vanilla/DOM compositions.

Styling ​

Target [role="combobox"], [aria-expanded], [role="listbox"], [role="option"], [data-value].

When to use / When not ​

Use for searchable or custom option picking beyond native <select>.

Do not use when a native Select is enough.

FAQ ​

Full listbox UI in React? The React export is the combobox root. Compose list/options with DOM resolve helpers or your own markup.

Is there an sometic-combobox? No. CE not shipped.

Vue adapter? Not shipped. React + DOM primary.

Does React forward native attrs? Yes, onto the root div.

Click toggles open? Yes, unless disabled.