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 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-search-select-dropdown

v1.5.0

Published

A customizable React autocomplete/search select dropdown component with TypeScript support

Readme

React Search Select Dropdown

A highly customizable React autocomplete/search select dropdown component with TypeScript support and inline styles.

Features

  • 🔍 Search functionality - Filter options as you type
  • ⌨️ Keyboard navigation - Navigate with arrow keys, select with Enter
  • 🎨 Fully customizable styling - Override default inline styles with customStyles prop
  • 🎭 Custom input support - Use any UI library (Material-UI, Ant Design, etc.) via renderInput prop
  • 🔤 TypeScript support - Full type definitions included
  • 🎯 Generic types - Support for any value type (string, number, objects)
  • 🌐 i18n ready - Customizable text for localization
  • 📱 Responsive design - Works on all screen sizes
  • Accessible - ARIA labels and keyboard support
  • 💅 Inline styles - No CSS conflicts, minimal external CSS (only scrollbar)

Installation

npm install react-search-select-dropdown

or

yarn add react-search-select-dropdown

or

pnpm add react-search-select-dropdown

Quick Start

import { Autocomplete } from "react-search-select-dropdown";
import type { AutocompleteOption } from "react-search-select-dropdown";
import "react-search-select-dropdown/styles.css";

const options: AutocompleteOption[] = [
  { value: "us", label: "United States" },
  { value: "ca", label: "Canada" },
  { value: "mx", label: "Mexico" },
];

function App() {
  return (
    <Autocomplete
      options={options}
      placeholder="Search country..."
      onSelect={(option) => console.log("Selected:", option)}
    />
  );
}

Usage Examples

Example 1: String Values (Default)

import { useState } from "react";
import { Autocomplete } from "react-search-select-dropdown";
import type { AutocompleteOption } from "react-search-select-dropdown";
import "react-search-select-dropdown/styles.css";

const countryOptions: AutocompleteOption[] = [
  { value: "us", label: "United States" },
  { value: "ca", label: "Canada" },
  { value: "mx", label: "Mexico" },
  { value: "gb", label: "United Kingdom" },
  { value: "fr", label: "France" },
  { value: "de", label: "Germany" },
  { value: "it", label: "Italy" },
  { value: "es", label: "Spain" },
];

function App() {
  const [selectedCountry, setSelectedCountry] =
    useState<AutocompleteOption | null>(null);

  return (
    <div>
      <Autocomplete
        options={countryOptions}
        placeholder="Search country..."
        onSelect={(option) => {
          setSelectedCountry(option);
          console.log("Selected country:", option);
        }}
        customStyles={{
          input: {
            borderColor: "gray",
          },
          dropdown: {
            maxHeight: "300px",
          },
          option: {
            padding: "8px 16px",
            fontSize: "16px",
          },
        }}
      />
      {selectedCountry && (
        <div
          style={{
            marginTop: "12px",
            padding: "12px",
            backgroundColor: "#f0fdf4",
            border: "1px solid #86efac",
            borderRadius: "6px",
            color: "#166534",
            fontSize: "14px",
            lineHeight: "1.6",
          }}
        >
          <strong>Selected:</strong> {selectedCountry.label} (code: {selectedCountry.value})
        </div>
      )}
    </div>
  );
}

Example 2: Number Values

import { useState } from "react";
import { Autocomplete } from "react-search-select-dropdown";
import type { AutocompleteOption } from "react-search-select-dropdown";
import "react-search-select-dropdown/styles.css";

const numberOptions: AutocompleteOption<number>[] = [
  { value: 1, label: "Option One" },
  { value: 2, label: "Option Two" },
  { value: 3, label: "Option Three" },
  { value: 4, label: "Option Four" },
  { value: 5, label: "Option Five" },
];

function App() {
  const [selectedNumber, setSelectedNumber] =
    useState<AutocompleteOption<number> | null>(null);

  return (
    <div>
      <Autocomplete
        options={numberOptions}
        placeholder="Search option..."
        onSelect={(option) => {
          setSelectedNumber(option);
          console.log("Selected number:", option);
        }}
        customStyles={{
          input: {
            borderColor: "gray",
          },
          dropdown: {
            maxHeight: "300px",
          },
          option: {
            padding: "8px 16px",
            fontSize: "16px",
          },
        }}
      />
      {selectedNumber && (
        <div
          style={{
            marginTop: "12px",
            padding: "12px",
            backgroundColor: "#f0fdf4",
            border: "1px solid #86efac",
            borderRadius: "6px",
            color: "#166534",
            fontSize: "14px",
            lineHeight: "1.6",
          }}
        >
          <strong>Selected:</strong> {selectedNumber.label} (ID: {selectedNumber.value})
        </div>
      )}
    </div>
  );
}

