⚡ Lightweight 📦 Zero Dependencies ⚙️ TypeScript ♿ Accessible

react-multiple-select-container

A production-ready React component for selecting multiple values — with search, chips, select-all, and built-in state management. Drop it in and it just works.

Live Demo Get Started

Why this package?

Native <select multiple> has terrible UX. This gives you everything you need in one import.

🔍

Built-in Search

Type to instantly filter through large option lists. Searchable by default, or turn it off with one prop.

🏷️

Chip Display

Selected items appear as removable chips. Or switch to compact count mode with showChips={false}.

Select All

One-click select/deselect all visible options. Respects disabled items and max selection limits.

🔒

Max Selections

Cap the number of picks with maxSelections. Remaining options auto-disable when the limit is hit.

⚖️

Controlled & Uncontrolled

Pass value + onChange for full control, or just options and let the component manage state.

🛠️

useMultiSelect Hook

Need a custom UI? Use the standalone hook for state logic — toggle, selectAll, clearAll, isSelected.

🎨

Easy Styling

All classes prefixed with rms-. Override any class in your own CSS — zero conflicts.

📜

Full TypeScript

Written in TypeScript. Ships with complete type definitions for Option, MultiSelectProps, and the hook.

Accessible

Proper ARIA roles — combobox, listbox, option. Keyboard navigation with Enter, Space, and Escape.

Install

Add the package and import the styles — that's all the setup.

npm install react-multiple-select-container

Usage

Two lines of imports and you're ready. Works uncontrolled or controlled.

JSX
import { MultiSelect } from "react-multiple-select-container";
import "react-multiple-select-container/styles.css";

const fruits = [
  { label: "Apple",  value: "apple" },
  { label: "Banana", value: "banana" },
  { label: "Cherry", value: "cherry" },
  { label: "Mango",  value: "mango" },
];

function App() {
  return (
    <MultiSelect
      options={fruits}
      placeholder="Pick your fruits"
      onChange={(selected) => console.log(selected)}
    />
  );
}
JSX
import { useState } from "react";
import { MultiSelect } from "react-multiple-select-container";
import "react-multiple-select-container/styles.css";

function App() {
  const [selected, setSelected] = useState([]);

  return (
    <MultiSelect
      options={fruits}
      value={selected}
      onChange={setSelected}
    />
  );
}
JSX
// Max 3 selections, no search, count mode
<MultiSelect
  options={options}
  maxSelections={3}
  searchable={false}
  showChips={false}
  placeholder="Pick up to 3..."
/>

// Disabled options
const roles = [
  { label: "Admin",    value: "admin" },
  { label: "Guest",    value: "guest", disabled: true },
  { label: "Moderator", value: "mod" },
];

<MultiSelect options={roles} />

Props

Full API reference for the <MultiSelect /> component.

Prop Type Default Description
options Option[] required Array of { label, value, disabled? }
value string[] Selected values (controlled mode)
defaultValue string[] [] Initial values (uncontrolled mode)
onChange (values: string[]) => void Callback fired when selection changes
placeholder string "Select..." Placeholder text when nothing is selected
searchable boolean true Show the search input in the dropdown
searchPlaceholder string Search input placeholder text (omit for none)
selectAll boolean true Show "Select All" option
selectAllLabel string "Select All" Label for the select all option
maxSelections number Maximum number of items that can be selected
disabled boolean false Disable the entire component
className string "" Custom CSS class on the container
showChips boolean true Show chips (true) or "N selected" count (false)
closeOnSelect boolean false Close dropdown after each selection

useMultiSelect Hook

For custom UIs — get all the state logic without the built-in dropdown.

Hook
import { useMultiSelect } from "react-multiple-select-container";

const {
  selected,        // string[] — current selected values
  setSelected,     // Dispatch — replace the entire selection
  toggle,          // (value) — add or remove a single value
  select,          // (value) — add a value (no-op if exists)
  deselect,        // (value) — remove a value
  selectAll,       // () — select all non-disabled options
  clearAll,        // () — clear everything
  isSelected,      // (value) — boolean check
  selectedOptions, // Option[] — full option objects for selected
} = useMultiSelect(options, initialValue?);
toggle(value)

Add the value if not selected, remove it if already selected.

select(value)

Add a value to the selection. No-op if already present.

deselect(value)

Remove a value from the selection.

selectAll()

Select all non-disabled options in one go.

clearAll()

Clear the entire selection back to empty.

isSelected(value)

Returns true if the value is currently selected.

selectedOptions

Full Option[] objects for all currently selected values.

setSelected(values)

Replace the entire selection with a new array.

Styling

Import the default CSS, then override any rms- prefixed class.

CSS
/* Import default styles */
import "react-multiple-select-container/styles.css";

/* Override anything you want */
.rms-control {
  border-radius: 12px;
  border-color: #3b82f6;
}
.rms-chip {
  background: #dbeafe;
  color: #1d4ed8;
}

Available CSS Classes

.rms-container
.rms-control
.rms-control--open
.rms-value-area
.rms-placeholder
.rms-chips
.rms-chip
.rms-chip-label
.rms-chip-remove
.rms-count
.rms-indicators
.rms-clear
.rms-separator
.rms-dropdown
.rms-search-wrapper
.rms-search
.rms-options
.rms-option
.rms-option--selected
.rms-option--disabled
.rms-option--select-all
.rms-checkbox
.rms-checkbox--checked
.rms-no-results