MultiSelect
Multi-select dropdown field with checkbox-style options.
Examples
Section titled “Examples”Default
Section titled “Default”Clear Columns
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} />Searchable
Section titled “Searchable”Clear Columns
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} />Entries On Focus
Section titled “Entries On Focus”function EmptyMultiSelectStory(args: React.ComponentProps<typeof MultiSelect>) { const [value, setValue] = useState<string[]>([]); return ( <MultiSelect {...args} hasClear onChange={setValue} startIcon={Columns3} value={value} /> );}
<EmptyMultiSelectStory {...args} />Trigger Variants
Section titled “Trigger Variants”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} />Badges
Section titled “Badges”Clear Columns
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} />Labels
Section titled “Labels”Clear Columns
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} />Disabled Options
Section titled “Disabled Options”Clear Columns
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} />Sections And Dividers
Section titled “Sections And Dividers”Clear Columns
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} />Disabled
Section titled “Disabled”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} />Loading
Section titled “Loading”Clear Columns
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} />Validation Status
Section titled “Validation Status”Clear Columns
Choose at least one column.
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} />Custom Options
Section titled “Custom Options”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} />With Description And Tooltip
Section titled “With Description And Tooltip”Choose which columns are visible in the table.
Clear Columns
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} />Badge Overflow
Section titled “Badge Overflow”Clear Columns
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} />Select All
Section titled “Select All”function EmptyMultiSelectStory(args: React.ComponentProps<typeof MultiSelect>) { const [value, setValue] = useState<string[]>([]); return ( <MultiSelect {...args} hasClear onChange={setValue} startIcon={Columns3} value={value} /> );}
<EmptyMultiSelectStory {...args} />Read Only
Section titled “Read Only”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} />MultiSelect
Section titled “MultiSelect”Multi-select dropdown field with checkbox-style options.
When isOptional: false, isRequired: false
| Prop | Type | Default | Description |
|---|---|---|---|
children | (option: MultiSelectOptionData) => ReactNode | — | Custom render function for selectable options. |
className | string | — | Additional CSS class names applied to the field root. |
data-testid | string | — | Test ID applied to the combobox button. |
description | ReactNode | — | Supporting text displayed below the label. |
hasClear | boolean | false | Whether to show a clear button when values are selected. |
htmlName | string | — | HTML name attribute for native form submission. Each selected value is submitted as a separate entry. |
hasEntriesOnFocus | boolean | false | Whether focusing the trigger opens the option list. Pointer presses keep their ordinary click-to-toggle behaviour. |
hasSearch | boolean | false | Whether to show search input in the dropdown. |
hasSelectAll | boolean | false | Whether to show a select-all option. |
isDefaultOpen | boolean | false | Whether the selector starts open. |
isDisabled | boolean | false | Whether the selector is disabled. |
isReadOnly | boolean | false | Whether the values are displayed without allowing focus or interaction. |
isLabelHidden | boolean | false | Whether to visually hide the label. |
isLoading | boolean | false | Whether the selector is loading. |
label* | string | — | Field label. |
labelIcon | IconComponent | — | Icon shown before the label. |
labelTooltip | ReactNode | — | Tooltip content shown next to the label. |
maxBadges | number | 3 | Maximum number of badges before showing an overflow count. |
onChange* | (value: string[]) => void | — | Called when selection changes. |
options* | ReadonlyArray<MultiSelectOption> | — | Options to display. |
placeholder | string | 'Select...' | Placeholder shown when no values are selected. |
ref | Ref<HTMLButtonElement> | — | Ref forwarded to the combobox button. |
searchPlaceholder | string | 'Search...' | Search input placeholder. |
selectAllLabel | string | 'Select all' | Select-all option label. |
size | "sm" | "md" | "lg" | 'md' | Select size. |
startIcon | IconComponent | — | Start icon rendered in the trigger. |
status | InputStatus | — | Validation status displayed below the selector. |
style | CSSProperties | — | Inline 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 | false | — | |
isRequired | false | — |
When isOptional: true, isRequired: false
| Prop | Type | Default | Description |
|---|---|---|---|
children | (option: MultiSelectOptionData) => ReactNode | — | Custom render function for selectable options. |
className | string | — | Additional CSS class names applied to the field root. |
data-testid | string | — | Test ID applied to the combobox button. |
description | ReactNode | — | Supporting text displayed below the label. |
hasClear | boolean | false | Whether to show a clear button when values are selected. |
htmlName | string | — | HTML name attribute for native form submission. Each selected value is submitted as a separate entry. |
hasEntriesOnFocus | boolean | false | Whether focusing the trigger opens the option list. Pointer presses keep their ordinary click-to-toggle behaviour. |
hasSearch | boolean | false | Whether to show search input in the dropdown. |
hasSelectAll | boolean | false | Whether to show a select-all option. |
isDefaultOpen | boolean | false | Whether the selector starts open. |
isDisabled | boolean | false | Whether the selector is disabled. |
isReadOnly | boolean | false | Whether the values are displayed without allowing focus or interaction. |
isLabelHidden | boolean | false | Whether to visually hide the label. |
isLoading | boolean | false | Whether the selector is loading. |
label* | string | — | Field label. |
labelIcon | IconComponent | — | Icon shown before the label. |
labelTooltip | ReactNode | — | Tooltip content shown next to the label. |
maxBadges | number | 3 | Maximum number of badges before showing an overflow count. |
onChange* | (value: string[]) => void | — | Called when selection changes. |
options* | ReadonlyArray<MultiSelectOption> | — | Options to display. |
placeholder | string | 'Select...' | Placeholder shown when no values are selected. |
ref | Ref<HTMLButtonElement> | — | Ref forwarded to the combobox button. |
searchPlaceholder | string | 'Search...' | Search input placeholder. |
selectAllLabel | string | 'Select all' | Select-all option label. |
size | "sm" | "md" | "lg" | 'md' | Select size. |
startIcon | IconComponent | — | Start icon rendered in the trigger. |
status | InputStatus | — | Validation status displayed below the selector. |
style | CSSProperties | — | Inline 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 | — | |
isRequired | false | — |
When isOptional: false, isRequired: true
| Prop | Type | Default | Description |
|---|---|---|---|
children | (option: MultiSelectOptionData) => ReactNode | — | Custom render function for selectable options. |
className | string | — | Additional CSS class names applied to the field root. |
data-testid | string | — | Test ID applied to the combobox button. |
description | ReactNode | — | Supporting text displayed below the label. |
hasClear | boolean | false | Whether to show a clear button when values are selected. |
htmlName | string | — | HTML name attribute for native form submission. Each selected value is submitted as a separate entry. |
hasEntriesOnFocus | boolean | false | Whether focusing the trigger opens the option list. Pointer presses keep their ordinary click-to-toggle behaviour. |
hasSearch | boolean | false | Whether to show search input in the dropdown. |
hasSelectAll | boolean | false | Whether to show a select-all option. |
isDefaultOpen | boolean | false | Whether the selector starts open. |
isDisabled | boolean | false | Whether the selector is disabled. |
isReadOnly | boolean | false | Whether the values are displayed without allowing focus or interaction. |
isLabelHidden | boolean | false | Whether to visually hide the label. |
isLoading | boolean | false | Whether the selector is loading. |
label* | string | — | Field label. |
labelIcon | IconComponent | — | Icon shown before the label. |
labelTooltip | ReactNode | — | Tooltip content shown next to the label. |
maxBadges | number | 3 | Maximum number of badges before showing an overflow count. |
onChange* | (value: string[]) => void | — | Called when selection changes. |
options* | ReadonlyArray<MultiSelectOption> | — | Options to display. |
placeholder | string | 'Select...' | Placeholder shown when no values are selected. |
ref | Ref<HTMLButtonElement> | — | Ref forwarded to the combobox button. |
searchPlaceholder | string | 'Search...' | Search input placeholder. |
selectAllLabel | string | 'Select all' | Select-all option label. |
size | "sm" | "md" | "lg" | 'md' | Select size. |
startIcon | IconComponent | — | Start icon rendered in the trigger. |
status | InputStatus | — | Validation status displayed below the selector. |
style | CSSProperties | — | Inline 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 | false | — | |
isRequired* | true | — |