Example 3: Custom Object Values

import { useState } from "react";
import { Autocomplete } from "react-search-select-dropdown";
import type { AutocompleteOption } from "react-search-select-dropdown";
import "react-search-select-dropdown/styles.css";

interface User {
  id: number;
  email: string;
  role: string;
}

const userOptions: AutocompleteOption<User>[] = [
  {
    value: { id: 1, email: "[email protected]", role: "admin" },
    label: "John Doe (Admin)",
  },
  {
    value: { id: 2, email: "[email protected]", role: "user" },
    label: "Jane Smith (User)",
  },
  {
    value: { id: 3, email: "[email protected]", role: "moderator" },
    label: "Bob Johnson (Moderator)",
  },
  {
    value: { id: 4, email: "[email protected]", role: "user" },
    label: "Alice Williams (User)",
  },
];

function App() {
  const [selectedUser, setSelectedUser] =
    useState<AutocompleteOption<User> | null>(null);

  return (
    <div>
      <Autocomplete
        options={userOptions}
        placeholder="Search user..."
        getOptionKey={(option) => option.value.id}
        onSelect={(option) => {
          setSelectedUser(option);
          console.log("Selected user:", option);
        }}
        customStyles={{
          input: {
            borderColor: "gray",
          },
          dropdown: {
            maxHeight: "300px",
          },
          option: {
            padding: "8px 16px",
            fontSize: "16px",
          },
        }}
      />
      {selectedUser && (
        <div
          style={{
            marginTop: "12px",
            padding: "12px",
            backgroundColor: "#f0fdf4",
            border: "1px solid #86efac",
            borderRadius: "6px",
            color: "#166534",
            fontSize: "14px",
            lineHeight: "1.6",
          }}
        >
          <strong>Selected User:</strong>
          <br />
          Name: {selectedUser.label}
          <br />
          ID: {selectedUser.value.id}
          <br />
          Email: {selectedUser.value.email}
          <br />
          Role: {selectedUser.value.role}
        </div>
      )}
    </div>
  );
}

Customization

Custom Styles

The component uses inline styles by default, which you can fully customize using the customStyles prop:

import {
  Autocomplete,
  type AutocompleteStyles,
} from "react-search-select-dropdown";
import type { AutocompleteOption } from "react-search-select-dropdown";
import "react-search-select-dropdown/styles.css";

const customStyles: AutocompleteStyles = {
  input: {
    borderColor: "#10b981",
    fontSize: "16px",
  },
  inputFocus: {
    borderColor: "#059669",
    boxShadow: "0 0 0 3px rgba(16, 185, 129, 0.1)",
  },
  dropdown: {
    borderColor: "#10b981",
    boxShadow: "0 10px 25px rgba(0, 0, 0, 0.15)",
  },
  option: {
    padding: "12px 16px",
    fontSize: "15px",
  },
  optionHighlighted: {
    backgroundColor: "#d1fae5",
  },
  optionSelected: {
    backgroundColor: "#10b981",
    color: "white",
  },
};

function App() {
  return (
    <Autocomplete
      options={options}
      placeholder="Search..."
      customStyles={customStyles}
    />
  );
}

Available Style Properties

  • wrapper - Main container
  • inputWrapper - Input container
  • input - Input field base styles
  • inputFocus - Input field when focused
  • inputDisabled - Input field when disabled
  • clearButton - Clear button base styles
  • clearButtonHover - Clear button on hover
  • arrow - Dropdown arrow base styles
  • arrowOpen - Dropdown arrow when open
  • dropdown - Dropdown list container
  • option - Individual option base styles
  • optionHighlighted - Option when highlighted
  • optionSelected - Option when selected
  • optionHighlightedSelected - Option when both highlighted and selected
  • noOptions - No results message

Custom No Results Text

<Autocomplete options={options} noResultsText="No se encontraron resultados" />

Custom Input with renderInput

You can pass a completely custom input component using the renderInput prop. This is useful for custom styling or integrating with UI libraries:

