Skip to content

MultiSelect

Multi-select dropdown field with checkbox-style options.

function MultiSelectStory(args: React.ComponentProps<typeof MultiSelect>) {
const [value, setValue] = useState<string[]>(['name', 'email']);
return (
<MultiSelect
{...args}
hasClear
onChange={setValue}
startIcon={Columns3}
value={value}
/>
);
}
<MultiSelectStory {...args} />
function MultiSelectStory(args: React.ComponentProps<typeof MultiSelect>) {
const [value, setValue] = useState<string[]>(['name', 'email']);
return (
<MultiSelect
{...args}
hasClear
onChange={setValue}
startIcon={Columns3}
value={value}
/>
);
}
<MultiSelectStory {...args} />
function EmptyMultiSelectStory(args: React.ComponentProps<typeof MultiSelect>) {
const [value, setValue] = useState<string[]>([]);
return (
<MultiSelect
{...args}
hasClear
onChange={setValue}
startIcon={Columns3}
value={value}
/>
);
}
<EmptyMultiSelectStory {...args} />
function TriggerVariantsStory(args: React.ComponentProps<typeof MultiSelect>) {
const [ghostValue, setGhostValue] = useState<string[]>(['name', 'email']);
const [buttonValue, setButtonValue] = useState<string[]>(['role']);
return (
<VStack gap={2} width="full">
<Toolbar
dividers={['bottom']}
label="Ghost trigger example"
size="sm"
startContent={
<>
<Button icon={Filter} label="Filter" variant="ghost" />
<MultiSelect
{...args}
isLabelHidden
label="Column filter"
onChange={setGhostValue}
value={ghostValue}
variant="ghost"
/>
</>
}
/>
<Toolbar
dividers={['bottom']}
label="Button trigger example"
size="sm"
startContent={
<>
<Button icon={Filter} label="Filter" variant="secondary" />
<MultiSelect
{...args}
isLabelHidden
label="Column filter"
onChange={setButtonValue}
value={buttonValue}
variant="button"
/>
</>
}
/>
</VStack>
);
}
<TriggerVariantsStory {...args} />
function MultiSelectStory(args: React.ComponentProps<typeof MultiSelect>) {
const [value, setValue] = useState<string[]>(['name', 'email']);
return (
<MultiSelect
{...args}
hasClear
onChange={setValue}
startIcon={Columns3}
value={value}
/>
);
}
<MultiSelectStory {...args} />
function MultiSelectStory(args: React.ComponentProps<typeof MultiSelect>) {
const [value, setValue] = useState<string[]>(['name', 'email']);
return (
<MultiSelect
{...args}
hasClear
onChange={setValue}
startIcon={Columns3}
value={value}
/>
);
}
<MultiSelectStory {...args} />
function MultiSelectStory(args: React.ComponentProps<typeof MultiSelect>) {
const [value, setValue] = useState<string[]>(['name', 'email']);
return (
<MultiSelect
{...args}
hasClear
onChange={setValue}
startIcon={Columns3}
value={value}
/>
);
}
<MultiSelectStory {...args} />
function MultiSelectStory(args: React.ComponentProps<typeof MultiSelect>) {
const [value, setValue] = useState<string[]>(['name', 'email']);
return (
<MultiSelect
{...args}
hasClear
onChange={setValue}
startIcon={Columns3}
value={value}
/>
);
}
<MultiSelectStory {...args} />
function MultiSelectStory(args: React.ComponentProps<typeof MultiSelect>) {
const [value, setValue] = useState<string[]>(['name', 'email']);
return (
<MultiSelect
{...args}
hasClear
onChange={setValue}
startIcon={Columns3}
value={value}
/>
);
}
<MultiSelectStory {...args} />
function MultiSelectStory(args: React.ComponentProps<typeof MultiSelect>) {
const [value, setValue] = useState<string[]>(['name', 'email']);
return (
<MultiSelect
{...args}
hasClear
onChange={setValue}
startIcon={Columns3}
value={value}
/>
);
}
<MultiSelectStory {...args} />
function MultiSelectStory(args: React.ComponentProps<typeof MultiSelect>) {
const [value, setValue] = useState<string[]>(['name', 'email']);
return (
<MultiSelect
{...args}
hasClear
onChange={setValue}
startIcon={Columns3}
value={value}
/>
);
}
<MultiSelectStory {...args} />
function CustomOptionsStory(args: React.ComponentProps<typeof MultiSelect>) {
const [value, setValue] = useState<string[]>(['name', 'role']);
return (
<MultiSelect {...args} hasSearch onChange={setValue} value={value}>
{option => (
<SelectOption
description={`${option.value}.field`}
icon={User}
label={option.label ?? option.value}
/>
)}
</MultiSelect>
);
}
<CustomOptionsStory {...args} />
Choose which columns are visible in the table.
function MultiSelectStory(args: React.ComponentProps<typeof MultiSelect>) {
const [value, setValue] = useState<string[]>(['name', 'email']);
return (
<MultiSelect
{...args}
hasClear
onChange={setValue}
startIcon={Columns3}
value={value}
/>
);
}
<MultiSelectStory {...args} />
function OverflowBadgesStory(args: React.ComponentProps<typeof MultiSelect>) {
const [value, setValue] = useState<string[]>([
'name',
'email',
'role',
'status',
]);
return (
<MultiSelect
{...args}
hasClear
maxBadges={2}
onChange={setValue}
startIcon={Columns3}
triggerDisplay="badges"
value={value}
/>
);
}
<OverflowBadgesStory {...args} />
function EmptyMultiSelectStory(args: React.ComponentProps<typeof MultiSelect>) {
const [value, setValue] = useState<string[]>([]);
return (
<MultiSelect
{...args}
hasClear
onChange={setValue}
startIcon={Columns3}
value={value}
/>
);
}
<EmptyMultiSelectStory {...args} />
function MultiSelectStory(args: React.ComponentProps<typeof MultiSelect>) {
const [value, setValue] = useState<string[]>(['name', 'email']);
return (
<MultiSelect
{...args}
hasClear
onChange={setValue}
startIcon={Columns3}
value={value}
/>
);
}
<MultiSelectStory {...args} />

