# MultiSelect A built-in tag for picking several options at once. Each chosen value shows as a removable [Pill](/components/combobox/pill/) inside the input, and the value is a list. Options come through `data` (the same convention as [Select](/components/combobox/select/) — a comma-separated list or `value::label` pairs). It hydrates into a fully interactive Mantine input in the browser. Use it as `{% multiselect %}` in Markdown, or call it from Python logic (loops, snippets) via `component('aardvark', 'multiselect', …)`. ## Basic multiselect A `label`, a `placeholder`, and a comma-separated `data` list. `searchable` lets the reader filter; `clearable` shows an × to drop all selections:
Source: Markdown ```aardvark {% multiselect label='Stack' placeholder='Pick a few' data='React, Vue, Svelte, Angular, Solid' searchable=true clearable=true %} ``` Source: Python ```python component('aardvark', 'multiselect', label='Stack', placeholder='Pick a few', data='React, Vue, Svelte, Angular, Solid', searchable=True, clearable=True) ``` ## value::label pairs with a default value `value::label` pairs (a double colon) give each option a stored value and a display label. `defaultValue` is a comma-separated list of values pre-selected on load:
Source: Markdown ```aardvark {% multiselect label='Languages' data='js::JavaScript, ts::TypeScript, py::Python, go::Go' defaultValue='ts, py' %} ``` Source: Python ```python component('aardvark', 'multiselect', label='Languages', data='js::JavaScript, ts::TypeScript, py::Python, go::Go', defaultValue='ts, py') ``` ## Grouped options with dataJson For grouped, disabled, or richer options pass a full JSON array through `dataJson` — a list of `{group, items}` objects. `dataJson` wins over `data`:
Source: Markdown ```aardvark {% multiselect label='Tooling' searchable=true dataJson='[{"group":"Build","items":["Vite","esbuild","Webpack"]},{"group":"Test","items":["Vitest","Jest","Playwright"]}]' %} ``` Source: Python ```python component('aardvark', 'multiselect', label='Tooling', searchable=True, dataJson='[{"group":"Build","items":["Vite","esbuild","Webpack"]},' '{"group":"Test","items":["Vitest","Jest","Playwright"]}]') ``` ## Limiting and hiding picked options `maxValues` caps how many can be chosen — once full, the rest are disabled. `hidePickedOptions` drops an option from the dropdown once it's selected:
Source: Markdown ```aardvark {% multiselect label='Pick up to 2' data='Red, Green, Blue, Yellow' maxValues=2 %} {% multiselect label='Toppings' data='Cheese, Mushroom, Olive, Onion' hidePickedOptions=true clearable=true %} ``` Source: Python ```python component('aardvark', 'multiselect', label='Pick up to 2', data='Red, Green, Blue, Yellow', maxValues=2) component('aardvark', 'multiselect', label='Toppings', data='Cheese, Mushroom, Olive, Onion', hidePickedOptions=True, clearable=True) ``` ## With other components A multiselect fits inside a [card](/components/data-display/card/) alongside other content — here a [text](/components/typography/text/) lead-in above the field: Select the frameworks your project uses.
Source: Markdown ```aardvark {% card %} {% text size='sm' c='dimmed' %}Select the frameworks your project uses.{% endText %} {% multiselect label='Frameworks' placeholder='Add a few' data='React, Vue, Svelte, Angular, Solid' searchable=true clearable=true %} {% endCard %} ``` Source: Python ```python component('aardvark', 'card', children=( component('aardvark', 'text', children='Select the frameworks your project uses.', size='sm', c='dimmed') + component('aardvark', 'multiselect', label='Frameworks', placeholder='Add a few', data='React, Vue, Svelte, Angular, Solid', searchable=True, clearable=True) )) ``` ## Attributes Every attribute is optional; omit one to take its Mantine default. The body is ignored — `multiselect` is a form control, not a container. | Attribute | Valid values | Description | | --- | --- | --- | | `data` | Comma-separated list, or `value::label` pairs (double colon) | The options. A bare item is both value and label; `value::label` carries a separate stored value. A single `:` is left intact. | | `dataJson` | JSON array string | A full options array — plain strings, `{value, label}` objects, `{group, items}` groups, and disabled flags. Wins over `data` when both are set. | | `defaultValue` | Comma-separated list of values from `data` | The options selected on load. | | `maxValues` | Integer | Cap the number of selections; further options are disabled once full. | | `label` | String | The field label. | | `placeholder` | String | Empty-state text inside the input. | | `description` | String | Helper text below the label. | | `error` | String | Validation message; also styles the field red. | | `size` | `xs`, `sm`, `md`, `lg`, `xl` | Input size. | | `radius` | `xs`, `sm`, `md`, `lg`, `xl` | Corner radius. | | `variant` | `default`, `filled`, `unstyled` | Input style. | | `searchable` | `true`, `false` (default `false`) | Let the reader filter options by typing. | | `clearable` | `true`, `false` (default `false`) | Show an × to clear all selections. | | `hidePickedOptions` | `true`, `false` (default `false`) | Remove an option from the dropdown once it's picked. | | `disabled` | `true`, `false` (default `false`) | Disable the input. | | `required` | `true`, `false` (default `false`) | Mark the field required. | | `withAsterisk` | `true`, `false` (default `false`) | Show the required asterisk on the label. | | `withCheckIcon` | `true`, `false` (default `true`) | Show the check mark on a selected option. | | `checkIconPosition` | `left`, `right` | Which side the check mark sits on. | | `withScrollArea` | `true`, `false` (default `true`) | Wrap a long dropdown in a scroll area. | | `nothingFoundMessage` | String | Text shown when a search matches nothing. | | `maxDropdownHeight` | Integer (px) | Cap the dropdown height. | ## CSS Selectors Target the rendered element through its island marker — `[data-aardvark-island="MultiSelect"]` — or through the Mantine Styles API classes (`.mantine-MultiSelect-root` and its inner parts): ```css /* Every rendered MultiSelect carries this island marker */ [data-aardvark-island="MultiSelect"] { } /* Mantine Styles API class on the root element */ .mantine-MultiSelect-root { } .mantine-MultiSelect-input { } .mantine-MultiSelect-pill { } .mantine-MultiSelect-label { } ``` ## Injecting Attributes `attr={…}` forwards raw HTML attributes — including event handlers — straight onto the rendered element, so you can wire DOM behavior the tag does not expose. The handler can be a full multi-line script, not just one expression — here it is wired to `onchange` on the search box, so typing to filter logs the text you type to the console and alerts it — selecting items is React state and fires no DOM `change` event:
Source: Markdown ```aardvark {% multiselect label='Stack' placeholder='Pick a few' data='React, Vue, Svelte, Angular, Solid' searchable=true clearable=true attr={'onchange': ''' const value = this.value; console.log('attr demo value:', value); alert(value); '''} %} ``` Source: Python ```python component('aardvark', 'multiselect', label='Stack', placeholder='Pick a few', data='React, Vue, Svelte, Angular, Solid', searchable=True, clearable=True, attr={'onchange': ''' const value = this.value; console.log('attr demo value:', value); alert(value); '''}) ```