Multi Select
MultiSelect is Brick's styled multiple-value choice control. It is built directly on Atom MultiSelect 0.10.1: Atom owns the value array, open state, option registration, keyboard/typeahead, focus, dismissal, positioning, ARIA, native form participation, validation, and reset. Brick owns the complete visual system and default decorative artwork.
Built from the published package
Know when Multi Select is the right part
Use it when
Use MultiSelect when people may choose several values from a predefined list that should remain compact until opened. It supports grouped and disabled options, native forms, Field messages, and keyboard typeahead.
Choose another path when
Use Checkbox Group for a short multiple-choice set that should remain visible, Select or Radio Group when exactly one value is required, Combobox when users must filter or enter text, and Dropdown Menu for actions. Options must not contain interactive descendants.
Installation and imports
The complete stylesheet above is the recommended default. For a measured route-aware build, replace it with the shared foundation and this component's stylesheet:
Add the modular stylesheet for every other Brick component the route renders.
Do not combine modular styles with styles.css or tokens.css.
Both entrypoints export MultiSelect, MultiSelectRoot, MultiSelectTrigger, MultiSelectValue,
MultiSelectIcon, MultiSelectPortal, MultiSelectContent, MultiSelectListbox,
MultiSelectViewport, MultiSelectScrollUpButton, MultiSelectScrollDownButton,
MultiSelectGroup, MultiSelectLabel, MultiSelectItem, MultiSelectItemText,
MultiSelectItemIndicator, MultiSelectSeparator, and MultiSelectArrow. Public types are
MultiSelectRootProps, MultiSelectTriggerProps, MultiSelectValueProps, MultiSelectIconProps,
MultiSelectPortalProps, MultiSelectContentProps, MultiSelectListboxProps,
MultiSelectViewportProps, MultiSelectScrollUpButtonProps,
MultiSelectScrollDownButtonProps, MultiSelectGroupProps, MultiSelectLabelProps,
MultiSelectItemProps, MultiSelectItemTextProps, MultiSelectItemIndicatorProps,
MultiSelectSeparatorProps, MultiSelectArrowProps, MultiSelectVariant, MultiSelectSize, and
MultiSelectShape.
Quick start
Placeholder text is a hint, not an accessible label. Use Field.Label or an
explicit ARIA label.
Visual recipes and states
outlineuses a raised surface and strong complete border.softuses a subtle fill and restrained border.underlineuses a transparent surface and bottom line.sm,md, andlguse 36px, 44px, and 52px minimum trigger and option-row heights.sharp,rounded, andpillchange Trigger geometry only.
The popup and options do not change with Trigger variant. Atom's data state drives open, highlighted, selected, disabled, read-only, and invalid paint. State changes never alter control or item geometry. Value text truncates before it can displace Icon; ItemIndicator owns one fixed logical-end column.
Field, forms, and validation
Compose MultiSelect inside Field for the visible label, description, required
marker, and error. Atom's aligned native multi-select remains the submission,
required-validity, external form, and reset proxy. Do not add hidden inputs
or reproduce validation in application code.
Controlled and uncontrolled value/open state are both supported. Native form
behavior remains unchanged by Brick visual props; Brick size is control
geometry and never the native multi-select's numeric size attribute.
Groups, scrolling, portal, and Arrow
Place Label and Items inside Group to expose an accessible option group. Use Separator between authored groups. Viewport owns option scrolling; the conditional scroll buttons are specialized MultiSelect controls and are not a generic Scroll Area replacement.
Content portals and positions itself by default. Portal may provide an explicit
portal owner, and Content supports Atom's custom container or
disablePortal behavior. Arrow must be inside Content and follows its
collision-resolved data-side and data-align.
Examples
See the /multi-select playground route for recipes, states, long scrolling groups,
forms, composition, appearance, customization, RTL, and responsive evidence.
Exclusions
MultiSelect intentionally has no single-value mode, flat items API, editable search,
arbitrary tone, consumer placement API, virtualization, async/loading state,
option creation, or automatic mobile sheet. Those require separate component
contracts.
API
Start with the public parts and root options below. Components with multiple parts separate each area into its own named subsection.
Root recipes
| Prop | Values | Default |
|---|---|---|
variant | outline, soft, underline | outline |
size | sm, md, lg | md |
shape | sharp, rounded, pill | rounded |
fullWidth | boolean | true |
underline has fixed sharp geometry and does not accept shape. Root also
forwards Atom's array-valued value, defaultValue, and onValueChange, plus open,
defaultOpen, onOpenChange, disabled, readOnly, invalid, required,
name, form, and validationBehavior.
Parts and artwork
Every DOM-owning part preserves native props, events, ARIA, data-*,
className, style, slot override, and its exact ref. Icon,
ItemIndicator, ScrollUpButton, ScrollDownButton, and Arrow provide decorative
Brick artwork when children are omitted. Supplying children replaces that
artwork; consumers then own its semantics.
ItemText should wrap each option's primary visible label because Atom uses it
for the displayed value and accessible option name. Item may contain additional
decorative content, but never nested controls.
Accessibility
Every MultiSelect requires an accessible name. Atom owns the button trigger, multiple-selection listbox semantics, expanded state, group relationships, active option focus, typeahead, multi-selection, Escape/Tab dismissal, focus return, touch-safe outside dismissal, portal ownership, and native form semantics.
Brick preserves visible keyboard focus and distinct highlighted, selected, disabled, read-only, and invalid states in light, dark, reduced-motion, and forced-color modes. Decorative artwork is hidden from accessibility APIs.
Responsive behavior
MultiSelect uses logical spacing, constrained popup width/height, long-label wrapping in options, and trigger truncation. It stays within narrow viewports, supports 200%/400% zoom, and reverses logical placement in RTL. Brick does not add responsive prop objects or an automatic mobile sheet.
Styling and tokens
Customization
Use recipe props first, semantic tokens for system changes, then MultiSelect variables or part class/style for a scoped change:
Do not target private SVG paths, Floating UI inline coordinates, the hidden form proxy, or Atom internals.
Tokens and CSS hooks
Stable classes and the overridable data-slot hooks are listed in
Anatomy and DOM ownership. Trigger exposes
data-variant, data-size, data-shape, and data-full-width; Atom state and
placement attributes remain intact.
Public variables include:
--brick-multi-select-trigger-min-block-size,--brick-multi-select-trigger-padding-inline,--brick-multi-select-trigger-gap,--brick-multi-select-trigger-radius;--brick-multi-select-trigger-font-family,--brick-multi-select-trigger-font-size,--brick-multi-select-trigger-font-weight,--brick-multi-select-trigger-line-height,--brick-multi-select-trigger-letter-spacing;--brick-multi-select-trigger-background,--brick-multi-select-trigger-foreground,--brick-multi-select-trigger-placeholder,--brick-multi-select-trigger-border,--brick-multi-select-trigger-hover-background,--brick-multi-select-trigger-hover-border,--brick-multi-select-trigger-focus-ring,--brick-multi-select-trigger-invalid-border;--brick-multi-select-trigger-disabled-background,--brick-multi-select-trigger-disabled-foreground,--brick-multi-select-trigger-disabled-border,--brick-multi-select-trigger-readonly-background;--brick-multi-select-icon-size,--brick-multi-select-icon-foreground;--brick-multi-select-content-background,--brick-multi-select-content-foreground,--brick-multi-select-content-border,--brick-multi-select-content-radius,--brick-multi-select-content-shadow,--brick-multi-select-content-max-block-size,--brick-multi-select-content-padding,--brick-multi-select-content-z-index;--brick-multi-select-item-min-block-size,--brick-multi-select-item-padding-inline,--brick-multi-select-item-gap,--brick-multi-select-item-highlighted-background,--brick-multi-select-item-selected-foreground,--brick-multi-select-item-disabled-foreground;--brick-multi-select-indicator-size,--brick-multi-select-label-foreground,--brick-multi-select-separator-color,--brick-multi-select-scroll-button-block-size, and--brick-multi-select-arrow-size.
Advanced reference
Open these details only when you need to inspect DOM ownership, native forwarding, or lower-level composition.