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.tsx

About

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.

Props
tsx
<MultiSelect
  options={options}
  value={selected}
  onValueChange={setSelected}
  maxShown={2}
  searchable={true}
/>

Examples

Selection

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'>.

PropTypeDefaultDescription
optionsMultiSelectOption[]required{ value, label, description?, disabled? }.
valuestring[]—Controlled or uncontrolled.
defaultValuestring[][]—
onValueChange(value: string[]) => void—Controlled or uncontrolled.
placeholderstring'Select…'—
searchablebooleantrue—
maxShownnumber2Chips before collapsing to a count. Rendering every chip makes the trigger grow without limit and pushes the rest of the form around.
sizekeyof typeof fieldSize'md'—
variant'default' | 'secondary' | 'ghost''default'—
errorbooleanfalse—
disabledbooleanfalse—
searchPlaceholderstring'Filter'—
searchLabelstring'Filter options'Accessible name for the filter field.
emptyMessageReactNode'No options match.'—
clearLabelReactNode'Clear'—
removeLabel(option: string) => stringDEFAULT_REMOVE_LABELAccessible name for a chip's remove button.
triggerClassNamestring——

Types

MultiSelectOption

Select several options from a list.

FieldTypeDescription
valuestring—
labelstring—
description?string—
disabled?boolean—

Behaviour

TopicDetailDescription
closingnever on selectMulti-select exists because people pick more than one thing; closing after each is the most common complaint about these controls.