Multi Select
Pick several options. The gap Select cannot fill — it is a single-value combobox by construction, which is why the LogViewer level filter had to become a threshold instead of a set.
src/components/ui/multi-select.tsxAbout
From the component's own source, where it was written.
Select several options from a list.
The gap Select cannot fill: it is a single-value combobox by construction, which is why LogViewer's level filter had to become a threshold instead of a set. This is the set version.
The trigger shows chips up to maxShown and then a count. Rendering every chip makes the control grow without limit and pushes the rest of the form around as options are picked — the count keeps the height stable.
Selecting does not close the panel. Multi-select exists because people pick more than one thing, and closing after each is the single most common complaint about these controls.
Install
npx astralyx-ui add multi-select
Usage
import { MultiSelect } from '@/components/ui/multi-select'
<MultiSelect options={options} value={selected} onValueChange={setSelected} />Composer
Change the props and the source below follows.
<MultiSelect
options={options}
value={selected}
onValueChange={setSelected}
maxShown={2}
searchable={true}
/>Examples
Selection
<MultiSelect options={options} defaultValue={['build', 'test']} />API
Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.
MultiSelect
Extends Omit<ComponentProps<'div'>, 'defaultValue' | 'onChange'>.
| Prop | Type | Default | Description |
|---|---|---|---|
| options | MultiSelectOption[] | required | { value, label, description?, disabled? }. |
| value | string[] | — | Controlled or uncontrolled. |
| defaultValue | string[] | [] | — |
| onValueChange | (value: string[]) => void | — | Controlled or uncontrolled. |
| placeholder | string | 'Select…' | — |
| searchable | boolean | true | — |
| maxShown | number | 2 | Chips before collapsing to a count. Rendering every chip makes the trigger grow without limit and pushes the rest of the form around. |
| size | keyof typeof fieldSize | 'md' | — |
| variant | 'default' | 'secondary' | 'ghost' | 'default' | — |
| error | boolean | false | — |
| disabled | boolean | false | — |
| searchPlaceholder | string | 'Filter' | — |
| searchLabel | string | 'Filter options' | Accessible name for the filter field. |
| emptyMessage | ReactNode | 'No options match.' | — |
| clearLabel | ReactNode | 'Clear' | — |
| removeLabel | (option: string) => string | DEFAULT_REMOVE_LABEL | Accessible name for a chip's remove button. |
| triggerClassName | string | — | — |
Types
MultiSelectOption
Select several options from a list.
| Field | Type | Description |
|---|---|---|
| value | string | — |
| label | string | — |
| description? | string | — |
| disabled? | boolean | — |
Behaviour
| Topic | Detail | Description |
|---|---|---|
| closing | never on select | Multi-select exists because people pick more than one thing; closing after each is the most common complaint about these controls. |