Import
import { Multiselect } from '@contentful/f36-multiselect';
Examples
Basic usage
The Multiselect is a fully controlled form element and expects the selectable items as children via the compound component Multiselect.Option.
Properties are:
For the multiselect itself:
- currentSelection (optional but recommended): an array of the labels of selected options. This will give the user a hint that there are selected items. This is optional
- placeholder (optional): Label of the trigger button without selected elements
- startIcon (optional): Icon on the start of the trigger button
- isLoading: enables showing a loading animation while searching or loading results
Inherited propertys from Popover Component.
- listWidth (optional): auto or full
- listMaxHeight (optional): sets the maximum height of the list drawer, overflow will be scrolled
It also accepts refs for the toggle button, the searchInput and the list.
For the option:
- itemId: identifier for the element, used to link the label with the checkbox
- value: the actual value of the select option
- label: displayed label
- onSelectItem: This function is called when the user selects a option, it needs to be passed to the MultiselectOption
- isChecked (optional): controlls if a element is initially selected
- isDisabled (optional): controlls if a element is changeable
function MultiselectBasicUsageExample() {
const spaces = [
'Travel Blog',
'Finnance Blog',
'Fitness App',
'News Website',
'eCommerce Catalogue',
'Photo Gallery',
];
const [selectedSpaces, setSelectedSpaces] = React.useState([]);
const handleSelectItem = (event) => {
const { checked, value } = event.target;
if (checked) {
setSelectedSpaces((prevState) => [...prevState, value]);
} else {
const newSelectedSpaces = selectedSpaces.filter(
(space) => space !== value,
);
setSelectedSpaces(newSelectedSpaces);
}
};
return (
<Stack flexDirection="column" alignItems="start">
<Multiselect
currentSelection={selectedSpaces}
popoverProps={{ isFullWidth: true }}
>
{spaces.map((space) => {
const val = space.toLowerCase().replace(/\s/g, '-');
return (
<Multiselect.Option
key={`key-${val}}`}
itemId={`space-${val}}`}
value={space}
label={space}
onSelectItem={handleSelectItem}
isChecked={selectedSpaces.includes(space)}
/>
);
})}
</Multiselect>
</Stack>
);
}
Searchable options
One optional feature of the Multiselect component is to allow filtering the list via a search field.
To make it work, the onSearchValueChange callback function needs to be provided.
To enable searching the following properties have to be set.
- onSearchValueChange: Callbackfunction which enables the search field. This function needs to provide the search /filter algorithm
- searchPlaceholder (optional): placeholder for the search field
- noMatchesMessage (optional): message shown when search result is empty
function MultiselectSearchExample() {
const spaces = [
'Travel Blog',
'Finnance Blog',
'Fitness App',
'News Website',
'eCommerce Catalogue',
'Photo Gallery',
];
const [selectedItems, setSelectedItems] = React.useState([]);
const [filteredItems, setFilteredItems] = React.useState(spaces);
const handleSearchValueChange = (event) => {
const value = event.target.value;
const newFilteredItems = spaces.filter((item) =>
item.toLowerCase().includes(value.toLowerCase()),
);
setFilteredItems(newFilteredItems);
};
const handleSelectItem = (event) => {
const { checked, value } = event.target;
if (checked) {
setSelectedItems((prevState) => [...prevState, value]);
} else {
const newSelectedFruits = selectedItems.filter(
(fruit) => fruit !== value,
);
setSelectedItems(newSelectedFruits);
}
};
return (
<Stack flexDirection="column" alignItems="start">
<Multiselect
searchPlaceholder="Search spaces"
onSearchValueChange={handleSearchValueChange}
popoverProps={{ isFullWidth: true }}
currentSelection={selectedItems}
>
{filteredItems.map((item, index) => {
return (
<Multiselect.Option
value={item}
label={item}
onSelectItem={handleSelectItem}
key={`${item}-${index}`}
itemId={`${item}-${index}`}
isChecked={selectedItems.includes(item)}
isDisabled={item === 'eCommerce Catalogue'}
/>
);
})}
</Multiselect>
</Stack>
);
}
SelectAll Option
To offer a shortcut for selecting and deselecting all options, you can use the compound component SelectAll. This requires a callback function which needs to contain your implementation for selecting all options.
function MultiselectSelectAllExample() {
const spaces = React.useMemo(
() => [
'Travel Blog',
'Finnance Blog',
'Fitness App',
'News Website',
'eCommerce Catalogue',
'Photo Gallery',
],
[],
);
const [selectedSpaces, setSelectedSpaces] = React.useState([]);
const handleSelectItem = (event) => {
const { checked, value } = event.target;
if (checked) {
setSelectedSpaces((prevState) => [...prevState, value]);
} else {
setSelectedSpaces((prevState) =>
prevState.filter((space) => space !== value),
);
}
};
const toggleAll = (event) => {
const { checked } = event.target;
if (checked) {
setSelectedSpaces(spaces);
} else {
setSelectedSpaces([]);
}
};
const areAllSelected = React.useMemo(() => {
return spaces.every((element) => selectedSpaces.includes(element));
}, [selectedSpaces, spaces]);
return (
<Stack flexDirection="column" alignItems="start">
<Multiselect
currentSelection={selectedSpaces}
popoverProps={{ isFullWidth: true }}
>
<Multiselect.SelectAll
onSelectItem={toggleAll}
isChecked={areAllSelected}
/>
{spaces.map((space) => {
const val = space.toLowerCase().replace(/\s/g, '-');
return (
<Multiselect.Option
key={`key-${val}`}
itemId={`space-${val}`}
value={space}
label={space}
onSelectItem={handleSelectItem}
isChecked={selectedSpaces.includes(space)}
/>
);
})}
</Multiselect>
</Stack>
);
}
Content guidelines
- Multiselect placeholder should be short but descriptive.
- Multiselect options can come from a simple array of strings or more complex objects.
- Do not use the index position of the items in the filtered array for keys or ids, as they are going to change while filtering.
- Use any algorithm you like in order to search and filter. Depending on your implementation you can also generate a new request to your dataset based on the users input.
Accessibility
- When focussing the toggle button, the enter key opens it. The dropdown content automatically will be focussed
- Pressing the space bar toggles the checked state of an option and will trigger the onSelectItem callback function