---
title: Combobox
description: A picker with search. Single or multiple, with checkboxes for multiple.
---

```tsx
import { Combobox } from "@openperf/deft";

import { Preview } from "../../src/Preview";

export default function ComboboxBasic() {
  return (
    <Preview overlay={true}>
      <Combobox.Root
        defaultValue="Option 1"
        items={["Option 1", "Option 2", "Option 3", "Option 4"]}
      >
        <Combobox.Trigger>
          <Combobox.Value />
        </Combobox.Trigger>
        <Combobox.Content>
          <Combobox.Search placeholder="Search" />
          <Combobox.Empty>No results</Combobox.Empty>
          <Combobox.List>
            {(option: string) => (
              <Combobox.Item key={option} value={option}>
                {option}
              </Combobox.Item>
            )}
          </Combobox.List>
        </Combobox.Content>
      </Combobox.Root>
    </Preview>
  );
}
```

- Use a combobox when the list is long enough to need search, such as projects. For a short fixed list, use a [Select](/deft/components/select); for actions, a [Menu](/deft/components/menu).
- Search takes focus on open, and `Combobox.Empty` names what was not found.
- A single-select combobox marks the current value with a check.
- The trigger is a button and takes its `variant` and `size`, with a chevron after the label.

## Multiple select

```tsx
import { Button, Combobox } from "@openperf/deft";
import { IconPlus } from "@tabler/icons-react";
import { useState } from "react";

import { Preview } from "../../src/Preview";

interface Option {
  count: number;
  label: string;
}

const OPTIONS: Option[] = [
  { label: "Option 1", count: 120 },
  { label: "Option 2", count: 48 },
  { label: "Option 3", count: 12 },
];

export default function ComboboxMultipleSelect() {
  const [value, setValue] = useState<Option[]>([]);

  return (
    <Preview overlay={true}>
      <Combobox.Root
        items={OPTIONS}
        itemToStringLabel={(option: Option) => option.label}
        multiple={true}
        onValueChange={setValue}
        value={value}
      >
        <Combobox.Trigger>
          {value.length > 0 ? value.map((option) => option.label).join(", ") : "Select options"}
        </Combobox.Trigger>
        <Combobox.Content>
          <Combobox.Search placeholder="Search" />
          <Combobox.Empty>No results</Combobox.Empty>
          <Combobox.List>
            {(option: Option) => (
              <Combobox.Item
                icon={IconPlus}
                indicator="checkbox"
                key={option.label}
                trailing={option.count}
                value={option}
              >
                {option.label}
              </Combobox.Item>
            )}
          </Combobox.List>
          <Combobox.Footer>
            <Button.Root
              onClick={() => {
                setValue([]);
              }}
              size="sm"
              variant="ghost"
            >
              Clear
            </Button.Root>
          </Combobox.Footer>
        </Combobox.Content>
      </Combobox.Root>
    </Preview>
  );
}
```

Set `multiple` on `Root` and `indicator="checkbox"` on each item, and show the selected labels in the trigger. `icon` leads an item and `trailing` adds a value after its label, such as a count that helps people choose. `Combobox.Footer` holds actions for the whole list, such as a reset.

## API

| Prop | Type | Default | Description |
| - | - | - | - |
| `variant?` | `"default" \| "field" \| "primary" \| "ghost" \| "danger"` | `"default"` | On Trigger. |
| `size?` | `"inline" \| "xs" \| "sm" \| "md"` | `"md"` | On Trigger. |
| `align?` | `"start" \| "center" \| "end"` | `"start"` | On Content. |
| `indicator?` | `"check" \| "checkbox"` | `"check"` | On Item. |
| `icon?` | `Icon` | - | On Item. A Tabler icon before the label. |
| `trailing?` | `ReactNode` | - | On Item. After the label. |

Parts: `Root`, `Content`, `Empty`, `Footer`, `GroupLabel`, `Item`, `List`, `Search`, `Trigger`, and the other Base UI parts, such as `Value` and `Group`. `Content` renders the portal, positioner and popup; `Search` renders Base UI's `Input`. Built on Base UI [Combobox](https://base-ui.com/react/components/combobox).
