---
title: Combobox
description: "Autocomplete input and command palette with a list of suggestions."
---

```tsx
import {
  Combobox,
  ComboboxContent,
  ComboboxEmpty,
  ComboboxInput,
  ComboboxItem,
  ComboboxList,
} from '@/components/ui/combobox';

const frameworks = ['Next.js', 'SvelteKit', 'Nuxt', 'Remix', 'Astro'];

export default function ComboboxDemo() {
  return (
    <Combobox items={frameworks}>
      <ComboboxInput placeholder="Search framework…" />
      <ComboboxContent>
        <ComboboxEmpty>No framework found.</ComboboxEmpty>
        <ComboboxList>
          {(item: string) => (
            <ComboboxItem key={item} value={item}>
              {item}
            </ComboboxItem>
          )}
        </ComboboxList>
      </ComboboxContent>
    </Combobox>
  );
}
```

## Install

```bash
npx shadcn@latest add @madeui/combobox
```

## Usage

```tsx
import {
  Combobox,
  ComboboxContent,
  ComboboxEmpty,
  ComboboxInput,
  ComboboxItem,
  ComboboxList,
} from '@/components/ui/combobox';
```

## Composition

### Simple

A single-line input and a flat list.

```tsx
<Combobox items={items}>
  <ComboboxInput />
  <ComboboxContent>
    <ComboboxEmpty />
    <ComboboxList>
      {(item) => <ComboboxItem value={item} />}
    </ComboboxList>
  </ComboboxContent>
</Combobox>
```

### With chips

Multi-select with `multiple`, chips, and a chips input. `ComboboxChips` also
serves as the popup anchor — pass a ref to `ComboboxContent`'s `anchor`.

```tsx
<Combobox items={items} multiple value={value} onValueChange={setValue}>
  <ComboboxChips ref={anchorRef}>
    <ComboboxValue>
      {(values) => values.map((value) => <ComboboxChip key={value}>{value}</ComboboxChip>)}
    </ComboboxValue>
    <ComboboxChipsInput />
  </ComboboxChips>
  <ComboboxContent anchor={anchorRef}>
    <ComboboxEmpty />
    <ComboboxList>
      {(item) => <ComboboxItem value={item} />}
    </ComboboxList>
  </ComboboxContent>
</Combobox>
```

## Multiple

Use `multiple` with `ComboboxChips` for multi-select. Selected values render
as removable chips inline with the input.

```tsx
'use client';

import * as React from 'react';

import {
  Combobox,
  ComboboxChip,
  ComboboxChips,
  ComboboxChipsInput,
  ComboboxContent,
  ComboboxEmpty,
  ComboboxItem,
  ComboboxList,
  ComboboxValue,
} from '@/components/ui/combobox';

const frameworks = ['Next.js', 'SvelteKit', 'Nuxt', 'Remix', 'Astro'];

export default function ComboboxMultiple() {
  const [value, setValue] = React.useState<string[]>(['Next.js']);
  const anchorRef = React.useRef<HTMLDivElement>(null);

  return (
    <Combobox items={frameworks} multiple value={value} onValueChange={setValue}>
      <ComboboxChips ref={anchorRef}>
        <ComboboxValue>
          {(items: string[]) =>
            items.map((item) => <ComboboxChip key={item}>{item}</ComboboxChip>)
          }
        </ComboboxValue>
        <ComboboxChipsInput placeholder="Add framework…" />
      </ComboboxChips>
      <ComboboxContent anchor={anchorRef}>
        <ComboboxEmpty>No framework found.</ComboboxEmpty>
        <ComboboxList>
          {(item: string) => (
            <ComboboxItem key={item} value={item}>
              {item}
            </ComboboxItem>
          )}
        </ComboboxList>
      </ComboboxContent>
    </Combobox>
  );
}
```

## Popup

Trigger the combobox from a button-like `ComboboxTrigger` instead of an
always-visible input — move `ComboboxInput` inside `ComboboxContent` with
`showTrigger={false}`.