import { Autocomplete, type AutocompleteInputProps } from "react-search-select-dropdown";
import type { AutocompleteOption } from "react-search-select-dropdown";
import "react-search-select-dropdown/styles.css";

const countryOptions: AutocompleteOption[] = [
  { value: "us", label: "United States" },
  { value: "ca", label: "Canada" },
  { value: "mx", label: "Mexico" },
];

function App() {
  return (
    <Autocomplete
      options={countryOptions}
      placeholder="Custom styled input..."
      onSelect={(option) => {
        console.log("Custom input selected:", option);
      }}
      renderInput={(props: AutocompleteInputProps) => (
        <input
          ref={props.ref}
          type={props.type}
          value={props.value}
          onChange={props.onChange}
          onFocus={props.onFocus}
          onBlur={props.onBlur}
          onKeyDown={props.onKeyDown}
          placeholder={props.placeholder}
          disabled={props.disabled}
          autoComplete={props.autoComplete}
          style={{
            ...props.style,
            borderWidth: "2px",
            borderStyle: "solid",
            borderColor: "#10b981",
            borderRadius: "8px",
            fontSize: "16px",
            fontWeight: "bold",
            padding: "12px 60px 12px 16px",
            backgroundColor: "#f0fdf4",
          }}
        />
      )}
      customStyles={{
        dropdown: {
          maxHeight: "300px",
          borderColor: "#10b981",
        },
        option: {
          padding: "12px 16px",
          fontSize: "16px",
        },
        optionHighlighted: {
          backgroundColor: "#d1fae5",
        },
        optionSelected: {
          backgroundColor: "#10b981",
          color: "white",
        },
      }}
    />
  );
}

Custom Input with Material-UI

You can use any UI library component as the input by using the renderInput prop:

import { useState } from "react";
import { Autocomplete, AutocompleteInputProps } from "react-search-select-dropdown";
import type { AutocompleteOption } from "react-search-select-dropdown";
import TextField from "@mui/material/TextField";
import "react-search-select-dropdown/styles.css";

const options: AutocompleteOption[] = [
  { value: "us", label: "United States" },
  { value: "ca", label: "Canada" },
  { value: "mx", label: "Mexico" },
];

function App() {
  const [selected, setSelected] = useState<AutocompleteOption | null>(null);

  return (
    <Autocomplete
      options={options}
      placeholder="Search country..."
      onSelect={setSelected}
      renderInput={(props: AutocompleteInputProps) => (
        <TextField
          inputRef={props.ref}
          type={props.type}
          value={props.value}
          onChange={props.onChange}
          onFocus={props.onFocus}
          onBlur={props.onBlur}
          onKeyDown={props.onKeyDown}
          placeholder={props.placeholder}
          disabled={props.disabled}
          autoComplete={props.autoComplete}
          variant="outlined"
          fullWidth
          label="Country"
          size="small"
        />
      )}
      customStyles={{
        inputWrapper: {
          position: "relative",
        },
        dropdown: {
          maxHeight: "300px",
        },
      }}
    />
  );
}

Complete Example with Multiple Instances

import { useState } from "react";
import { Autocomplete, AutocompleteInputProps } from "react-search-select-dropdown";
import type { AutocompleteOption } from "react-search-select-dropdown";
import "react-search-select-dropdown/styles.css";

interface User {
  id: number;
  email: string;
  role: string;
}

const countryOptions: AutocompleteOption[] = [
  { value: "us", label: "United States" },
  { value: "ca", label: "Canada" },
  { value: "mx", label: "Mexico" },
  { value: "gb", label: "United Kingdom" },
  { value: "fr", label: "France" },
  { value: "de", label: "Germany" },
  { value: "it", label: "Italy" },
  { value: "es", label: "Spain" },
];

const numberOptions: AutocompleteOption<number>[] = [
  { value: 1, label: "Option One" },
  { value: 2, label: "Option Two" },
  { value: 3, label: "Option Three" },
  { value: 4, label: "Option Four" },
  { value: 5, label: "Option Five" },
];

const userOptions: AutocompleteOption<User>[] = [
  {
    value: { id: 1, email: "[email protected]", role: "admin" },
    label: "John Doe (Admin)",
  },
  {
    value: { id: 2, email: "[email protected]", role: "user" },
    label: "Jane Smith (User)",
  },
  {
    value: { id: 3, email: "[email protected]", role: "moderator" },
    label: "Bob Johnson (Moderator)",
  },
  {
    value: { id: 4, email: "[email protected]", role: "user" },
    label: "Alice Williams (User)",
  },
];