Multi-select dropdown field with checkbox-style options.

When isOptional: false, isRequired: false

PropTypeDefaultDescription
children(option: MultiSelectOptionData) => ReactNodeCustom render function for selectable options.
classNamestringAdditional CSS class names applied to the field root.
data-testidstringTest ID applied to the combobox button.
descriptionReactNodeSupporting text displayed below the label.
hasClearbooleanfalseWhether to show a clear button when values are selected.
htmlNamestringHTML name attribute for native form submission. Each selected value is submitted as a separate entry.
hasEntriesOnFocusbooleanfalseWhether focusing the trigger opens the option list. Pointer presses keep their ordinary click-to-toggle behaviour.
hasSearchbooleanfalseWhether to show search input in the dropdown.
hasSelectAllbooleanfalseWhether to show a select-all option.
isDefaultOpenbooleanfalseWhether the selector starts open.
isDisabledbooleanfalseWhether the selector is disabled.
isReadOnlybooleanfalseWhether the values are displayed without allowing focus or interaction.
isLabelHiddenbooleanfalseWhether to visually hide the label.
isLoadingbooleanfalseWhether the selector is loading.
label*stringField label.
labelIconIconComponentIcon shown before the label.
labelTooltipReactNodeTooltip content shown next to the label.
maxBadgesnumber3Maximum number of badges before showing an overflow count.
onChange*(value: string[]) => voidCalled when selection changes.
options*ReadonlyArray<MultiSelectOption>Options to display.
placeholderstring'Select...'Placeholder shown when no values are selected.
refRef<HTMLButtonElement>Ref forwarded to the combobox button.
searchPlaceholderstring'Search...'Search input placeholder.
selectAllLabelstring'Select all'Select-all option label.
size"sm" | "md" | "lg"'md'Select size.
startIconIconComponentStart icon rendered in the trigger.
statusInputStatusValidation status displayed below the selector.
styleCSSPropertiesInline styles applied to the field root.
triggerDisplay"count" | "labels" | "badges"'count'How selected items are summarized in the trigger.
value*string[]Selected option values.
variant"button" | "ghost" | "outline"'outline'Visual style of the selector trigger.
isOptionalfalse
isRequiredfalse

When isOptional: true, isRequired: false

