Getting StartedComponentsDesign TokensThemingTheme SynthesizerFrameworksAccessibilityUtilitiesServer RenderingBrowser SupportContributingChangelog App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip
ARC UI ARC Radiant Components
v3.2 Docs Components Tokens Synthesizer
Getting StartedFrameworksServer Rendering Design TokensThemingTheme SynthesizerTypographyUtilities All ComponentsAccessibilityBrowser SupportChangelogContributingStats App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip

Multi Select

Multi-value select with tag chips, inline search filtering, and keyboard navigation.

Components Multi Select
input interactive
<arc-multi-select>

Overview

MultiSelect is a form control that allows users to choose multiple values from a predefined list of options. Selected items appear as removable tag chips inside the control, giving clear visual feedback about what has been chosen. The inline text input doubles as a filter — typing narrows the dropdown to matching options, making it efficient even with large option sets. Options are provided declaratively using `<arc-option>` child elements, each with a `value` and visible label. The dropdown opens on focus and filters in real time as the user types. Items can be toggled on and off by clicking or via keyboard navigation with ArrowUp/ArrowDown and Enter. Pressing Backspace when the text input is empty removes the last selected tag, providing a natural editing flow. MultiSelect fires an `arc-change` event whenever the selection changes, with the current value array in the event detail. The component handles outside-click dismissal automatically and exposes CSS parts for `control`, `tag`, `input`, `dropdown`, and `option` to support targeted style customisation.

Guidelines

When to use

  • Always provide a `label` so the field is accessible to screen readers
  • Use a descriptive `placeholder` to hint at expected input, such as "Choose languages..."
  • Keep option labels concise so they display well as tags inside the control
  • Listen to `arc-change` to react to selection changes and keep external state in sync
  • Pre-populate the `value` array when editing existing records to show current selections

When not to use

  • Do not use MultiSelect when only a single value is needed — use Select instead
  • Do not provide more than ~50 options without also considering server-side filtering via arc-change
  • Do not use extremely long option labels — they will overflow the tag chips and the dropdown
  • Do not set both `disabled` and a pre-selected `value` without a clear visual explanation of why editing is blocked
  • Avoid nesting MultiSelect inside a popover or modal without testing z-index stacking for the dropdown

Features

  • Selected values rendered as removable pill-shaped tag chips inside the control area
  • Inline type-ahead filtering that narrows the dropdown options in real time
  • Full keyboard navigation: ArrowUp/Down to move, Enter to select, Escape to close, Backspace to remove the last tag
  • Check marks next to already-selected options in the dropdown for clear state indication
  • Declarative options via `<arc-option>` child elements with `value` and `label` attributes
  • Automatic outside-click dismissal of the dropdown panel
  • Focus glow on the control using the shared `--focus-glow` design token
  • "No results found" empty state when the filter query matches no options

Preview

React Vue Angular Svelte Lit

Usage

This component requires JavaScript. No pure HTML/CSS version is available — use the Web Component directly or a framework wrapper.

<arc-multi-select label="Languages" placeholder="Choose...">
  <arc-option value="js">JavaScript</arc-option>
  <arc-option value="ts">TypeScript</arc-option>
  <arc-option value="py">Python</arc-option>
</arc-multi-select>
import { MultiSelect, Option } from '@arclux/arc-ui-react';

export default function Example() {
  return (
    <MultiSelect label="Languages" placeholder="Choose...">
      <Option value="js">JavaScript</Option>
      <Option value="ts">TypeScript</Option>
      <Option value="py">Python</Option>
    </MultiSelect>
  );
}
<script setup>
import { MultiSelect, Option } from '@arclux/arc-ui-vue';
</script>

<template>
  <MultiSelect label="Languages" placeholder="Choose...">
    <Option value="js">JavaScript</Option>
    <Option value="ts">TypeScript</Option>
    <Option value="py">Python</Option>
  </MultiSelect>
</template>
<script>
  import { MultiSelect, Option } from '@arclux/arc-ui-svelte';
</script>

<MultiSelect label="Languages" placeholder="Choose...">
  <Option value="js">JavaScript</Option>
  <Option value="ts">TypeScript</Option>
  <Option value="py">Python</Option>
</MultiSelect>
import { Component } from '@angular/core';
import { MultiSelect, Option } from '@arclux/arc-ui-angular';

@Component({
  imports: [MultiSelect, Option],
  template: `
    <arc-multi-select label="Languages" placeholder="Choose...">
      <arc-option value="js">JavaScript</arc-option>
      <arc-option value="ts">TypeScript</arc-option>
      <arc-option value="py">Python</arc-option>
    </arc-multi-select>
  `,
})
export class MyComponent {}
import { MultiSelect, Option } from '@arclux/arc-ui-solid';

export default function Example() {
  return (
    <MultiSelect label="Languages" placeholder="Choose...">
      <Option value="js">JavaScript</Option>
      <Option value="ts">TypeScript</Option>
      <Option value="py">Python</Option>
    </MultiSelect>
  );
}
import { MultiSelect, Option } from '@arclux/arc-ui-preact';

export default function Example() {
  return (
    <MultiSelect label="Languages" placeholder="Choose...">
      <Option value="js">JavaScript</Option>
      <Option value="ts">TypeScript</Option>
      <Option value="py">Python</Option>
    </MultiSelect>
  );
}

API

size 'sm' | 'md' | 'lg' 'md'
Control size. `md` is the default; `sm` and `lg` scale the control height and padding.
value string[] []
Array of selected option values. Updated when items are toggled and emitted via `arc-change`.
placeholder string ''
Hint text shown inside the control when no items are selected and the input is empty.
label string ''
Visible label rendered above the control in a small uppercase style.
name string ''
disabled boolean false
Disables the control, preventing interaction and reducing opacity to 50%.
readonly boolean false
Prevents toggling options or removing chips while the control stays focusable; the dropdown can still be opened for viewing and the values still submit.
formAssociated boolean true
properties object { required: { type: Boolean, reflect: true }, readonly: { type: Boolean, reflect: true }, }
Lit merges static properties up the prototype chain, so every consumer gets these without declaring them. `required` participates in constraint validation below; `readonly` reflects for styling and is enforced by each component's interaction handlers (the mixin can't know which gestures mutate state).
autoValidates boolean true
Components that run their own constraint-validation logic (pattern checks, range checks) opt out of the automatic required sync by overriding this to false, and own the whole validity flag set instead.
form
validity
validationMessage
required boolean false

Events

arc-change detail: { value: string[] }
Fired when the selected values change
arc-input detail: { value: string }
Fired on every keystroke in the filter input. `event.detail.value` contains the current query text.

See Also