esc

Type to search...

The problem

Multi-select adds a layer of complexity that single-select doesn't have. You need to show selected items as removable chips, filter already-selected items out of the dropdown, handle chip overflow in tight layouts, and give users a way to clear everything at once. Keyboard behavior changes too: backspace should optionally remove the last chip, not just clear the search text.

SearchableDropdownMulti handles all of this. The API surface mirrors SearchableDropdown with a few additions for chip management.

Basic usage

SkillPicker.tsx
import { useState } from "react";
import { SearchableDropdownMulti } from "@luciodale/react-searchable-dropdown";
import "@luciodale/react-searchable-dropdown/dist/multi-style.css";

const skills = ["TypeScript", "React", "Node.js", "Python", "Go", "Rust"];

function SkillPicker() {
  const [selected, setSelected] = useState<string[] | undefined>(undefined);

  return (
    <SearchableDropdownMulti
      options={skills}
      values={selected}
      setValues={setSelected}
      placeholder="Select skills..."
    />
  );
}

Selected items appear as chips above the search input. The dropdown automatically filters out already-selected options so users don't pick the same thing twice.

Backspace deletion

When deleteLastChipOnBackspace is true, pressing backspace with an empty search input removes the most recently selected chip. This matches the behavior users expect from tag inputs and multi-select fields.

BackspaceExample.tsx
<SearchableDropdownMulti
  options={skills}
  values={selected}
  setValues={setSelected}
  deleteLastChipOnBackspace={true}
  placeholder="Select skills..."
/>

Clear all

When there are selected values, a clear-all button appears. You can hook into this with onClearAll for side effects, or provide a custom ClearAllIcon.

ClearCallbacksExample.tsx
<SearchableDropdownMulti
  options={skills}
  values={selected}
  setValues={setSelected}
  onClearAll={() => console.log("all cleared")}
  onClearOption={(option) => console.log("removed:", option)}
  placeholder="Select skills..."
/>

Object options

Multi-select works identically with object options. The same searchOptionKeys and type inference apply.

ObjectMultiExample.tsx
type Tool = {
  label: string;
  value: string;
  category: string;
};

const tools: Tool[] = [
  { label: "VS Code", value: "vscode", category: "Editor" },
  { label: "Vim", value: "vim", category: "Editor" },
  { label: "Docker", value: "docker", category: "DevOps" },
  { label: "Kubernetes", value: "k8s", category: "DevOps" },
];

function ToolPicker() {
  const [selected, setSelected] = useState<Tool[] | undefined>(undefined);

  return (
    <SearchableDropdownMulti
      options={tools}
      values={selected}
      setValues={setSelected}
      searchOptionKeys={["label", "category"]}
      placeholder="Search tools..."
    />
  );
}

Debouncing

DebounceMultiExample.tsx
<SearchableDropdownMulti
  options={hugeList}
  values={selected}
  setValues={setSelected}
  debounceDelay={100}
  deleteLastChipOnBackspace={true}
  placeholder="Select cities..."
/>

Next steps

  • Grouping — grouped options in multi-select
  • Styling — customize chips and multi-select appearance
  • Live demo — try multi-select with a large dataset