• CMSnpm version

    • Overview
    • ContentBuilder
    • InviteUserForm
    • LoginForm
    • RenewPasswordForm
    • WysiwygInput
  • UInpm version

    • Overview
    • Accordion
    • AlertBubble
    • AnnouncementBar
    • Avatar
    • AvatarFileInput
    • Badge
    • Button
    • ButtonGroup
    • ButtonList
    • Calendar
    • Checkbox
    • CheckboxButton
    • CheckboxInput
    • CheckboxList
    • Chip
    • ColorRadio
    • ColorRadioGroup
    • Combobox
    • DatePicker
    • DatePickerInput
    • DateRangePicker
    • DateRangePickerInput
    • DatetimePicker
    • DatetimePickerInput
    • Dialog
    • Dropdown
    • Dropzone
    • ErrorMessage
    • FileInput
    • FlashMessages
    • FormComponent
    • Icon
    • IconButton
    • ImageGallery
    • InfoBox
    • Input
    • Label
    • Layout
    • Lightbox
    • ListItem
    • Loader
    • Lozenge
    • Menu
    • Message
    • Modal
    • ✅ ModalDialog
    • ✅ ModalHeader
    • MultiCombobox
    • MultiSelect
    • Pagination
    • Paper
    • Popover
    • Radio
    • RadioGroup
    • RasterImage
    • Select
    • Switch
    • ✅ Tabs
    • TextInput
    • TextLink
    • Textarea
    • TimePicker
    • TimePickerInput
    • Toggle
    • Tooltip
    • Typography
  • Formnpm version

    • Overview
    • AvatarFileInput
    • CheckboxButton
    • CheckboxInput
    • CheckboxList
    • ColorRadioGroup
    • Combobox
    • DatePickerInput
    • DateRangePickerInput
    • DatetimePickerInput
    • Dropzone
    • FileInput
    • Form
    • FormRenderer
    • GpsInput
    • MoneyInput
    • MultiCombobox
    • MultiSelect
    • NumberInput
    • PasswordInput
    • RadioGroup
    • Select
    • TextInput
    • Textarea
    • TimePickerInput
    • Toggle
  • DataGridnpm version

    • Overview
    • DataGrid
    • DataGridCustomExample
    • ExportButton
    • FilterList
    • Filters
    • FiltersButton
    • FulltextInput
    • HiddenColumns
    • HiddenColumnsButton
    • Pagination
    • RowCounts
    • RowsPerPageSelect
    • SelectedRowsToolbar
    • TableV2
    • ToolbarControl
    • ToolbarCustoms
    • ToolbarTabs
  • Wysiwygnpm version

    • Overview
  • Resizernpm version

    • Overview
  • Routernpm version

    • Overview
  • Corenpm version

    • Overview
  • Core-Reactnpm version

    • Overview
  • DnDnpm version

    • Overview
  • Stylesnpm version

    • Overview
  • Localizenpm version

    • Overview
  • Analyticsnpm version

    • Overview
  • Datepickernpm version

    • Overview
  • Icons-generatornpm version

    • Overview
  • Smart-addressnpm version

    • Overview
  • E2Enpm version

    • Overview
  • E2E-Playwrightnpm version

    • Overview
View source on GitLab

MultiSelect

Multi-value dropdown picker built on Base UI Select in multiple mode. Selected values render as removable chips; the option list is fixed (no text filtering).

When to use

Reach for MultiSelect when the user picks several values from a fixed list and no text filtering is needed.

  • Need to filter options by typing? Use MultiCombobox.
  • Only one value? Use Select.

Use @uxf/ui/multi-select for a controlled component outside a form. Inside a @uxf/form form, use @uxf/form/multi-select instead — it registers the field with react-hook-form and derives isInvalid / helperText from validation. This @uxf/ui component is the controlled primitive the form twin wraps.

Usage

import { MultiSelect, MultiSelectOption, MultiSelectValue } from "@uxf/ui/multi-select";
import { useState } from "react";

const options: MultiSelectOption<string>[] = [
    { color: "red", id: "one", label: "Option red" },
    { color: "blue", id: "two", label: "Option blue" },
    { disabled: true, id: "three", label: "Option three" },
];

function Example() {
    const [value, setValue] = useState<MultiSelectValue<string>>(null);

    return (
        <MultiSelect
            label="Choose options"
            name="example"
            onChange={setValue}
            options={options}
            placeholder="Select..."
            value={value}
        />
    );
}

value is an array of ids (MultiSelectValue<T> = T[] | null) — not option objects — and onChange receives the new array of ids, always in canonical (sorted) order rather than in click order (see Value order). Selected chips can be removed with their close button or by pressing Backspace.

