MultiSelect

stable
Since 1.2
Multiple-choice picker with search, select-all, removable value tags, a custom footer, and distinct empty and no-match states.
Forms
primitive
Display
Documented
import { MultiSelect } from '@ivim/native/components';

When to use

Use when
Several values are chosen from a list too long to show all at once.
The chosen values should stay visible and individually removable — use showSelectedTags.
Don't use when
Only one value may be chosen — use Select.
There are a handful of short options that should stay visible — use CheckboxGroup or TagGroup.

Playground

Adjust the controls to preview live prop combinations. The code snippet updates to match the current selection.
Teams
size
size
Searchable
isSearchable
Select all
hasSelectAll
Selected tags
showSelectedTags
Disabled
isDisabled
<MultiSelect />

Example

States
Default
Teams
With a selection
Teams
Searchable, with select all
Teams
Removable selected tags
Teams
Custom summary wording
Teams
With a footer
Teams
Empty list (distinct from no matches)
Teams
One option disabled
Teams
With an error
Teams
Disabled
Teams

Anatomy

The parts that compose this component.
1
Trigger
Summarizes the selection and reports expanded state.
2
Selected tags
Optional removable tags beneath the trigger.
3
Overlay
Search field, bulk actions, the option list, and an optional footer.
4
Option
A checkbox row carrying its own label and description.
5
Footer
Pinned content below the list, e.g. a "create new" action.

Guidelines

Do
Use formatSelection to say what is being counted ("3 teams") rather than the generic "3 selected".
Do
Turn on showSelectedTags when the exact selection matters more than its size.
Do
Give the empty state real wording when the list can legitimately be empty — it is a different situation from a search that matched nothing.
Don't
Offer select-all over a list long enough that selecting everything is rarely what someone means.

Props

Public props for this component. Required props are marked; defaults reflect the component implementation.
options
required
MultiSelectOption[]
{ value, label, description?, isDisabled? }.
selectedKeys / defaultSelectedKeys
string[]
Controlled and uncontrolled selection.
onSelectionChange
(keys: string[]) => void
Fires with the next selection.
isSearchable / hasSelectAll
boolean
default: false
Adds a filter field, and "Select all" / "Clear" controls.
showSelectedTags
boolean
default: false
Renders the selection as removable tags beneath the trigger.
formatSelection
(count: number, total: number) => string
Overrides the trigger summary.
emptyState / footer
ReactNode
Shown when the option list is empty, and pinned below the list.
disabledKeys
string[]
Keys that cannot be toggled, in addition to per-option isDisabled.
aria-label
string
Accessible name when there is no visible label, or when the label is not plain text.
label / description / errorMessage / placeholder
ReactNode / ReactNode / ReactNode / string
Field anatomy; label, requirement, and error all reach the trigger’s accessible name.
isDisabled / isInvalid / isRequired
boolean
default: false
Field state.
size / fullWidth
'sm' | 'md' | 'lg' / boolean
default: 'md' / false
Trigger height and whether it fills its container.

Accessibility

Roles and screen-reader behavior this component provides, plus keyboard interactions.
The trigger announces label, requirement, the current summary, and any error as one name.
Options are checkboxes, so their selected state is announced individually.
Select-all and clear operate only on enabled options — a disabled option is one the user may not change, so a bulk action must not change it either.
A disabled option that is already selected is preserved by clear, rather than being removed into a state the user cannot restore.
The empty-list and no-matches states are distinct, so nobody retypes against a collection that was never populated.
Tab
Moves focus to the trigger, then into the overlay.
Space / Enter
Opens the overlay, or toggles the focused option.
Escape
Dismisses the overlay.

Platform & RTL

Behavior that differs across the platforms this component runs on.
Web
The overlay is a floating surface over a dismiss layer; every control inside is focusable.
iOS
The overlay presents from the bottom; tapping outside dismisses it.
Android
Matches iOS; the hardware back button dismisses the overlay.
RTL
Trigger content, tags, and option rows mirror with the writing direction.

State coverage

Interaction and visual states this component supports.
base
semantic color
density

Token references

Semantic design tokens this component page exercises. Tap one to edit it live.