```tsx
import * as stylex from '@stylexjs/stylex';

import {
  Combobox,
  ComboboxContent,
  ComboboxEmpty,
  ComboboxInput,
  ComboboxItem,
  ComboboxList,
  ComboboxTrigger,
  ComboboxValue,
} from '@/components/ui/combobox';
import { space } from '@/lib/constants.stylex';

const fruits = ['Apple', 'Banana', 'Cherry', 'Mango', 'Peach'];

export default function ComboboxPopup() {
  return (
    <Combobox items={fruits}>
      <ComboboxTrigger>
        <ComboboxValue placeholder="Select a fruit" />
      </ComboboxTrigger>
      <ComboboxContent>
        <ComboboxInput
          showTrigger={false}
          placeholder="Search fruit…"
          style={styles.input}
        />
        <ComboboxEmpty>No fruit found.</ComboboxEmpty>
        <ComboboxList>
          {(item: string) => (
            <ComboboxItem key={item} value={item}>
              {item}
            </ComboboxItem>
          )}
        </ComboboxList>
      </ComboboxContent>
    </Combobox>
  );
}

const styles = stylex.create({
  input: {
    paddingBlock: space.s1,
    paddingInline: space.s1,
    width: '100%',
  },
});
```

## Clear

Use `showClear` on `ComboboxInput` to show a button that clears the value.

```tsx
import {
  Combobox,
  ComboboxContent,
  ComboboxEmpty,
  ComboboxInput,
  ComboboxItem,
  ComboboxList,
} from '@/components/ui/combobox';

const frameworks = ['Next.js', 'SvelteKit', 'Nuxt', 'Remix', 'Astro'];

export default function ComboboxClear() {
  return (
    <Combobox items={frameworks} defaultValue="Next.js">
      <ComboboxInput showClear placeholder="Search framework…" />
      <ComboboxContent>
        <ComboboxEmpty>No framework found.</ComboboxEmpty>
        <ComboboxList>
          {(item: string) => (
            <ComboboxItem key={item} value={item}>
              {item}
            </ComboboxItem>
          )}
        </ComboboxList>
      </ComboboxContent>
    </Combobox>
  );
}
```

## Groups

Use `ComboboxGroup`, `ComboboxLabel`, `ComboboxCollection`, and
`ComboboxSeparator` to group related items.

```tsx
import * as React from 'react';

import {
  Combobox,
  ComboboxCollection,
  ComboboxContent,
  ComboboxEmpty,
  ComboboxGroup,
  ComboboxInput,
  ComboboxItem,
  ComboboxLabel,
  ComboboxList,
  ComboboxSeparator,
} from '@/components/ui/combobox';

const groups = [
  { label: 'Fruits', items: ['Apple', 'Banana', 'Cherry'] },
  { label: 'Vegetables', items: ['Carrot', 'Potato', 'Spinach'] },
];

export default function ComboboxGroups() {
  return (
    <Combobox items={groups}>
      <ComboboxInput placeholder="Search produce…" />
      <ComboboxContent>
        <ComboboxEmpty>No produce found.</ComboboxEmpty>
        <ComboboxList>
          {groups.map((group, index) => (
            <React.Fragment key={group.label}>
              {index > 0 && <ComboboxSeparator />}
              <ComboboxGroup items={group.items}>
                <ComboboxLabel>{group.label}</ComboboxLabel>
                <ComboboxCollection>
                  {(item: string) => (
                    <ComboboxItem key={item} value={item}>
                      {item}
                    </ComboboxItem>
                  )}
                </ComboboxCollection>
              </ComboboxGroup>
            </React.Fragment>
          ))}
        </ComboboxList>
      </ComboboxContent>
    </Combobox>
  );
}
```

## Custom items

Use `itemToStringValue` when items are objects, and render any content
inside `ComboboxItem`.

```tsx
import * as stylex from '@stylexjs/stylex';

import {
  Combobox,
  ComboboxContent,
  ComboboxEmpty,
  ComboboxInput,
  ComboboxItem,
  ComboboxList,
} from '@/components/ui/combobox';
import { fontSize } from '@/lib/constants.stylex';
import { colors } from '@/lib/tokens.stylex';

interface Framework {
  label: string;
  value: string;
  description: string;
}

const frameworks: Framework[] = [
  {
    label: 'Next.js',
    value: 'next',
    description: 'The React framework for the web',
  },
  {
    label: 'SvelteKit',
    value: 'sveltekit',
    description: 'Web development, streamlined',
  },
  {
    label: 'Nuxt',
    value: 'nuxt',
    description: 'The intuitive Vue framework',
  },
];

export default function ComboboxCustomItems() {
  return (
    <Combobox
      items={frameworks}
      itemToStringValue={(framework: Framework) => framework.label}
    >
      <ComboboxInput placeholder="Search framework…" />
      <ComboboxContent>
        <ComboboxEmpty>No framework found.</ComboboxEmpty>
        <ComboboxList>
          {(framework: Framework) => (
            <ComboboxItem key={framework.value} value={framework}>
              <div {...stylex.props(styles.row)}>
                <span {...stylex.props(styles.title)}>{framework.label}</span>
                <span {...stylex.props(styles.description)}>
                  {framework.description}
                </span>
              </div>
            </ComboboxItem>
          )}
        </ComboboxList>
      </ComboboxContent>
    </Combobox>
  );
}

const styles = stylex.create({
  row: {
    display: 'flex',
    flexDirection: 'column',
  },
  title: {
    fontSize: fontSize.sm,
  },
  description: {
    color: colors.mutedForeground,
    fontSize: fontSize.xs,
  },
});
```