PropTypeDefaultDescription
children(option: MultiSelectOptionData) => ReactNodeCustom render function for selectable options.
classNamestringAdditional CSS class names applied to the field root.
data-testidstringTest ID applied to the combobox button.
descriptionReactNodeSupporting text displayed below the label.
hasClearbooleanfalseWhether to show a clear button when values are selected.
htmlNamestringHTML name attribute for native form submission. Each selected value is submitted as a separate entry.
hasEntriesOnFocusbooleanfalseWhether focusing the trigger opens the option list. Pointer presses keep their ordinary click-to-toggle behaviour.
hasSearchbooleanfalseWhether to show search input in the dropdown.
hasSelectAllbooleanfalseWhether to show a select-all option.
isDefaultOpenbooleanfalseWhether the selector starts open.
isDisabledbooleanfalseWhether the selector is disabled.
isReadOnlybooleanfalseWhether the values are displayed without allowing focus or interaction.
isLabelHiddenbooleanfalseWhether to visually hide the label.
isLoadingbooleanfalseWhether the selector is loading.
label*stringField label.
labelIconIconComponentIcon shown before the label.
labelTooltipReactNodeTooltip content shown next to the label.
maxBadgesnumber3Maximum number of badges before showing an overflow count.
onChange*(value: string[]) => voidCalled when selection changes.
options*ReadonlyArray<MultiSelectOption>Options to display.
placeholderstring'Select...'Placeholder shown when no values are selected.
refRef<HTMLButtonElement>Ref forwarded to the combobox button.
searchPlaceholderstring'Search...'Search input placeholder.
selectAllLabelstring'Select all'Select-all option label.
size"sm" | "md" | "lg"'md'Select size.
startIconIconComponentStart icon rendered in the trigger.
statusInputStatusValidation status displayed below the selector.
styleCSSPropertiesInline styles applied to the field root.
triggerDisplay"count" | "labels" | "badges"'count'How selected items are summarized in the trigger.
value*string[]Selected option values.
variant"button" | "ghost" | "outline"'outline'Visual style of the selector trigger.
isOptional*true
isRequiredfalse

When isOptional: false, isRequired: true

PropTypeDefaultDescription
children(option: MultiSelectOptionData) => ReactNodeCustom render function for selectable options.
classNamestringAdditional CSS class names applied to the field root.
data-testidstringTest ID applied to the combobox button.
descriptionReactNodeSupporting text displayed below the label.
hasClearbooleanfalseWhether to show a clear button when values are selected.
htmlNamestringHTML name attribute for native form submission. Each selected value is submitted as a separate entry.
hasEntriesOnFocusbooleanfalseWhether focusing the trigger opens the option list. Pointer presses keep their ordinary click-to-toggle behaviour.
hasSearchbooleanfalseWhether to show search input in the dropdown.
hasSelectAllbooleanfalseWhether to show a select-all option.
isDefaultOpenbooleanfalseWhether the selector starts open.
isDisabledbooleanfalseWhether the selector is disabled.
isReadOnlybooleanfalseWhether the values are displayed without allowing focus or interaction.
isLabelHiddenbooleanfalseWhether to visually hide the label.
isLoadingbooleanfalseWhether the selector is loading.
label*stringField label.
labelIconIconComponentIcon shown before the label.
labelTooltipReactNodeTooltip content shown next to the label.
maxBadgesnumber3Maximum number of badges before showing an overflow count.
onChange*(value: string[]) => voidCalled when selection changes.
options*ReadonlyArray<MultiSelectOption>Options to display.
placeholderstring'Select...'Placeholder shown when no values are selected.
refRef<HTMLButtonElement>Ref forwarded to the combobox button.
searchPlaceholderstring'Search...'Search input placeholder.
selectAllLabelstring'Select all'Select-all option label.
size"sm" | "md" | "lg"'md'Select size.
startIconIconComponentStart icon rendered in the trigger.
statusInputStatusValidation status displayed below the selector.
styleCSSPropertiesInline styles applied to the field root.
triggerDisplay"count" | "labels" | "badges"'count'How selected items are summarized in the trigger.
value*string[]Selected option values.
variant"button" | "ghost" | "outline"'outline'Visual style of the selector trigger.
isOptionalfalse
isRequired*true