Skip to main content
This component is deprecated and will be removed in future releases. Please use the Dropdown component with multiple prop instead for new projects.View Dropdown Documentation

Overview

NSMultiSelectDropdown is a multi-select dropdown component with search functionality and an “Apply” button. It allows users to select multiple options from a list and apply their selections in batch.

Migration Notice

For new implementations, use the form Dropdown component with multiple={true} which provides:
  • Better accessibility
  • Improved keyboard navigation
  • Form integration capabilities
  • More flexible styling options
  • Better state management

Import

import { NSMultiSelectDropdown } from '@newtonschool/grauity';

Basic Usage

import { NSMultiSelectDropdown } from '@newtonschool/grauity';
import { useState } from 'react';

function Example() {
  const [selectedOptions, setSelectedOptions] = useState(new Set());

  const options = new Set([
    { id: '1', label: 'Option 1' },
    { id: '2', label: 'Option 2' },
    { id: '3', label: 'Option 3' },
    { id: '4', label: 'Option 4' },
  ]);

  return (
    <NSMultiSelectDropdown
      options={options}
      onOptionsChange={(selected) => setSelectedOptions(selected)}
    />
  );
}

Props

noOptionSelctedText
string
default:"'Select'"
Text to display when no option is selected.
Note the typo in the prop name noOptionSelctedText - this is maintained for backwards compatibility.
options
Set<DropdownOption>
default:"new Set([])"
Set of options available for selection. Each option must have id (string) and label properties.
Flag to enable or disable the search functionality.
onSearchInputChange
(value: string) => void
Callback function triggered when the search input value changes.
searchPlaceholder
string
default:"'Search'"
Placeholder text for the search input field.
shouldEnableAllSelected
boolean
default:"true"
Flag to enable or disable the “Select All” functionality.
defaultAllSelected
boolean
default:"false"
Flag to set all options as selected by default.
allOptionText
string
default:"'All'"
Text to display for the “Select All” option and when all options are selected.
onOptionsChange
(options: Set<DropdownOption>) => void
Callback function triggered when the selected options change. Called when the user clicks the “Apply” button.
triggerComponent
React.ReactNode
Additional component to render as the trigger component. If not provided, the default trigger button will be rendered.
className
string
Additional class name for the dropdown wrapper.
interface DropdownOption {
  id: string;
  label: string;
}

Examples

Basic Multi-Select

import { NSMultiSelectDropdown } from '@newtonschool/grauity';
import { useState } from 'react';

function BasicMultiSelect() {
  const [selected, setSelected] = useState(new Set());

  const options = new Set([
    { id: '1', label: 'React' },
    { id: '2', label: 'Vue' },
    { id: '3', label: 'Angular' },
    { id: '4', label: 'Svelte' },
  ]);

  return (
    <div>
      <NSMultiSelectDropdown
        noOptionSelctedText="Select frameworks"
        options={options}
        onOptionsChange={(selected) => {
          setSelected(selected);
          console.log('Selected:', Array.from(selected));
        }}
      />
      
      <div>
        <p>Selected: {selected.size} frameworks</p>
      </div>
    </div>
  );
}

With Select All

import { NSMultiSelectDropdown } from '@newtonschool/grauity';

function SelectAllExample() {
  const options = new Set([
    { id: '1', label: 'Monday' },
    { id: '2', label: 'Tuesday' },
    { id: '3', label: 'Wednesday' },
    { id: '4', label: 'Thursday' },
    { id: '5', label: 'Friday' },
  ]);

  return (
    <NSMultiSelectDropdown
      noOptionSelctedText="Select days"
      options={options}
      shouldEnableAllSelected={true}
      allOptionText="All Days"
      onOptionsChange={(selected) => console.log('Selected days:', selected)}
    />
  );
}

Default All Selected

import { NSMultiSelectDropdown } from '@newtonschool/grauity';

function DefaultAllSelected() {
  const options = new Set([
    { id: '1', label: 'Email' },
    { id: '2', label: 'SMS' },
    { id: '3', label: 'Push' },
  ]);

  return (
    <NSMultiSelectDropdown
      noOptionSelctedText="Notifications"
      options={options}
      defaultAllSelected={true}
      allOptionText="All Notifications"
      onOptionsChange={(selected) => console.log('Enabled:', selected)}
    />
  );
}