## Disabled

```tsx
import {
  Combobox,
  ComboboxContent,
  ComboboxEmpty,
  ComboboxInput,
  ComboboxItem,
  ComboboxList,
} from '@/components/ui/combobox';

const frameworks = ['Next.js', 'SvelteKit', 'Nuxt', 'Remix', 'Astro'];

export default function ComboboxDisabled() {
  return (
    <Combobox items={frameworks} disabled>
      <ComboboxInput placeholder="Search framework…" />
      <ComboboxContent>
        <ComboboxEmpty>No framework found.</ComboboxEmpty>
        <ComboboxList>
          {(item: string) => (
            <ComboboxItem key={item} value={item}>
              {item}
            </ComboboxItem>
          )}
        </ComboboxList>
      </ComboboxContent>
    </Combobox>
  );
}
```

## Auto highlight

Use `autoHighlight` to highlight the first matching item automatically while
filtering.

```tsx
import {
  Combobox,
  ComboboxContent,
  ComboboxEmpty,
  ComboboxInput,
  ComboboxItem,
  ComboboxList,
} from '@/components/ui/combobox';

const frameworks = ['Next.js', 'SvelteKit', 'Nuxt', 'Remix', 'Astro'];

export default function ComboboxAutoHighlight() {
  return (
    <Combobox items={frameworks} autoHighlight>
      <ComboboxInput placeholder="Search framework…" />
      <ComboboxContent>
        <ComboboxEmpty>No framework found.</ComboboxEmpty>
        <ComboboxList>
          {(item: string) => (
            <ComboboxItem key={item} value={item}>
              {item}
            </ComboboxItem>
          )}
        </ComboboxList>
      </ComboboxContent>
    </Combobox>
  );
}
```

## API reference

Built on [Base UI Combobox](https://base-ui.com/react/components/combobox). Pass `items` to the root and it filters as you type out of the box; `ComboboxList` accepts a render function over the filtered items. All other props are forwarded to the underlying Base UI parts (`multiple`, `value`, `onValueChange`, `itemToStringValue`, `autoHighlight`, custom `filter`, …); see the [Base UI Combobox API reference](https://base-ui.com/react/components/combobox#api-reference).

### ComboboxInput

Text input with a built-in dropdown trigger button.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `showTrigger` | `boolean` | `true` | Render the built-in dropdown trigger button. Set `false` when the input lives inside `ComboboxContent` and a `ComboboxTrigger` elsewhere anchors the popup. |
| `showClear` | `boolean` | `false` | Render a clear button (`Base UI Clear`) before the trigger. |
| `style` | `StyleXStyles` | — | StyleX styles merged last — always win over the component's own styles, applied to the wrapper. |

### ComboboxContent

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `side` | `'top' \| 'right' \| 'bottom' \| 'left'` | `'bottom'` |  |
| `sideOffset` | `number` | `6` |  |
| `align` | `'start' \| 'center' \| 'end'` | `'start'` |  |
| `alignOffset` | `number` | `0` |  |
| `anchor` | `Element \| RefObject<Element \| null> \| (() => Element)` | — | Positions the popup against an element other than the input/trigger, e.g. `ComboboxChips`. |
| `style` | `StyleXStyles` | — | StyleX styles merged last — always win over the component's own styles. |

### Styling

`ComboboxTrigger` (select-like popup trigger button), `ComboboxChips` (chips container, also usable as a popup anchor), `ComboboxChip` (pill with a built-in remove button), and `ComboboxChipsInput` (borderless input for inline use inside `ComboboxChips`) all accept `style` (`StyleXStyles`, merged last so caller overrides always win) plus all native props of the element they render.

`ComboboxGroup`, `ComboboxLabel`, `ComboboxValue`, and `ComboboxCollection` are also exported for grouped and multi-part lists.