function App() {
  const [selectedCountry, setSelectedCountry] =
    useState<AutocompleteOption | null>(null);
  const [selectedNumber, setSelectedNumber] =
    useState<AutocompleteOption<number> | null>(null);
  const [selectedUser, setSelectedUser] =
    useState<AutocompleteOption<User> | null>(null);

  return (
    <div style={{ padding: "40px", maxWidth: "800px", margin: "0 auto" }}>
      <h1>React Search Select Dropdown - Examples</h1>

      {/* Example 1: String Values */}
      <div style={{ marginBottom: "30px" }}>
        <label style={{ display: "block", marginBottom: "8px", fontWeight: 500 }}>
          Example 1: String Values (Countries)
        </label>
        <Autocomplete
          options={countryOptions}
          placeholder="Search country..."
          onSelect={setSelectedCountry}
          customStyles={{
            input: {
              borderColor: "gray",
            },
            dropdown: {
              maxHeight: "300px",
            },
            option: {
              padding: "8px 16px",
              fontSize: "16px",
            },
          }}
        />
        {selectedCountry && (
          <div
            style={{
              marginTop: "12px",
              padding: "12px",
              backgroundColor: "#f0fdf4",
              border: "1px solid #86efac",
              borderRadius: "6px",
              color: "#166534",
              fontSize: "14px",
              lineHeight: "1.6",
            }}
          >
            <strong>Selected:</strong> {selectedCountry.label} (code:{" "}
            {selectedCountry.value})
          </div>
        )}
      </div>

      {/* Example 2: Number Values */}
      <div style={{ marginBottom: "30px" }}>
        <label style={{ display: "block", marginBottom: "8px", fontWeight: 500 }}>
          Example 2: Number Values
        </label>
        <Autocomplete
          options={numberOptions}
          placeholder="Search option..."
          onSelect={setSelectedNumber}
          customStyles={{
            input: {
              borderColor: "gray",
            },
            dropdown: {
              maxHeight: "300px",
            },
            option: {
              padding: "8px 16px",
              fontSize: "16px",
            },
          }}
        />
        {selectedNumber && (
          <div
            style={{
              marginTop: "12px",
              padding: "12px",
              backgroundColor: "#f0fdf4",
              border: "1px solid #86efac",
              borderRadius: "6px",
              color: "#166534",
              fontSize: "14px",
              lineHeight: "1.6",
            }}
          >
            <strong>Selected:</strong> {selectedNumber.label} (ID:{" "}
            {selectedNumber.value})
          </div>
        )}
      </div>

      {/* Example 3: Custom Object Values */}
      <div style={{ marginBottom: "30px" }}>
        <label style={{ display: "block", marginBottom: "8px", fontWeight: 500 }}>
          Example 3: Custom Object Values (Users)
        </label>
        <Autocomplete
          options={userOptions}
          placeholder="Search user..."
          getOptionKey={(option) => option.value.id}
          onSelect={setSelectedUser}
          customStyles={{
            input: {
              borderColor: "gray",
            },
            dropdown: {
              maxHeight: "300px",
            },
            option: {
              padding: "8px 16px",
              fontSize: "16px",
            },
          }}
        />
        {selectedUser && (
          <div
            style={{
              marginTop: "12px",
              padding: "12px",
              backgroundColor: "#f0fdf4",
              border: "1px solid #86efac",
              borderRadius: "6px",
              color: "#166534",
              fontSize: "14px",
              lineHeight: "1.6",
            }}
          >
            <strong>Selected User:</strong>
            <br />
            Name: {selectedUser.label}
            <br />
            ID: {selectedUser.value.id}
            <br />
            Email: {selectedUser.value.email}
            <br />
            Role: {selectedUser.value.role}
          </div>
        )}
      </div>

      {/* Example 4: Disabled State */}
      <div style={{ marginBottom: "30px" }}>
        <label style={{ display: "block", marginBottom: "8px", fontWeight: 500 }}>
          Example 4: Disabled State
        </label>
        <Autocomplete
          options={countryOptions}
          placeholder="This is disabled..."
          disabled={true}
          customStyles={{
            input: {
              borderColor: "gray",
            },
            dropdown: {
              maxHeight: "300px",
            },
            option: {
              padding: "8px 16px",
              fontSize: "16px",
            },
          }}
        />
      </div>

      {/* Example 5: Custom Input with renderInput */}
      <div style={{ marginBottom: "30px" }}>
        <label style={{ display: "block", marginBottom: "8px", fontWeight: 500 }}>
          Example 5: Custom Input (renderInput)
        </label>
        <Autocomplete
          options={countryOptions}
          placeholder="Custom styled input..."
          onSelect={(option) => {
            console.log("Custom input selected:", option);
          }}
          renderInput={(props: AutocompleteInputProps) => (
            <input
              ref={props.ref}
              type={props.type}
              value={props.value}
              onChange={props.onChange}
              onFocus={props.onFocus}
              onBlur={props.onBlur}
              onKeyDown={props.onKeyDown}
              placeholder={props.placeholder}
              disabled={props.disabled}
              autoComplete={props.autoComplete}
              style={{
                ...props.style,
                borderWidth: "2px",
                borderStyle: "solid",
                borderColor: "#10b981",
                borderRadius: "8px",
                fontSize: "16px",
                fontWeight: "bold",
                padding: "12px 60px 12px 16px",
                backgroundColor: "#f0fdf4",
              }}
            />
          )}
          customStyles={{
            dropdown: {
              maxHeight: "300px",
              borderColor: "#10b981",
            },
            option: {
              padding: "12px 16px",
              fontSize: "16px",
            },
            optionHighlighted: {
              backgroundColor: "#d1fae5",
            },
            optionSelected: {
              backgroundColor: "#10b981",
              color: "white",
            },
          }}
        />
      </div>
    </div>
  );
}