With Custom Trigger

import { NSMultiSelectDropdown, NSChip } from '@newtonschool/grauity';
import { useState } from 'react';

function CustomTrigger() {
  const [count, setCount] = useState(0);
  const options = new Set([
    { id: '1', label: 'Option 1' },
    { id: '2', label: 'Option 2' },
    { id: '3', label: 'Option 3' },
  ]);

  return (
    <NSMultiSelectDropdown
      options={options}
      triggerComponent={
        <NSChip>
          Selected: {count}
        </NSChip>
      }
      onOptionsChange={(selected) => setCount(selected.size)}
    />
  );
}

Custom Search Handler

import { NSMultiSelectDropdown } from '@newtonschool/grauity';
import { useState } from 'react';

function CustomSearch() {
  const allOptions = new Set([
    { id: '1', label: 'JavaScript' },
    { id: '2', label: 'TypeScript' },
    { id: '3', label: 'Python' },
    { id: '4', label: 'Java' },
    { id: '5', label: 'Go' },
  ]);
  
  const [filteredOptions, setFilteredOptions] = useState(allOptions);

  const handleSearch = (searchValue: string) => {
    if (!searchValue) {
      setFilteredOptions(allOptions);
      return;
    }

    const filtered = new Set(
      Array.from(allOptions).filter((option) =>
        option.label.toLowerCase().includes(searchValue.toLowerCase())
      )
    );
    setFilteredOptions(filtered);
  };

  return (
    <NSMultiSelectDropdown
      options={filteredOptions}
      onSearchInputChange={handleSearch}
      searchPlaceholder="Search languages..."
      onOptionsChange={(selected) => console.log('Selected:', selected)}
    />
  );
}
import { NSMultiSelectDropdown } from '@newtonschool/grauity';

function NoSearch() {
  const options = new Set([
    { id: '1', label: 'Small' },
    { id: '2', label: 'Medium' },
    { id: '3', label: 'Large' },
  ]);

  return (
    <NSMultiSelectDropdown
      options={options}
      shouldEnableSearch={false}
      noOptionSelctedText="Select size"
      onOptionsChange={(selected) => console.log('Selected:', selected)}
    />
  );
}

Behavior

Apply Pattern: Unlike single-select dropdowns, this component uses an “Apply” button. Selections are only confirmed when the user clicks “Apply”, allowing them to make multiple changes before committing.
Visual Feedback: The dropdown header shows:
  • The placeholder text when nothing is selected
  • “All” (or custom allOptionText) when all options are selected
  • A single option label when one option is selected
  • selected” when multiple (but not all) options are selected
Search functionality is debounced with a 500ms delay to improve performance.

Accessibility

The component includes accessibility features:
  • role="combobox" for the dropdown header
  • role="listbox" for the options list
  • role="searchbox" for the search input
  • aria-expanded to indicate dropdown state
  • aria-controls to link header with list
  • aria-labelledby for proper labeling
  • Keyboard navigation support
  • Click-away detection to close dropdown

Limitations

This component has several limitations compared to the newer Dropdown component:
  • Options are stored in a Set, which can be less convenient than arrays
  • Limited styling customization options
  • No support for option descriptions or icons
  • No grouping or divider support
  • Prop name typo (noOptionSelctedText) maintained for backwards compatibility
Consider migrating to the Dropdown component for a better user experience and more features.

Migration Guide

To migrate from NSMultiSelectDropdown to the modern Dropdown component:
// Old (MultiSelectDropdown)
import { NSMultiSelectDropdown } from '@newtonschool/grauity';

const options = new Set([
  { id: '1', label: 'Option 1' },
  { id: '2', label: 'Option 2' },
]);

<NSMultiSelectDropdown
  options={options}
  onOptionsChange={(selected) => {
    // selected is a Set of DropdownOption objects
    setSelected(selected);
  }}
/>

// New (Dropdown with multiple)
import { NSDropdown } from '@newtonschool/grauity';

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

<NSDropdown
  multiple
  options={options}
  onChange={(values) => {
    // values is an array of selected values
    setSelected(values);
  }}
/>
Key differences:
  • options is now an array instead of a Set
  • Option structure uses value instead of id
  • onChange returns an array of values instead of a Set of objects
  • Built-in “Select All” functionality without extra props
  • Better TypeScript support

Build docs developers (and LLMs) love