Skip to content
OpenPerf
Esc
↑↓navigate↵open⌘Jpreview
On this page

Combobox

A picker with search. Single or multiple, with checkboxes for multiple.

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; for actions, a 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

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

PropType
variant?"default" | "field" | "primary" | "ghost" | "danger"

On Trigger.

Type"default" | "field" | "primary" | "ghost" | "danger"
Default"default"
size?"inline" | "xs" | "sm" | "md"

On Trigger.

Type"inline" | "xs" | "sm" | "md"
Default"md"
align?"start" | "center" | "end"

On Content.

Type"start" | "center" | "end"
Default"start"
indicator?"check" | "checkbox"

On Item.

Type"check" | "checkbox"
Default"check"
icon?Icon

On Item. A Tabler icon before the label.

TypeIcon
trailing?ReactNode

On Item. After the label.

TypeReactNode

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.

Was this page helpful?