Skip to content

shadcn.io is an independent project built on shadcn/ui

Free

Async/Dynamic Search Combobox for React

A combobox that waits half a second after you type, then shows three results and a spinner while it waits.

The popup starts with Start typing to search. After a pause it shows a spinner and Searching..., then three results built from the text, such as your query followed by Result 1. An empty search says No results found.

Use it for users, products, or anything too large to load up front. A short fixed list can filter locally in a Combobox. In React, Base UI does not filter this list. The results are shown as they come back.

Preview

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.
Use email insteadNo credit card

Anatomy

Combobox anatomy: control, input, trigger, content, item, item indicator

Usage

<Combobox filter={null} items={results} onInputValueChange={setSearch}>
  <ComboboxTrigger
    render={
      <Button className="w-[250px] justify-between" variant="outline" />
    }
  >
    <ComboboxValue placeholder="Search dynamically..." />
  </ComboboxTrigger>
  <ComboboxContent>
    <ComboboxInput placeholder="Type to search..." showTrigger={false} />
    {isSearching ? (
      <div className="flex items-center justify-center gap-2 p-4">
        <Spinner />
        <span className="text-muted-foreground text-sm">Searching...</span>
      </div>
    ) : null}
    {isSearching || search ? null : (
      <p className="p-4 text-center text-muted-foreground text-sm">
        Start typing to search
      </p>
    )}
    {search && !isSearching ? (
      <ComboboxEmpty>No results found.</ComboboxEmpty>
    ) : null}
    {isSearching ? null : (
      <ComboboxList>
        {(result: string) => (
          <ComboboxItem key={result} value={result}>
            {result}
          </ComboboxItem>
        )}
{/* The rest of the file is under Installation. */}

FAQ

How does a search run?

The typed text goes into state, and an effect starts a 500 ms timer whenever it changes. When the timer fires, the results are stored and the spinner goes away. Typing again clears the old timer first, so only the last text is searched.

Why doesn't the combobox filter the results itself?

The server already did. The list shows the results as they come back. filter is null, so the combobox shows items as they are.

Which states can the popup show?

Start typing to search with an empty box, a Spinner and Searching... while waiting, the results when they arrive, and No results found. when a search returns nothing.

How do I call a real API?

Fetch in place of the timer, and ignore responses for a search that's no longer current, for example with an AbortController in the effect's cleanup.

What does the button show?

The picked result, or Search dynamically... before a pick.

Is the input debounced?

Yes, by the timer: a request starts only after typing pauses for 500 ms. Keep a short delay like this so a fast typist doesn't send a request per key.

API Reference

Combobox

Sets filter={null}, items={results}, onInputValueChange={setSearch}, placeholder="Search dynamically...", placeholder="Type to search..." and showTrigger={false}. The rest is on the Combobox page.

Button

Sets variant="outline". The rest is on the Button page.

Spinner

No extra props in this demo. The rest is on the Spinner page.