A React multi select dropdown - check off several options, the menu stays open. For filters and pickers.
MultiSelect playground
Install MultiSelect
1. New project? One command installs the package and wires everything - see Installation:
pnpm dlx zyncat-ui init2. Import the component - it loads its own stylesheet:
import { MultiSelect } from '@zyncat/ui/multi-select';Usage
import { MultiSelect } from '@zyncat/ui/multi-select'; <MultiSelect ariaLabel="Channels" value={channels} onChange={setChannels} options={CHANNELS} searchable />Compose MultiSelect in your application. No Tailwind or external styling library is required; every value resolves from Zyncat UI's token vocabulary.
MultiSelect props
MultiSelect
SelectGroup
SelectOption
Frequently asked questions
Import it per subpath and pass the options plus the selected array: import { MultiSelect } from '@zyncat/ui/multi-select', then <MultiSelect options={CHANNELS} value={channels} onChange={setChannels} ariaLabel="Channels" searchable />. options takes a flat SelectOption[] or SelectGroup[] for labelled sections, value is the array of selected option values, and onChange fires with the next array plus the option that was toggled. Drop value and pass defaultValue instead to run it uncontrolled.
The first selected option's label followed by a +N pill counting the rest, so three selections read "Design +2". One selection shows just that label, and its icon if the option carries one; none shows placeholder, which defaults to "Select options".
Both are built in. Every row draws a checkbox tick that tracks its aria-selected state, and searchable pins a type-to-filter field above the list which matches each option against its label and its description. searchPlaceholder sets that field's text; without searchable, typing into the open menu jumps to an option by prefix instead.
The native <select multiple> needs Ctrl or Cmd-click to add to a selection, renders as a scrolling box rather than a dropdown, and barely takes styling. This is a custom listbox instead: one click toggles a row, the menu stays put, and the size, highlight and rail props restyle it on top of the same design tokens as the rest of the library. It is MIT, needs no jQuery plugin and no Tailwind config, and ships zero runtime dependencies.
Yes. The trigger is a role="combobox" button wired with aria-haspopup, aria-expanded, aria-controls and aria-activedescendant, the list is a role="listbox" with aria-multiselectable, and each row is a role="option" carrying aria-selected. Arrow keys move the active option, Home and End jump to the ends, Enter toggles it - so does Space, unless searchable has put the caret in the filter field - Escape closes and returns focus to the trigger, and disabled options are skipped by keyboard nav and typeahead alike.