The choice
Downshift (by Kent C. Dodds and Alex Reardon) is the headless reference for combobox and select in React. It ships nothing but accessibility primitives, keyboard handling, and state. No markup, no styling, no virtualization. Every pixel you see is yours to build, and the library keeps the A11y contract watertight along the way.
react-searchable-dropdown is the opposite axis: a component with opinions. Virtualized rendering, fuzzy search, portal positioning, chips, and grouping are defaults, not exercises. You trade Downshift's flexibility for a faster path from npm install to working dropdown.
Where each one sits
Downshift sits at the "do less" end of the spectrum on purpose.
It's a set of hooks (useSelect,
useCombobox,
useMultipleSelection) that hand you the
state, the event handlers, and the correct ARIA attributes. Every
render decision is yours.
react-searchable-dropdown sits further toward "batteries included." It still gives you styling hooks and type safety, but you don't write the list, the input, the chip row, or the keyboard handler yourself. If you need to ship a combobox today, that matters.
Feature by feature
Feature comparison between react-searchable-dropdown and downshift
| Feature | @luciodale/react-searchable-dropdown Component, batteries included | downshift Headless hooks, bring your own UI |
|---|---|---|
| Ships the markup Input, list, chips rendered for you out of the box. | Supported | Not supported |
| Virtualized option list Handles 100k+ options without jank. | Supported | Not supported |
| Fuzzy search built in Typo tolerant, with highlight. | Supported | Not supported |
| Portal positioning Floating UI integration, handles modals and scroll containers. | Supported | Not supported |
| Multi select chips Removable chips, clear all, backspace to remove last. | Supported | Via useMultipleSelection hook |
| Grouped options | Supported | Build your own |
| ARIA combobox pattern Full keyboard support, focus management, screen reader announcements. | Supported | Supported |
| Headless / full render control Every element rendered by you. | className slots + CSS vars | Supported |
| Styling freedom | Slots + CSS vars | Unlimited (you render it) |
| Production track record | Young | 10+ years, industry reference |
| Bundle size (min+gz, core) | ~15 kB | ~4 kB (no UI) |
| Time to first working combobox | Minutes | Hours (you build the UI) |
- Ships the markup
- Yes
- Virtualized option list
- Yes
- Fuzzy search built in
- Yes
- Portal positioning
- Yes
- Multi select chips
- Yes
- Grouped options
- Yes
- ARIA combobox pattern
- Yes
- Headless / full render control
- className slots + CSS vars
- Styling freedom
- Slots + CSS vars
- Production track record
- Young
- Bundle size (min+gz, core)
- ~15 kB
- Time to first working combobox
- Minutes
- Ships the markup
- No
- Virtualized option list
- No
- Fuzzy search built in
- No
- Portal positioning
- No
- Multi select chips
- Via useMultipleSelection hook
- Grouped options
- Build your own
- ARIA combobox pattern
- Yes
- Headless / full render control
- Yes
- Styling freedom
- Unlimited (you render it)
- Production track record
- 10+ years, industry reference
- Bundle size (min+gz, core)
- ~4 kB (no UI)
- Time to first working combobox
- Hours (you build the UI)
The headless trade off
Downshift is the correct answer when your design system has specific requirements that don't fit any existing component. The library guarantees accessibility, you guarantee everything else. That's powerful, and it's also a commitment: you own rendering, keyboard edge cases, filtering, virtualization, positioning, and every future behavior.
// Downshift: you render every element
const { getToggleButtonProps, getMenuProps, getItemProps, isOpen } = useSelect({
items: options,
});
return (
<div>
<button {...getToggleButtonProps()}>{selectedItem?.label ?? "Pick"}</button>
<ul {...getMenuProps()} hidden={!isOpen}>
{isOpen && options.map((opt, i) => (
<li key={opt.value} {...getItemProps({ item: opt, index: i })}>
{opt.label}
</li>
))}
</ul>
</div>
);react-searchable-dropdown picks sensible defaults and lets you override the pieces you care about via className slots and CSS variables.
<SearchableDropdown
options={cities}
value={city}
setValue={setCity}
placeholder="Pick a city"
/>When to pick Downshift
When to pick react-searchable-dropdown
Next steps
- vs react-select — if you're comparing to the component-heavy camp
- Getting started — install and drop it in
- Styling — className slots and CSS variables