Build Advanced Dropdowns with React Searchable Component

Description:

React Searchable Dropdown is a dropdown component built for React applications that need selection functionality.

It includes built-in virtualization for performance, real-time search filtering, and the ability to create new options dynamically.

Features

  • 🔍 Real-time search filtering with configurable filter types and debounce delay.
  • ⌨️ Full keyboard navigation support for accessibility compliance.
  • 🌐 Portal rendering that prevents overflow issues in complex layouts.
  • 🔄 Smart positioning with automatic flipping and scroll handling.
  • 🎯 Both single-select and multi-select variants available.
  • 📦 Optional grouping functionality for organizing large option sets.
  • 🎨 Extensive styling customization through className props.
  • 🚀 Virtualized list rendering for optimal performance with large datasets.
  • ✨ Dynamic option creation when no matches are found.
  • ♿ Built-in accessibility features including ARIA support.
  • 🎭 Custom icon support for dropdown triggers and actions.
  • 🔒 Disabled state handling for form validation scenarios.

Preview

advanced-dropdown-searchable

Use Cases

  • Admin dashboards that need to handle large user or product selection lists with search functionality.
  • E-commerce platforms requiring category or tag selection with the ability to create new categories on the fly.
  • Content management systems where editors need to select or create tags, categories, or metadata values.
  • Form builders that require dynamic option selection with multi-select capabilities for survey creation.
  • Data visualization tools where users need to filter datasets by multiple criteria or dimensions.

How To Use It

1. Install the package.

npm install @luciodale/react-searchable-dropdown

For Yarn users:

yarn add @luciodale/react-searchable-dropdown

For Bun users:

bun add @luciodale/react-searchable-dropdown

2. Import the required CSS files for styling. The library provides separate stylesheets for single and multi-select variants.

import "@luciodale/react-searchable-dropdown/dist/assets/single-style.css";

3. The library supports two data formats: simple string arrays and object arrays with label-value pairs. For object arrays, you must specify the searchOptionKeys prop to define which fields should be searchable.

Single Select Implementation

import { SearchableDropdown } from '@luciodale/react-searchable-dropdown';
import "@luciodale/react-searchable-dropdown/dist/assets/single-style.css";
const options = [
  { label: 'JavaScript', value: 'js' },
  { label: 'TypeScript', value: 'ts' },
  { label: 'Python', value: 'py' }
];
function LanguageSelector() {
  const [selectedLanguage, setSelectedLanguage] = useState(options[0]);
  return (
    <SearchableDropdown
      options={options}
      value={selectedLanguage}
      setValue={setSelectedLanguage}
      placeholder="Choose a programming language..."
      searchOptionKeys={['label']}
      createNewOptionIfNoMatch={true}
    />
  );
}

Multi Select Implementation

import { SearchableDropdownMulti } from '@luciodale/react-searchable-dropdown';
import "@luciodale/react-searchable-dropdown/dist/assets/multi-style.css";
function SkillSelector() {
  const [selectedSkills, setSelectedSkills] = useState([]);
  return (
    <SearchableDropdownMulti
      options={options}
      values={selectedSkills}
      setValues={setSelectedSkills}
      placeholder="Select your skills..."
      searchOptionKeys={['label']}
      deleteLastChipOnBackspace={true}
    />
  );
}

4. The component offers customization options including filter types, positioning strategies, and styling hooks. You can control search behavior, dropdown positioning, and visual appearance through props.

<SearchableDropdown
  options={complexOptions}
  searchOptionKeys={['label', 'description', 'category']}
  filterType="WORD_STARTS_WITH"
  debounceDelay={300}
  dropdownOptionsHeight={400}
  strategy="fixed"
  offset={10}
  classNameSearchableDropdownContainer="custom-dropdown"
/>
options: T[];
placeholder?: string;
values: T[] | undefined;
setValues: (options: T[]) => void;
searchQuery?: string | undefined;
onSearchQueryChange?: (query: string | undefined) => void;
onClearAll?: () => void;
onClearOption?: (option: T) => void;
debounceDelay?: number;
filterType?: TSearchableDropdownFilterType;
dropdownOptionsHeight?: number;
createNewOptionIfNoMatch?: boolean;
dropdownOptionNoMatchLabel?: string;
dropdownNoOptionsLabel?: string;
disabled?: boolean;
offset?: number;
strategy?: "absolute" | "fixed";
deleteLastChipOnBackspace?: boolean;
classNameMultiSelectedOption?: string;
classNameMultiSelectedOptionClose?: string;
classNameClearAll?: string;
DropdownIcon?: FunctionComponent<{ toggled: boolean }>;
ClearAllIcon?: FunctionComponent;
context?: G;

FAQs

Q: Can I use this component with form libraries like Formik or React Hook Form?
A: Yes, the component works with any form library. You control the state through the value/setValue or values/setValues props, making integration straightforward.

Q: How does the virtualization work with large datasets?
A: The component uses react-virtuoso internally to render only visible options, maintaining smooth performance even with thousands of items. The virtualization is automatic and requires no additional configuration.

Q: Can I customize the search filtering behavior?
A: Yes, you can choose from multiple filter types including case-sensitive matching, starts-with filtering, word matching, and acronym search. You can also set debounce delays and specify which object keys to search.

Q: Does the component support server-side filtering?
A: The component handles client-side filtering by default. For server-side filtering, you can control the search query through the searchQuery and onSearchQueryChange props and update the options based on server responses.

Q: How do I handle option creation when no matches are found?
A: Set createNewOptionIfNoMatch to true, and the component will automatically show an option to create new entries. You can customize the label using the dropdownOptionNoMatchLabel prop.

Add Comment