Vize

Transfer List

Accessible, unstyled dual-listbox transfer list with typed items, search, and bulk moves.

Package @vizejs/ui/transfer-list
Maturity stable
Own the source vize lib pull transfer-list
Requires collection, composite-navigation, context, controllable-state, id, typeahead
Aliases transfer list, dual listbox, shuttle, list builder
Covers Ant Design Transfer, PrimeVue PickList, MUI Transfer List

Usage

import { TransferList, TransferListRoot, TransferListAction, TransferListEmpty, TransferListItem, TransferListPanel, TransferListSearch } from "@vizejs/ui/transfer-list";

Or copy the source into your project with vize lib pull transfer-list (see Source Distribution).

API

TransferList<T>

Source: src/families/selection/transfer-list/transfer-list-root.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned base id. null and undefined select a deterministic fallback.
items (required) readonly T[] required Every item, in canonical order; the source panel shows items not in the target.
modelValue readonly T[] undefined Controlled target (right-hand) values. undefined selects uncontrolled behavior.
defaultValue readonly T[] [] Initial target values for uncontrolled use and the value restored by reset.
by TransferListBy<T> undefined Compare values by a property key or with a custom equality function.
itemText (item: T) => string undefined Human-readable text used by search and typeahead.
itemDisabled (item: T) => boolean undefined Keep individual items in place.
filter TransferListFilter<T> undefined Search filter. Defaults to an accent- and case-insensitive "contains" match.
sourceQuery string undefined Controlled source search text.
targetQuery string undefined Controlled target search text.
max number Infinity Maximum number of target values.
orderMode TransferListOrderMode "append" append adds moved items at the end; source-order keeps items order.
disabled boolean false Disable every panel, item, and action.
name string undefined Form field name; each target value submits one hidden input.
form string undefined Id of the owning form when rendered outside it.
formValue (item: T) => string undefined Serialize a value for form submission.

Events

Event Payload Description
update:modelValue [value: readonly T[]] Fired when the target list requests a new controlled value.
change [ value: readonly T[], previous: readonly T[], moved: readonly T[], direction: TransferListDirection, nativeEvent: Event | null, ] Fired after a move: next target, previous target, moved items, direction, and the triggering event.
update:sourceQuery [query: string] Fired when the source search text requests a new controlled value.
update:targetQuery [query: string] Fired when the target search text requests a new controlled value.

Slots

Slot Slot props Description
default TransferListSlotState<T> Panels, search fields, and action buttons. Receives both sides and capacity.

Exposed

Member Type Description
moveToSource —
moveToTarget —
reset —
target —

TransferListRoot<T>

Source: src/families/selection/transfer-list/transfer-list-root.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned base id. null and undefined select a deterministic fallback.
items (required) readonly T[] required Every item, in canonical order; the source panel shows items not in the target.
modelValue readonly T[] undefined Controlled target (right-hand) values. undefined selects uncontrolled behavior.
defaultValue readonly T[] [] Initial target values for uncontrolled use and the value restored by reset.
by TransferListBy<T> undefined Compare values by a property key or with a custom equality function.
itemText (item: T) => string undefined Human-readable text used by search and typeahead.
itemDisabled (item: T) => boolean undefined Keep individual items in place.
filter TransferListFilter<T> undefined Search filter. Defaults to an accent- and case-insensitive "contains" match.
sourceQuery string undefined Controlled source search text.
targetQuery string undefined Controlled target search text.
max number Infinity Maximum number of target values.
orderMode TransferListOrderMode "append" append adds moved items at the end; source-order keeps items order.
disabled boolean false Disable every panel, item, and action.
name string undefined Form field name; each target value submits one hidden input.
form string undefined Id of the owning form when rendered outside it.
formValue (item: T) => string undefined Serialize a value for form submission.

Events

Event Payload Description
update:modelValue [value: readonly T[]] Fired when the target list requests a new controlled value.
change [ value: readonly T[], previous: readonly T[], moved: readonly T[], direction: TransferListDirection, nativeEvent: Event | null, ] Fired after a move: next target, previous target, moved items, direction, and the triggering event.
update:sourceQuery [query: string] Fired when the source search text requests a new controlled value.
update:targetQuery [query: string] Fired when the target search text requests a new controlled value.

Slots

Slot Slot props Description
default TransferListSlotState<T> Panels, search fields, and action buttons. Receives both sides and capacity.

Exposed

Member Type Description
target readonly T[] Current target values.
moveToTarget () => readonly T[] Move checked items to the target.
moveToSource () => readonly T[] Move checked items back to the source.
reset () => boolean Restore defaultValue.

