npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@luciodale/react-searchable-dropdown

v1.0.0

Published

A reusable React searchable dropdown component.

Downloads

293

Readme

React Searchable Dropdown VIEW DEMO

NPM Package

FOR REACT 18 (last supported version) use version: 0.0.48-react-18

A modern, accessible, and customizable dropdown component for React applications.

I created this library because I was tired of piecing together different dropdown components to get the features I needed. You know the drill - one library has virtualization but looks terrible, another looks great but can't handle large lists, and yet another has a nice API but no way to create new options.

What I really wanted was a dropdown that:

  • Handles large lists smoothly (virtualization)
  • Lets users create new options when they don't find what they're looking for
  • Looks good out of the box but is easy to style to match your project
  • Works with both simple string arrays and complex object arrays - no data transformation needed

The good news? I built it! This library combines these essential features in a way that:

  • Works great right away with sensible defaults
  • Needs minimal setup for most cases
  • Styling is a breeze - just add your CSS classes
  • All the good stuff in one package, no more mixing and matching

Features

  • 🔍 Real-time search filtering
  • ⌨️ Keyboard navigation support
  • 🌐 Portal rendering for overflow handling
  • 🔄 Smart positioning handling scrolling and flipping
  • 🎯 Single and multi-select variants
  • 📦 Optionally grouped dropdown options
  • 🎨 Fully customizable styling
  • 🚀 Virtualized list for performance
  • ✨ Create new options on the fly
  • ♿ Accessibility support
  • 🎭 Custom icons support
  • 🔒 Disabled state support

Installation

npm install @luciodale/react-searchable-dropdown
# or
yarn add @luciodale/react-searchable-dropdown
# or
bun add @luciodale/react-searchable-dropdown

Option Types

The components support two types of options:

  1. String Array - Simple array of strings:
const options = ['Option 1', 'Option 2', 'Option 3'];
  1. Object Array - Array of objects with required label and value properties, plus optional metadata:
const options = [
  { 
    label: 'Option 1', 
    value: '1',
    description: 'This is option 1',
    category: 'A',
    // ... any other metadata
  },
  { 
    label: 'Option 2', 
    value: '2',
    description: 'This is option 2',
    category: 'B',
    // ... any other metadata
  }
];

Important: When using object options, you must specify the searchOptionKeys prop to define which fields should be used for filtering. This is a required prop for object options.

<SearchableDropdown
  options={options}
  searchOptionKeys={['label']} // Required for object options
  // ... other props
/>

The searchOptionKeys array tells the component which fields to search through when filtering options. For example, with the above configuration, searching for "A" would match options where solely the label contains "A".

Usage

Single Select

import { SearchableDropdown } from '@luciodale/react-searchable-dropdown';
import "@luciodale/react-searchable-dropdown/dist/assets/single-style.css";


const options = [
  { label: 'Option 1', value: '1' },
  { label: 'Option 2', value: '2' },
  // ...
];

function MyComponent() {
  const [value, setValue] = useState<{label: string, value: string}>(options[0]);

  return (
    <SearchableDropdown
      options={options}
      value={value}
      setValue={setValue}
      placeholder="Select an option..."
      searchOptionKeys={['label']}
    />
  );
}

Multi Select

import { SearchableDropdownMulti } from '@luciodale/react-searchable-dropdown';
import "@luciodale/react-searchable-dropdown/dist/assets/multi-style.css";


const options = [
  { label: 'Option 1', value: '1' },
  { label: 'Option 2', value: '2' },
  // ...
];

function MyComponent() {
  const [values, setValues] = useState([]);

  return (
    <SearchableDropdownMulti
      options={options}
      values={values}
      setValues={setValues}
      placeholder="Select options..."
      searchOptionKeys={['label']}
    />
  );
}

VIEW THE DEMO for more examples.

API

Common Props

Both components share these common props:

