# Combobox (/docs/combobox)





`Combobox` is the low-level, composable building block for searchable selects. It's a thin styled layer over [Ark UI's Combobox](https://ark-ui.com/), exposing the parts so you assemble the control and dropdown yourself. The data-driven [`Autocomplete`](/docs/autocomplete) and [`MultiSelect`](/docs/multi-select) are built on it — reach for `Combobox` directly only when those don't fit.

> Want "just pass `data`"? Use `Autocomplete` / `MultiSelect` / `Select`. `Combobox` is the composition layer underneath.

## Playground [#playground]

<story.Playground />

## Anatomy [#anatomy]

You own the collection and the filtering — Ark's contract. Build a collection with `createListCollection` (re-exported from the module), filter your source list on input change, and render a `Combobox.Item` per option. `size` / `variant` / `color` set once on `Root` flow to the parts.

```tsx
'use client';
import { useMemo, useState } from 'react';
import { Combobox, createListCollection } from '@42-central/ui-react/combobox';

const PROJECTS = ['Libft', 'ft_printf', 'Get Next Line', 'Minishell', 'ft_transcendence'];

export function ProjectPicker() {
  const [items, setItems] = useState(PROJECTS);
  const collection = useMemo(
    () => createListCollection({ items, itemToValue: (i) => i, itemToString: (i) => i }),
    [items],
  );

  return (
    <Combobox.Root
      collection={collection}
      openOnClick
      onInputValueChange={({ inputValue }) => {
        const q = inputValue.toLowerCase().trim();
        setItems(q ? PROJECTS.filter((f) => f.toLowerCase().includes(q)) : PROJECTS);
      }}
    >
      <Combobox.Control>
        <Combobox.Input placeholder="Search projects…" />
        <Combobox.ClearTrigger />
        <Combobox.Trigger />
      </Combobox.Control>

      <Combobox.Content>
        {items.map((item) => (
          <Combobox.Item key={item} item={item}>{item}</Combobox.Item>
        ))}
        <Combobox.Empty>Nothing found</Combobox.Empty>
      </Combobox.Content>
    </Combobox.Root>
  );
}
```

## Parts [#parts]

| Part                    | Wraps (Ark)                           | Notes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| ----------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Combobox.Root`         | `Combobox.Root`                       | Takes the `collection`. Adds `size` / `variant` / `color`; defaults the dropdown to the control's width (`positioning.sameWidth`). Ark's `translations` (`triggerLabel`, `clearTriggerLabel`) default to the kit's English — "Show options" and "Clear value", the same wording as the rest of the combobox family — and a partial override keeps the other key. All Ark root props (`value`, `inputValue`, `multiple`, `onValueChange`, `onInputValueChange`, …) pass through. Accepts `testId`, landing on the root element. |
| `Combobox.Control`      | `Combobox.Control`                    | The input shell (same chrome as [`Input`](/docs/input)). Holds the input + triggers. Accepts `startSlot` / `endSlot` for inline-start / -end adornments, laid out like [`Input`](/docs/input)'s slots. Accepts `testId`, landing on this shell element.                                                                                                                                                                                                                                                                        |
| `Combobox.Input`        | `Combobox.Input`                      | The search `<input>`. Accepts `testId`, landing on this `<input>`.                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `Combobox.Trigger`      | `Combobox.Trigger`                    | Chevron toggle; rotates when open.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `Combobox.ClearTrigger` | `Combobox.ClearTrigger`               | Clears the value; auto-hidden when empty.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `Combobox.Content`      | `Positioner` + `Content`              | The floating panel (positioner + scroll container in one).                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `Combobox.Item`         | `Item` + `ItemText` + `ItemIndicator` | An option. Pass `item={collectionItem}`; renders a check when selected. Accepts `testId`, landing on this option's element.                                                                                                                                                                                                                                                                                                                                                                                                    |
| `Combobox.Group`        | `ItemGroup` + `ItemGroupLabel`        | Pass `label` to head a group of options.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `Combobox.Empty`        | `Empty`                               | Shown when the collection is empty (e.g. no matches).                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `Combobox.Context`      | `Combobox.Context`                    | Render-prop access to the live machine api.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |

`Root`, `Control`, `Input`, and `Item` each take their own `testId` prop for a stable
`data-testid` on their respective rendered element — see the [Testing](/docs/testing) guide.
`Trigger`, `ClearTrigger`, `Group`, and `Empty` deliberately don't get an explicit `testId`: they're
thin Ark re-exports, and Ark's own `data-part` attribute (e.g. `[data-part="trigger"]`,
`[data-part="clear-trigger"]`) already gives a free, stable selector on those parts without any
extra prop.

## Grouped options [#grouped-options]

Wrap options in `Combobox.Group` with a `label`:

```tsx
<Combobox.Content>
  <Combobox.Group label="Common Core">
    <Combobox.Item item="libft">Libft</Combobox.Item>
    <Combobox.Item item="ft_printf">ft_printf</Combobox.Item>
  </Combobox.Group>
  <Combobox.Group label="Outer Core">
    <Combobox.Item item="ft_transcendence">ft_transcendence</Combobox.Item>
    <Combobox.Item item="inception">Inception</Combobox.Item>
  </Combobox.Group>
</Combobox.Content>
```

## Multiple selection [#multiple-selection]

Pass `multiple` to `Combobox.Root` and pair it with a [`PillsInput`](/docs/pills-input) target to show selected values as pills — this is exactly what [`MultiSelect`](/docs/multi-select) assembles for you.

## Field integration [#field-integration]

`Combobox` consumes Ark's `Field` context, so wrapping it in [`Field`](/docs/field) wires the label, description, error, and `aria-*` automatically:

```tsx
<Field label="Project" description="Pick a project">
  <ProjectPicker />
</Field>
```

## Accessibility [#accessibility]

* Full combobox keyboard model from Ark: type to filter, `↑` / `↓` to move, `Enter` to select, `Esc` to close, `Home` / `End` to jump.
* `role="combobox"` / `listbox` / `option` and the `aria-activedescendant` / `aria-expanded` wiring are handled by the Ark machine.
* RTL is honored via the document `dir`. Filtering, custom values, and selection behavior are all Ark-owned — see the [Ark Combobox docs](https://ark-ui.com/) for the full prop surface forwarded through `Combobox.Root`.