TransferListAction

Source: src/families/selection/transfer-list/transfer-list-action.vue

Props

Prop Type Default Description
action (required) TransferListAction required Move checked or all visible items in one direction.
ariaLabel string undefined Accessible name; defaults to an English description of the action.

Slots

Slot Slot props Description
default { readonly enabled: boolean } Button content such as an arrow icon. Receives availability.

TransferListEmpty

Source: src/families/selection/transfer-list/transfer-list-empty.vue

Props

Prop Type Default Description
side (required) TransferListSide required Panel whose emptiness this message reports.

Slots

Slot Slot props Description
default { readonly query: string; readonly filtered: boolean } Message shown while the panel has no visible items. Receives the search text.

TransferListItem<T>

Source: src/families/selection/transfer-list/transfer-list-item.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned option id. null and undefined select a deterministic fallback.
value (required) T required Item value from the panel's items.
textValue string undefined Typeahead text; defaults to the root itemText.

Slots

Slot Slot props Description
default TransferListItemSlotState<T> Item content. Receives checked, active, and disabled state.

Exposed

Member Type Description
checked —
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.

TransferListPanel

Source: src/families/selection/transfer-list/transfer-list-panel.vue

Props

Prop Type Default Description
side (required) TransferListSide required Which list this panel shows: available (source) or chosen (target) items.
ariaLabel string undefined Accessible name, e.g. "Available" or "Selected".
ariaLabelledby string undefined Space-separated ids of a visible panel heading.

Slots

Slot Slot props Description
default TransferListPanelSlotState<unknown> Render one TransferListItem per visible item. Values are untyped here; the root slot exposes the same lists typed as T.

TransferListSearch

Source: src/families/selection/transfer-list/transfer-list-search.vue

Props

Prop Type Default Description
side (required) TransferListSide required Panel this field filters.
placeholder string undefined Hint text shown while empty.
ariaLabel string undefined Accessible name, e.g. "Search available".

Behavior

Contract

TransferList is a headless, strongly typed dual listbox. transfer-list-root.vue is generic over the item type T: items holds every item, v-model holds the target (right-hand) values as readonly T[], and the source panel shows the rest. transfer-list-panel.vue renders one multiselectable role="listbox" per side with active-descendant navigation and typeahead from the shared collection registry and composite navigation. transfer-list-item.vue renders role="option" where aria-selected means "checked for moving". transfer-list-search.vue filters one panel, transfer-list-action.vue moves checked or all visible items, and transfer-list-empty.vue reports an empty panel. Named lists submit one hidden input per target value. No CSS ships.

Normative Behavior

# State Input Outcome Proven by
T1 any render two multiselectable listboxes split items by the target model; hidden inputs mirror the target renders two multiselect listboxes that split items by the target model
T2 source click items / "Add selected" toggles checked state (never for disabled items), moves checked items, emits change(value, previous, moved, direction, event) clicking checks items and the selected action moves them, emitting the move
T3 source-order move / "Add all" / "Remove all" keeps canonical order, skips disabled items, disables the action when nothing can move source-order mode keeps canonical order and move-all skips disabled items
T4 max "Add all" moves only up to max, publishes data-full, disables further adds max caps the target and disables moving further items
T5 search type / Escape / ArrowDown filters one panel accent-insensitively, move-all moves only visible items, empty state distinguishes filtering, Escape clears, ArrowDown enters the panel search filters one panel accent-insensitively and drives the empty state
T6 panel focused arrows / Home / Space / Shift+Arrow / Ctrl+A / Enter navigates skipping disabled items, toggles, extends checks, checks all visible, moves checked (or the active item); the highlight recovers to a neighbour keyboard: navigation, Space toggles, Shift+Arrow extends, Ctrl+A, Enter moves
T7 any double-click / printable key moves one item; typeahead highlights by text double-click moves an item and typeahead finds items by text
T8 controlled move emits and waits for the parent controlled target waits for the parent
T9 disabled any panels leave the tab order; items, actions, and search are inert disabled transfer lists block every interaction
T10 any exposed API moveToTarget, moveToSource, reset share state exposed methods move checked items
T11 no provider mount a part throws VIZE_UI_CONTEXT_MISSING parts require a TransferList provider
T12 pure helper transferItems respects max, order modes, and direction transferItems respects max, order modes, and direction

SSR

Panel ids derive from the root id; markup is byte-identical across isolated requests and hydrates without warnings (renders byte-identical TransferList markup across isolated SSR requests, hydrates TransferList without mismatches or node replacement).