group | package | title | order | slug | category | description | props | import | source | docs | styles | ||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
mantine-core |
@mantine/core |
MultiSelect |
1 |
/core/multi-select/ |
inputs |
Custom searchable multi select |
|
import { MultiSelect } from '@mantine/core'; |
mantine-core/src/MultiSelect/MultiSelect.tsx |
core/MultiSelect.mdx |
|
import { MultiSelectDemos } from '@mantine/demos';
MultiSelect component allows user to pick any amount of option from the given data
:
<Demo data={MultiSelectDemos.countries} demoProps={{ toggle: true, zIndex: 4 }} />
A bare minimum example:
import { useState } from 'react';
import { MultiSelect } from '@mantine/core';
function Demo() {
const [value, setValue] = useState([]);
return <MultiSelect value={value} onChange={setValue} data={[]} />;
}
Note that MultiSelect value should always be an array of either string or undefined:
// Incorrect, will have bugs
<MultiSelect data={[{ value: 1, label: '1' }]} value={[1]} />
// Correct, works as expected
<MultiSelect data={[{ value: '1', label: '1' }]} value={['1']} />
MultiSelect support two different data formats:
- An array of strings – use when you do not need to customize item component or display
label
different thanvalue
- An array of objects with required
value
andlabel
properties and any other additional properties
// Data as an array of strings, will be mapped to
// [
// { value: 'React', label: 'React' },
// { value: 'Angular', label: 'Angular' },
// { value: 'Svelte', label: 'Svelte' },
// { value: 'Vue', label: 'Vue' },
// ]
<MultiSelect data={['React', 'Angular', 'Svelte', 'Vue']} />
// Data as an array of objects:
// Minimal example (same as first example above)
<MultiSelect data={[
{ value: 'React', label: 'React' },
{ value: 'Angular', label: 'Angular' },
{ value: 'Svelte', label: 'Svelte' },
{ value: 'Vue', label: 'Vue' },
]} />
// Additional data properties for custom item component (see documentation below)
<MultiSelect
valueComponent={({ value, label, image, name }) => /* Your custom value component with data properties */}
itemComponent={({ value, label, image, name }) => /* Your custom item component with data properties */}
data={[
{
value: 'bob@handsome.inc',
label: 'bob@handsome.inc',
image: 'image-link',
name: 'Bob Handsome',
},
{
value: 'bill@outlook.com',
label: 'bill@outlook.com',
image: 'image-link',
name: 'Bill Rataconda',
},
{
value: 'amy@wong.cn',
label: 'amy@wong.cn',
image: 'image-link',
name: 'Amy Wong',
},
]}
/>
Set searchable
prop to enable search in select and nothingFound
prop to provide label that will be shown when no options were found:
Set searchValue
and onSearchChange
prop to enable controlled search in select:
Set clearable
prop to enable clearing all values at once.
When prop is true and at least value is selected clear button will replace chevron in right section:
Set creatable
and getCreateLabel
props to enable creating new select item.
Note that you will need to handle data state to manage item creation correctly:
When dropdown height is exceeded dropdown becomes scrollable, to change max-height set maxDropdownHeight
prop with value in px:
You can change select item component and filtering logic that is used in search. To do so you will need to:
- Add extra props to
data
objects - Create
filter
function which determines whether item should be added to the search results - Provide
itemComponent
which will consumedata
objects
Apart from itemComponent
you can customize appearance of label by providing valueComponent
:
By default, dropdown is placed below the input and when there is not enough space, it flips to be above the input.
To change this behavior, set dropdownPosition
prop:
If you have a large data set (> 100 items) you will have to optimize items rendering.
The best strategy is to use searchable
option with limit
:
// Only 20 items are rendered at a time
// See countries list example above
<MultiSelect searchable limit={20} />
By default, dropdown animations are turned off to increase responsiveness. You can enable them by setting optional props:
transition
– premade transition name or custom transition styles object, see Transition component for all available optionstransitionDuration
– transition duration in ms, defaults to 0transitionTimingFunction
– defaults totheme.transitionTimingFunction
By default, MultiSelect uses ScrollArea to render dropdown.
If you want to use native scrollbars instead, set div
as a dropdown component:
You can use any React node as icon:
<Demo data={MultiSelectDemos.icon} demoProps={{ zIndex: 4 }} />
In disabled state:
- options to remove, add or search is disabled
- input cannot be cleared with clear button
- cursor is changed to
not-allowed
You can replace icon in right section with rightSection
prop.
Note that in this case clearable
option will not work and will need to handle it yourself:
import { useRef } from 'react';
import { MultiSelect } from '@mantine/core';
function Demo() {
const ref = useRef<HTMLInputElement>(null);
return <MultiSelect ref={ref} data={[]} />;
}
Provide aria-label
in case you use component without label for screen reader support:
<MultiSelect /> // -> not ok, select is not labeled
<MultiSelect label="My select" /> // -> ok, select and label is connected
<MultiSelect aria-label="My select" /> // -> ok, label is not visible but will be announced by screen reader
If you use clearable
option set clearButtonLabel
:
<MultiSelect clearable clearButtonLabel="Clear select field" />