| Prop | Type | Default | Description | |------|------|---------|-------------| | options | string[] \| { label: string; value: string; [key: string]: any }[] | Required | Array of options to display (strings or objects with label/value) | | placeholder | string | - | Placeholder text when no value is selected | | disabled | boolean | false | Whether the dropdown is disabled | | debounceDelay | number | 0 | Delay in ms before filtering options | | searchOptionKeys | string[] | Required for object options | Keys to search in object options | | filterType | 'CASE_SENSITIVE_EQUAL' \| 'EQUAL' \| 'STARTS_WITH' \| 'WORD_STARTS_WITH' \| 'CONTAINS' \| 'ACRONYM' \| 'MATCHES' \| 'NO_MATCH' | 'CONTAINS' | Type of search filtering | | dropdownOptionsHeight | number | 300 | Height of the dropdown options container | | createNewOptionIfNoMatch | boolean | true | Whether to allow creating new options | | dropdownOptionNoMatchLabel | string | 'No Match' | Label shown when no matches are found | | offset | number | 5 | Distance in pixels between the trigger and dropdown | | strategy | 'absolute' \| 'fixed' | 'absolute' | Positioning strategy for the dropdown | | DropdownIcon | React.ComponentType<{ toggled: boolean }> | - | Custom dropdown icon component | | searchQuery | string \| undefined | - | Controlled search query value | | onSearchQueryChange | (query: string \| undefined) => void | - | Callback when search query changes | | dropdownNoOptionsLabel | string | - | Label shown when there are no options | | onBlur | () => void | - | Callback when dropdown loses focus | | context | any | - | Context value passed to react-virtuoso for grouped options | | handleGroups | (matchingOptions: TDropdownOption[]) => { groupCounts: number[]; groupCategories: string[] } | - | Function to group options and return counts and categories | | groupContent | (index: number, groupCategories: string[], context: any) => React.ReactNode | - | Function to render group headers |

Single Select Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | value | string \| { label: string; value: string } \| undefined | Required | Currently selected value | | setValue | (value: string \| { label: string; value: string } \| undefined) => void | Required | Callback when value changes |

Multi Select Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | values | (string \| { label: string; value: string })[] \| undefined | Required | Currently selected values | | setValues | (values: (string \| { label: string; value: string })[]) => void | Required | Callback when values change | | ClearAllIcon | React.ComponentType | - | Custom clear all icon component | | onClearAll | () => void | - | Callback when all values are cleared | | onClearOption | (option: string \| { label: string; value: string }) => void | - | Callback when a single option is cleared | | deleteLastChipOnBackspace | boolean | - | Remove last Chip when pressing backspace and the searchQuery is empty

Positioning

The components use Floating UI for positioning and support two key props for customization:

Offset

The offset prop controls the distance in pixels between the trigger element and the dropdown. Default is 5.

<SearchableDropdown
  offset={10} // 10px gap between trigger and dropdown
  // ... other props
/>

Strategy

The strategy prop determines the positioning strategy:

  • 'absolute' (default): Positions relative to the nearest positioned ancestor
  • 'fixed': Positions relative to the viewport, useful for modals or when breaking out of overflow containers
<SearchableDropdown
  strategy="fixed" // Use fixed positioning
  // ... other props
/>

Styling

Both components support extensive styling customization through className props:

<SearchableDropdown
  classNameSearchableDropdownContainer="custom-container"
  classNameSearchQueryInput="custom-input"
  classNameDropdownOptions="custom-options"
  classNameDropdownOption="custom-option"
  classNameDropdownOptionFocused="custom-option-focused"
  classNameDropdownOptionSelected="custom-option-selected"
  classNameDropdownOptionDisabled="custom-option-disabled"
  classNameDropdownOptionLabel="custom-option-label"
  classNameDropdownOptionLabelFocused="custom-option-label-focused"
  classNameDropdownOptionNoMatch="custom-option-no-match"
  classNameTriggerIcon="custom-trigger-icon"
  classNameTriggerIconInvert="custom-trigger-icon-invert"
  classNameDisabled="custom-disabled"
/>

The multi-select variant includes additional class names for chips:

<SearchableDropdownMulti
  // ... common class names ...
  classNameMultiSelectedOption="custom-chip"
  classNameMultiSelectedOptionClose="custom-chip-close"
  classNameClearAll="custom-clear-all"
/>

Contributing

This library is in its early versions but has been battle-tested in production environments. While it's solid and reliable, there's always room for improvement! I'm open to:

  • New feature ideas
  • Performance optimizations
  • Better accessibility
  • More examples and documentation
  • Bug reports and fixes

Feel free to open issues or submit pull requests.

License

MIT