Components Forms
MultiSelect
StableChoose several values; selections appear as removable tags and the list stays open while you pick.
Use MultiSelect to choose any number of values from a list, such as the departments a signature template applies to. Selected values show as removable tags in the field. Turn on searchable for long lists. For fewer than six options consider a CheckboxGroup, which shows every choice at once.
Overview
Members of these departments receive the signature.
import { FormField, MultiSelect } from '@bindshq/stance-react';
import type { SelectOptions } from '@bindshq/stance-react';
const departments: SelectOptions = [
{ value: 'sales', label: 'Sales' },
{ value: 'marketing', label: 'Marketing' },
{ value: 'legal', label: 'Legal' },
{ value: 'finance', label: 'Finance' },
{ value: 'support', label: 'Customer support' },
{ value: 'engineering', label: 'Engineering' },
{ value: 'people', label: 'People & culture', disabled: true },
];
export function Basic() {
return (
<div style={{ width: 360 }}>
<FormField
label="Apply template to"
description="Members of these departments receive the signature."
>
<MultiSelect
options={departments}
defaultValue={['sales', 'marketing']}
placeholder="Choose departments"
/>
</FormField>
</div>
);
}Light, dark and high contrast
Every Stance component is designed and tested in all three appearance modes.
Members of these departments receive the signature.
Members of these departments receive the signature.
Members of these departments receive the signature.
Import
import { MultiSelect, type SelectOptions } from '@bindshq/stance-react';Examples
Searchable
Type to filter; Backspace in an empty search removes the last tag.
import { FormField, MultiSelect } from '@bindshq/stance-react';
import type { SelectOptions } from '@bindshq/stance-react';
const departments: SelectOptions = [
{ value: 'sales', label: 'Sales' },
{ value: 'marketing', label: 'Marketing' },
{ value: 'legal', label: 'Legal' },
{ value: 'finance', label: 'Finance' },
{ value: 'support', label: 'Customer support' },
{ value: 'engineering', label: 'Engineering' },
{ value: 'people', label: 'People & culture', disabled: true },
];
export function Searchable() {
return (
<div style={{ width: 360 }}>
<FormField label="Departments">
<MultiSelect options={departments} searchable placeholder="Search departments" />
</FormField>
</div>
);
}import * as React from 'react';
import { FormField, MultiSelect } from '@bindshq/stance-react';
import type { SelectOptions } from '@bindshq/stance-react';
const departments: SelectOptions = [
{ value: 'sales', label: 'Sales' },
{ value: 'marketing', label: 'Marketing' },
{ value: 'legal', label: 'Legal' },
{ value: 'finance', label: 'Finance' },
{ value: 'support', label: 'Customer support' },
{ value: 'engineering', label: 'Engineering' },
{ value: 'people', label: 'People & culture', disabled: true },
];
export function Controlled() {
const [value, setValue] = React.useState<string[]>([
'sales',
'legal',
'finance',
'support',
'engineering',
]);
return (
<div style={{ display: 'grid', gap: 8, width: 360 }}>
<FormField label="Departments">
<MultiSelect options={departments} value={value} onValueChange={setValue} maxTags={2} />
</FormField>
<span style={{ color: 'var(--st-color-fg-muted)', fontSize: 'var(--st-font-size-sm)' }}>
{value.length} departments selected
</span>
</div>
);
}Select at least one department
import { FormField, MultiSelect } from '@bindshq/stance-react';
import type { SelectOptions } from '@bindshq/stance-react';
const departments: SelectOptions = [
{ value: 'sales', label: 'Sales' },
{ value: 'marketing', label: 'Marketing' },
{ value: 'legal', label: 'Legal' },
{ value: 'finance', label: 'Finance' },
{ value: 'support', label: 'Customer support' },
{ value: 'engineering', label: 'Engineering' },
{ value: 'people', label: 'People & culture', disabled: true },
];
export function Invalid() {
return (
<div style={{ width: 360 }}>
<FormField label="Departments" error="Select at least one department" required>
<MultiSelect options={departments} />
</FormField>
</div>
);
}API reference
| Prop | Type | Default | Description |
|---|---|---|---|
options* required | SelectOptions | None | Options or groups, as in Select. |
value / defaultValue | string[] | [] | Selected values (controlled or initial). |
onValueChange | (value: string[]) => void | None | Called on every change. |
placeholder | string | 'Select…' | Shown when nothing is selected. |
searchable | boolean | false | Replace the button with a filter input. |
searchPlaceholder | string | 'Search…' | Placeholder of the search input once values are selected. |
showActions | boolean | true | Show “Select all” and a live count above the list. |
maxTags | number | 3 | Collapse further tags into “+N”. |
name / form | string | None | Submits one hidden input per selected value. |
size | 'sm' | 'md' | 'lg' | 'md' | Minimum control height. |
disabled / required / invalid | boolean | None | Also inherited from FormField. |
open / defaultOpen / onOpenChange | boolean / function | None | Popup open state. |
removeLabel | (label: string) => string | `Remove ${label}` | Accessible label for tag remove buttons (localisation). |
emptyText | ReactNode | 'No matches' | Shown when the search matches nothing. |
Accessibility
- The control is a combobox controlling a listbox with aria-multiselectable="true"; options expose aria-selected.
- Selected tags are a labelled list; each has a remove button with a descriptive label.
- The “N selected” count is announced politely as selections change.
- Choosing an option keeps the list open so several values can be picked in one pass.
Keyboard
| Keys | Action |
|---|---|
| ArrowDown ArrowUp Enter | Open the list. |
| ArrowDown ArrowUp | Move the active option. |
| Enter Space | Toggle the active option (Space only without search). |
| Ctrl+A ⌘A | Select or deselect all visible options. |
| Backspace | With an empty search, remove the last selected value. |
| Escape Tab | Close the list. |
Usage guidelines
Do
- Use searchable when there are more than about 15 options.
- Show a count or summary when many values are selected.
Don’t
- Use MultiSelect when only one value is allowed.
- Hide important constraints, such as a maximum, until after submission.