export default App;

Keyboard Navigation

  • Arrow Down: Navigate to next option
  • Arrow Up: Navigate to previous option
  • Enter: Select highlighted option
  • Escape: Close dropdown and blur input

API Reference

Props

| Prop | Type | Default | Description | | --------------- | ----------------------------------------------------- | ----------------------- | ------------------------------------------------------- | | options | AutocompleteOption<T>[] | required | Array of options to display | | placeholder | string | 'Search...' | Placeholder text for the input | | onSelect | (option: AutocompleteOption<T> \| null) => void | undefined | Callback when an option is selected | | disabled | boolean | false | Disable the autocomplete | | getOptionKey | (option: AutocompleteOption<T>) => string \| number | Uses value or label | Function to generate unique keys for options | | customStyles | AutocompleteStyles | {} | Override default styles with custom inline styles | | noResultsText | string | 'No results found' | Text to display when no options match the search | | value | AutocompleteOption<T> \| null | undefined | Controlled value for the autocomplete | | renderInput | (props: AutocompleteInputProps) => ReactNode | undefined | Custom input component renderer for maximum flexibility |

Types

interface AutocompleteOption<T = string> {
  value: T;
  label: string;
}

interface AutocompleteInputProps {
  ref: React.RefObject<HTMLInputElement>;
  type: string;
  style: CSSProperties;
  placeholder: string;
  value: string;
  onChange: (e: ChangeEvent<HTMLInputElement>) => void;
  onFocus: () => void;
  onBlur: () => void;
  onKeyDown: (e: KeyboardEvent<HTMLInputElement>) => void;
  disabled: boolean;
  autoComplete: string;
}

interface AutocompleteStyles {
  wrapper?: CSSProperties;
  inputWrapper?: CSSProperties;
  input?: CSSProperties;
  inputFocus?: CSSProperties;
  inputDisabled?: CSSProperties;
  clearButton?: CSSProperties;
  clearButtonHover?: CSSProperties;
  arrow?: CSSProperties;
  arrowOpen?: CSSProperties;
  dropdown?: CSSProperties;
  option?: CSSProperties;
  optionHighlighted?: CSSProperties;
  optionSelected?: CSSProperties;
  optionHighlightedSelected?: CSSProperties;
  noOptions?: CSSProperties;
}

interface AutocompleteProps<T = string> {
  options: AutocompleteOption<T>[];
  placeholder?: string;
  onSelect?: (option: AutocompleteOption<T> | null) => void;
  disabled?: boolean;
  getOptionKey?: (option: AutocompleteOption<T>) => string | number;
  customStyles?: AutocompleteStyles;
  noResultsText?: string;
  value?: AutocompleteOption<T> | null;
  renderInput?: (props: AutocompleteInputProps) => ReactNode;
}

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.