Exports: MultiSelect and the types MultiSelectProps, MultiSelectOption, MultiSelectValue, MultiSelectValueId (deprecated alias of SelectableId), MultiSelectTypeRef.

Props

MultiSelectProps<ValueId = SelectableId, Option = MultiSelectOption<ValueId>> extends FormControlProps<ValueId[] | null>. SelectableId is string | number (from @uxf/core/types); MultiSelectOption is { id: ValueId; label: ReactNode; color?: ChipColor; disabled?: boolean }. It is not Clearable — there is no isClearable prop.

PropTypeDefaultDescription
labelReactNode—Required. Field label.
namestring—Required. Field name (also set as data-name).
valueValueId[] | null—Required. Selected option ids, or null.
onChange(value: ValueId[]) => void—Required. Called with the new array of selected ids, in canonical (sorted) order.
optionsOption[]—Required. Selectable options.
withCheckboxesbooleanfalseRender options as a checkbox list (keeps selected options visible in the list).
placeholderstring—Shown when nothing is selected.
helperTextReactNode—Text under the control; styled as an error when isInvalid.
isDisabledbooleanfalseDisable the control.
isReadOnlybooleanfalsePrevent changes while staying focusable.
isInvalidbooleanfalseInvalid styling; sets aria-invalid and styles helperText as an error.
isRequiredbooleanfalseMark the field required (adds the label indicator).
hiddenLabelbooleanfalseVisually hide the label (kept for assistive tech).
renderOption(option: Option) => ReactNodeoption.labelCustom renderer for each dropdown option (ignored when withCheckboxes).
keyExtractor(option: Option) => string | numberoption.idCustom React key for options.
noOptionsMessagestringlocalized "No items found"Empty-list message.
allOptionsSelectedMessagestringlocalized "All options are already selected"Shown when every option is selected.
iconNameIconName"caretDown"Icon for the dropdown arrow.
sizeInputGroupSize"default""small", "default", or "large".
variantInputGroupVariant"default"Input group variant.
idstringauto (useId)Root id; the error-message id derives from it.
onBlur / onFocusFocusEventHandler<HTMLInputElement>—Focus handlers.

The component is a forwardRef — the ref points at the trigger <div> (MultiSelectTypeRef = HTMLDivElement). Layout/dropdown props: className, style, form, leftAddon, rightAddon, leftElement, rightElement, inputArrow, dropdownClassName, dropdownMatchesInputWidth, dropdownMaxHeight (default 240), dropdownPlacement (default "bottom"), dropdownStrategy.

Value order

The value is semantically a set, and the emitted array is always sorted by id (normalizeSelectableIds) rather than kept in click order. Rendering is unaffected — the chips render from the options-ordered selection, never from the value order.

This matters for react-hook-form: it compares arrays index by index, so a click-ordered value made a form read as dirty after an option was deselected and selected again. The component can only canonicalize what it emits, so run your defaultValues through the same helper:

const formApi = useForm<FormData>({ defaultValues: { tags: normalizeSelectableIds(data.tagIds) } });

If you submit this value somewhere order-sensitive, note that the payload order changed.

Variants & states

  • Checkbox mode: withCheckboxes renders each option as a checkbox and keeps selected options in the list rather than hiding them.
  • Chips: each selected value is a Chip; its color comes from the option's color. Chips are removable unless the control or the option is disabled.
  • Sizes: small, default, large (via size).
  • Invalid / disabled / read-only: as with the other form controls (isInvalid, isDisabled, isReadOnly).
  • No search: unlike the combobox family there is no text input; the option list is static.

Requirements

The component composes the input, label, dropdown, form-component, icon, and chip primitives, so import their stylesheets once in your global CSS:

@import url("@uxf/ui/css/icon.css");
@import url("@uxf/ui/css/dropdown.css");
@import url("@uxf/ui/css/label.css");
@import url("@uxf/ui/css/form-component.css");
@import url("@uxf/ui/css/input-basic.css");
@import url("@uxf/ui/css/input.css");
@import url("@uxf/ui/css/chip.css");
@import url("@uxf/ui/css/multi-select.css");

When using withCheckboxes, also import the checkbox stylesheets:

@import url("@uxf/ui/css/checkbox.css");
@import url("@uxf/ui/css/checkbox-input.css");

Also requires the global @uxf/ui token layer, set up once per app — see @uxf/ui setup.

Default
Open in new tab
OnlyForE2ETests
Open in new tab
Sizes
Open in new tab
States
Open in new tab