Advanced multi-select

Picks many items from a large, grouped list, with search, select-all and a running count.

Live React portVue source: WildAdvancedMultiSelectDropdown.vueStorybook story: Dropdowns/Advanced Multi-Select

Try it

Search for “bore”, then tick one site in a group and watch its group and client go mixed.

Size
Chips
Disabled
<WildAdvancedMultiSelectDropdown
  v-model="chosen"
  :nodes="sites"
/>

When to use

  • Use it to choose many sites from a list grouped by client and group.
  • Use it when people pick whole groups at once, such as every site a client owns.
Don’t use it
  • For a flat list, or a single choice. Use Search select.
  • For a few options that should all stay visible. Use Checkbox.

Anatomy

  • Trigger: the placeholder, a count of selected sites, or the select-all label.
  • Search: filters as you type, and opens each match’s client and group.
  • Select all: ticks or clears every site.
  • Tree: clients, groups and sites, each with a checkbox.
  • Chips: one per top-level client or site with a selection, each removable.

Selection

Ticking a client or group ticks every site under it. When only some are ticked, its box shows mixed, and so does Select all.

Orchard Holdings · 2/5Canterbury Ag
<WildAdvancedMultiSelectDropdown v-model="chosen" :nodes="sites" />
A fully selected client shows as a blue chip. A part-selected one counts its own sites, here 2/5.

Sizes

Three heights. The default is sm, at 36px.

sm · 36
md · 40
lg · 44
<WildAdvancedMultiSelectDropdown :nodes="sites" />
<WildAdvancedMultiSelectDropdown size="md" :nodes="sites" />
<WildAdvancedMultiSelectDropdown size="lg" :nodes="sites" />

States

Disabled dims the trigger to 40% and locks its chips.

none
some
all
disabled

Content

  • Name the items in placeholder and allItemsLabel when they aren’t sites.
  • Keep labels short. Long ones end in an ellipsis.

Accessibility

The trigger announces the summary it shows. Each tree row announces its level and whether it’s checked, unchecked or mixed.

KeyWhat it does
Enter / SpaceOn the trigger, opens or closes the panel. On Select all or a row, ticks or clears every site it covers.
TabMoves through search, Select all and the tree. Tabbing out closes the panel.
↓ / ↑Moves between visible rows, and ↓ from the search into the tree.
→Opens a client or group, or moves to its first child.
←Closes a client or group, or moves to its parent.
Home / EndFirst or last visible row.
EscapeCloses the panel and returns focus to the trigger.

Props

PropTypeDefaultDescription
nodesTreeNode[]—{ id, label, children? }, nested to any depth.
v-modelSelectionOutput—The ticked sites: { mode, selectedNodeIds, selectedLeafIds }.
placeholderstring'Select sites...'Trigger text when nothing is selected.
allItemsLabelstring'All Sites'Select-all row, and the trigger when all are selected.
size'sm' | 'md' | 'lg''sm'Trigger height: 36, 40 or 44px.
showChipsbooleantrueShows the chips under the trigger.
maxHeightnumber400Height cap on the whole panel, in px.
disabledbooleanfalseDims the trigger and locks its chips.
virtualizedbooleanfalseReserved for long lists. Has no effect yet.
@change(value: SelectionOutput) => void—Fires with the new selection on every tick.
@open / @close() => void—When the panel opens or closes.

Tokens

TokenValueWhere it lands
--radius-xl10pxTrigger and search corners.
--radius-lg8pxPanel corners.
--radius-md6pxRow corners.
--color-border-default#E6E6E6Borders at rest, and the panel dividers.
--color-grey-800#7F7D83Trigger border on hover, and chevrons.
--color-grey-200#F1F1F1Trigger fill on hover.
--color-grey-100#F5F5F5Row fill on hover.
--color-primary-active#1877F2Open border and keyboard focus ring.
--color-primary-light#EBFAFFSelect all, once everything is selected.
--global-blue-1100#0C296ASelect all text on that fill, 12.75:1 (blue-1000 would be 3.96:1).
--color-grey-1100#1D1C20Row and value text.
(no token)#4F4D55Placeholder and no-match text.
--shadow-dropdown0 4px 12px rgba(0,0,0,.08), …Panel elevation.